;;; ------------------------------------------------------------
;;; AutoCATS ¸®½À ÀÚ·á½Ç
;; ¸í·É: TCASE
;; ±â´É: ¼±ÅÃÇÑ TEXT ¹× MTEXTÀÇ ¿µ¹® ´ë¼Ò¹®ÀÚ ÀÏ°ý º¯È¯
;; ÃâÃ³: https://www.autocats.co.kr/lisp/text-case
;; ¹öÀü: 1.0 (2026-07-27)
;; ¶óÀÌ¼±½º: ÀÚÀ¯ »ç¿ë¡¤¼öÁ¤, Àç¹èÆ÷ ½Ã ÃâÃ³(autocats.co.kr) Ç¥±â
;; ¾ÈÀü: *error* ÇÚµé·¯ + UNDO ±×·ì, Àá±ä ·¹ÀÌ¾î °Ç³Ê¶Ü
;;; ------------------------------------------------------------

(vl-load-com)

(defun autocats-tcase-letter-p (char)
  (/= (strcase char) (strcase char T)))

(defun autocats-tcase-toggle (value / idx char result)
  (setq idx 1 result "")
  (while (<= idx (strlen value))
    (setq char (substr value idx 1)
          result
          (strcat result
            (if (autocats-tcase-letter-p char)
              (if (= char (strcase char))
                (strcase char T)
                (strcase char))
              char))
          idx (1+ idx)))
  result)

(defun autocats-tcase-title (value / idx char word-start result)
  (setq idx 1 word-start T result "")
  (while (<= idx (strlen value))
    (setq char (substr value idx 1))
    (cond
      ((autocats-tcase-letter-p char)
       (setq result (strcat result (strcase char (not word-start)))
             word-start nil))
      ((wcmatch char "#")
       (setq result (strcat result char)
             word-start nil))
      (T
       (setq result (strcat result char)
             word-start T)))
    (setq idx (1+ idx)))
  result)

(defun autocats-tcase-convert (value mode)
  (cond
    ((= mode "U") (strcase value))
    ((= mode "L") (strcase value T))
    ((= mode "T") (autocats-tcase-title value))
    ((= mode "G") (autocats-tcase-toggle value))
    (T nil)))

(defun autocats-tcase-locked-p (ent / row)
  (setq row (tblsearch "LAYER" (cdr (assoc 8 (entget ent)))))
  (and row (= 4 (logand 4 (cdr (assoc 70 row))))))

(defun autocats-tcase-apply (ent mode / data converted updated)
  (setq data (entget ent))
  (if (assoc 1 data)
    (progn
      (setq converted
            (mapcar
              '(lambda (pair)
                 (if (member (car pair) '(1 3))
                   (cons (car pair)
                     (autocats-tcase-convert (cdr pair) mode))
                   pair))
              data)
            updated (entmod converted))
      (if updated (progn (entupd ent) T) nil))
    nil))

(defun c:TCASE (/ *error* doc undo-open mode ss idx ent changed skipped)
  (defun *error* (msg)
    (if undo-open
      (progn (vla-EndUndoMark doc) (setq undo-open nil)))
    (if (and msg (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*EXIT*,*Ãë¼Ò*")))
      (princ (strcat "\n[TCASE] Áß´Ü: " msg)))
    (princ))

  (initget "Upper Lower Title toGgle")
  (setq mode (getkword "\n[TCASE] º¯È¯ [Upper/Lower/Title/toGgle] <Upper>: "))
  (setq mode
        (cond
          ((or (null mode) (= mode "Upper")) "U")
          ((= mode "Lower") "L")
          ((= mode "Title") "T")
          (T "G")))
  (princ "\n[TCASE] º¯È¯ÇÒ TEXT ¶Ç´Â MTEXT¸¦ ¼±ÅÃÇÏ¼¼¿ä.")
  (setq ss (ssget '((0 . "TEXT,MTEXT"))))
  (if ss
    (progn
      (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))
            idx 0 changed 0 skipped 0)
      (vla-StartUndoMark doc)
      (setq undo-open T)
      (while (< idx (sslength ss))
        (setq ent (ssname ss idx))
        (if (or (autocats-tcase-locked-p ent)
                (not (autocats-tcase-apply ent mode)))
          (setq skipped (1+ skipped))
          (setq changed (1+ changed)))
        (setq idx (1+ idx)))
      (vla-EndUndoMark doc)
      (setq undo-open nil)
      (princ (strcat "\n[TCASE] ¿Ï·á: " (itoa changed)
                     "°³ º¯°æ / " (itoa skipped) "°³ °Ç³Ê¶Ü")))
    (princ "\n[TCASE] ¼±ÅÃµÈ ¹®ÀÚ°¡ ¾ø½À´Ï´Ù."))
  (princ))

(princ "\n[AutoCATS] TCASE ·Îµå ¿Ï·á - ¸í·ÉÇà¿¡ TCASE ¸¦ ÀÔ·ÂÇÏ¼¼¿ä.")
(princ)
