;;; ------------------------------------------------------------
;;; AutoCATS ¸®½À ÀÚ·á½Ç
;; ¸í·É: MOFFSET
;; ±â´É: ÇÏ³ªÀÇ °î¼±À» ¿©·¯ °Å¸®¸¸Å­ °°Àº ¹æÇâÀ¸·Î ÀÏ°ý OFFSET
;; ÃâÃ³: https://www.autocats.co.kr/lisp/multiple-offset
;; ¹öÀü: 1.0 (2026-07-23)
;; ¶óÀÌ¼±½º: ÀÚÀ¯ »ç¿ë¡¤¼öÁ¤, Àç¹èÆ÷ ½Ã ÃâÃ³(autocats.co.kr) Ç¥±â
;; ¾ÈÀü: *error* ÇÚµé·¯ + UNDO ±×·ì, Àß¸øµÈ °Å¸® ¹× Àá±ä ·¹ÀÌ¾î Â÷´Ü
;;; ------------------------------------------------------------

(vl-load-com)

(defun autocats-moffset-split (value / result start position)
  (setq result '() start 0)
  (while (setq position (vl-string-search "," value start))
    (setq result (append result (list (substr value (1+ start) (- position start))))
          start (1+ position)))
  (append result (list (substr value (1+ start)))))

(defun autocats-moffset-distances (value / tokens output token number invalid)
  (setq tokens (autocats-moffset-split value)
        output '()
        invalid nil)
  (foreach token tokens
    (setq token (vl-string-trim " \t" token)
          number (if (/= token "") (distof token 2) nil))
    (if (or (null number) (<= number 0.0))
      (setq invalid T)
      (if (not (member number output))
        (setq output (append output (list number))))))
  (if (or invalid (null output)) nil output))

(defun autocats-moffset-locked-p (ent / row)
  (setq row (tblsearch "LAYER" (cdr (assoc 8 (entget ent)))))
  (and row (= 4 (logand 4 (cdr (assoc 70 row))))))

(defun autocats-moffset-run (ent distances side / distance before result count)
  (setq count 0)
  (foreach distance distances
    (setq before (entlast)
          result
          (vl-catch-all-apply
            '(lambda ()
               (command "_.OFFSET" distance ent side "")
               T)))
    (if (and (not (vl-catch-all-error-p result))
             (not (equal before (entlast))))
      (setq count (1+ count))))
  count)

(defun c:MOFFSET (/ *error* doc undo-open oldecho picked ent raw distances side count)
  (defun *error* (msg)
    (if undo-open
      (progn (vla-EndUndoMark doc) (setq undo-open nil)))
    (if oldecho (setvar "CMDECHO" oldecho))
    (if (and msg (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*EXIT*,*Ãë¼Ò*")))
      (princ (strcat "\n[MOFFSET] Áß´Ü: " msg)))
    (princ))

  (setq picked (entsel "\n[MOFFSET] OFFSETÇÒ °î¼±À» ¼±ÅÃÇÏ¼¼¿ä: ")
        ent (if picked (car picked) nil))
  (if (null ent)
    (princ "\n[MOFFSET] °î¼±À» ¼±ÅÃÇÏÁö ¾Ê¾Ò½À´Ï´Ù.")
    (if (autocats-moffset-locked-p ent)
      (princ "\n[MOFFSET] Àá±ä ·¹ÀÌ¾îÀÇ °´Ã¼´Â ¼öÁ¤ÇÒ ¼ö ¾ø½À´Ï´Ù.")
      (progn
        (setq raw (getstring T "\nOFFSET °Å¸®µéÀ» ½°Ç¥·Î ÀÔ·Â <¿¹: 100,200,300>: ")
              distances (autocats-moffset-distances raw))
        (if (null distances)
          (princ "\n[MOFFSET] 0º¸´Ù Å« ¼ýÀÚ¸¦ ½°Ç¥·Î ±¸ºÐÇØ ÀÔ·ÂÇØ¾ß ÇÕ´Ï´Ù.")
          (progn
            (setq side (getpoint "\nOFFSET ¹æÇâÀ» ÁöÁ¤ÇÒ Á¡: "))
            (if side
              (progn
                (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))
                      oldecho (getvar "CMDECHO"))
                (setvar "CMDECHO" 0)
                (vla-StartUndoMark doc)
                (setq undo-open T
                      count (autocats-moffset-run ent distances side))
                (vla-EndUndoMark doc)
                (setq undo-open nil)
                (setvar "CMDECHO" oldecho)
                (setq oldecho nil)
                (princ (strcat "\n[MOFFSET] " (itoa count)
                               "°³ OFFSET »ý¼º ¿Ï·á. (Áßº¹ °Å¸®´Â ÇÑ ¹ø¸¸ Ã³¸®)")))))))))
  (princ))

(princ "\n[AutoCATS] MOFFSET ·Îµå ¿Ï·á - ¸í·ÉÇà¿¡ MOFFSET ¸¦ ÀÔ·ÂÇÏ¼¼¿ä.")
(princ)
