;;; ============================================================
;;; DMT v35 - dmt_full.lsp
;;; Urun: DMT
;;; Dagitim dosyasi: dmt_full.lsp
;;; Bu dosya v35 tek dosya surumudur.
;;; Production / user package
;;; Moduler kaynaklardan uretilmistir.
;;; ============================================================

(vl-load-com)

;;; ===================== ActiveX Core Helpers =====================
(defun _DmtCurrentDoc ()
  (vla-get-ActiveDocument (vlax-get-acad-object))
)

(defun _DmtCurrentSpace ()
  (if (= (getvar "CVPORT") 1)
    (vla-get-PaperSpace (_DmtCurrentDoc))
    (vla-get-ModelSpace (_DmtCurrentDoc))
  )
)

(defun _DmtStartUndo ()
  (vla-StartUndoMark (_DmtCurrentDoc))
)

(defun _DmtEndUndo ()
  (vla-EndUndoMark (_DmtCurrentDoc))
)

;;; ===================== Error Handling =====================
(setq _dmt_old_error nil)
(setq _dmt_old_osmode nil)
(setq _dmt_old_cmdecho nil)

(defun _DmtErrorHandler (msg)
  (if (or (= (strcase msg) "FUNCTION CANCELLED")
          (= (strcase msg) "QUIT / EXIT ABORT")
          (vl-string-search "CANCEL" (strcase msg)))
    (princ "\n[DMT] Islem kullanici tarafindan iptal edildi.")
    (princ (strcat "\n[DMT] Beklenmeyen Hata: " msg))
  )
  
  (vl-catch-all-apply '_DmtEndUndo '())
  (if _dmt_old_osmode (setvar "osmode" _dmt_old_osmode))
  (if _dmt_old_cmdecho (setvar "cmdecho" _dmt_old_cmdecho))
  
  (setq *error* _dmt_old_error)
  (princ)
)

(defun _DmtInitSafeMode ()
  (setq _dmt_old_error *error*
        *error* _DmtErrorHandler
        _dmt_old_osmode (getvar "osmode")
        _dmt_old_cmdecho (getvar "cmdecho"))
  (setvar "cmdecho" 0)
)

(defun _DmtRestoreSafeMode ()
  (if _dmt_old_osmode (setvar "osmode" _dmt_old_osmode))
  (if _dmt_old_cmdecho (setvar "cmdecho" _dmt_old_cmdecho))
  (if _dmt_old_error (setq *error* _dmt_old_error))
)
;;; ================================================================;;; ============================================================
;;; DMT v35 - dmt_core.lsp
;;; Altyapi: string, sayi, format, CSV escape, loglama
;;; Entity erisimi YOKTUR. Tum moduller bunu kullanir.
;;; ============================================================

;;; --- Version ---
(setq DMT_VERSION "35")

;;; --- Global log ---
(setq DMT_LOG nil)

;;; --- Sabitleri ---
(setq DMT_XDATA_APP   "DMETRAJ")
(setq DMT_NOD_DICT_NAME "DMETRAJ")
(setq DMT_MAP_XREC_KEY "MAPPING")
(setq DMT_DONE_XREC_KEY "DONE_HANDLES")
(setq DMT_MAP_STORE_VERSION "1")
(setq DMT_MARK_LAYER  "hakedis")
(setq DMT_LAYER_COLOR 3)
(setq DMT_CIRCLE_COLOR 3)
(setq DMT_TEXT_COLOR   7)
(setq DMT_DCL_FILE    "dmt.dcl")
(setq DMT_KNTRL_DEFAULT_ZOOM 500.0)
(setq DMT_ACTIVE_KIRIS_KOLON "")
(if (not (boundp 'DMT_BASE_DIR))
  (setq DMT_BASE_DIR "")
)
(cond
  ((and (boundp '*LOAD-TRUENAME*) *LOAD-TRUENAME*)
   (setq DMT_BASE_DIR (vl-filename-directory *LOAD-TRUENAME*)))
  ((and (boundp '*LOAD-PATHNAME*) *LOAD-PATHNAME*)
   (setq DMT_BASE_DIR (vl-filename-directory *LOAD-PATHNAME*)))
)

;;; --- Varsayilan ayarlar (setenv ile degisir) ---
(setq DMT_MARK_SIZE_MODE    "MANUEL")
(setq DMT_CIRCLE_DIAM       100.0)
(setq DMT_PAPER_CIRCLE_DIAM 8.0)
(setq DMT_CSV_DEC_SEP       ",")
(setq DMT_SORT_MODE         "Y_DESC_X_ASC")
(setq DMT_SORT_MODE_KEYS
  (list "Y_DESC" "Y_ASC" "X_ASC" "X_DESC" "Y_DESC_X_ASC" "X_ASC_Y_DESC")
)
(setq DMT_SORT_MODE_LABELS
  (list
    "ustten alta"
    "alttan uste"
    "soldan saga"
    "sagdan sola"
    "ust-alt sonra sol-sag"
    "sol-sag sonra ust-alt"
  )
)

;;; --- Mapping field listesi ---
(setq DMT_MAP_FIELDS
  (list "POZ" "CAP" "ADET" "BOY" "CARPAN" "KONUM" "EK1" "EK2" "EK3")
)

;;; ===================== String utilities =====================

(defun _s (x) (if x x ""))

(defun _Trim (s) (vl-string-trim " \t\r\n" (_s s)))

(defun _ReplaceAll (s a b / p)
  (setq s (_s s))
  (while (setq p (vl-string-search a s))
    (setq s (strcat (substr s 1 p) b (substr s (+ p (strlen a) 1))))
  )
  s
)

(defun _CleanVal (s)
  (setq s (_s s))
  (setq s (_ReplaceAll s "\r" " "))
  (setq s (_ReplaceAll s "\n" " "))
  s
)

(defun _CollapseSpaces (s)
  (setq s (_s s))
  (while (vl-string-search "  " s)
    (setq s (_ReplaceAll s "  " " "))
  )
  (_Trim s)
)

(defun _PadR (s n)
  (setq s (_s s))
  (while (< (strlen s) n) (setq s (strcat s " ")))
  (substr s 1 n)
)

(defun _TruncStr (s n)
  (setq s (_s s))
  (if (> (strlen s) n) (substr s 1 n) s)
)

(defun _JoinStrList (lst sep / cleaned)
  (setq cleaned 
    (vl-remove-if '(lambda (x) (= x ""))
      (mapcar '(lambda (x) (_Trim (_s x))) lst)
    )
  )
  (if cleaned
    (substr (apply 'strcat (mapcar '(lambda (x) (strcat sep x)) cleaned)) (1+ (strlen sep)))
    ""
  )
)

;;; ===================== Number utilities =====================

(defun _HasDigit (s) (wcmatch (_s s) "*[0-9]*"))

(defun _DmtDigitCharP (ch)
  (and (= (type ch) 'STR)
       (= (strlen ch) 1)
       (wcmatch ch "#"))
)

(defun _DmtFirstNumberToken (s / i n ch nextCh token started hasDot hasDigit)
  ;; COM/RegExp bagimliligi olmadan ilk sayisal parcayi ayikla.
  ;; Ornekler: "L=140.5" -> "140.5", "12mm" -> "12", ",75" -> "0.75"
  (setq s (_ReplaceAll (_s s) "," "."))
  (setq i 1
        n (strlen s)
        token ""
        started nil
        hasDot nil
        hasDigit nil)
  (while (<= i n)
    (setq ch (substr s i 1))
    (cond
      ((not started)
       (cond
         ((_DmtDigitCharP ch)
          (setq token ch started T hasDigit T))
         ((or (= ch "-") (= ch "+"))
          (if (< i n)
            (progn
              (setq nextCh (substr s (1+ i) 1))
              (if (or (_DmtDigitCharP nextCh) (= nextCh "."))
                (setq token ch started T)
              )
            )
          )
         )
         ((= ch ".")
          (if (< i n)
            (progn
              (setq nextCh (substr s (1+ i) 1))
              (if (_DmtDigitCharP nextCh)
                (setq token "0." started T hasDot T)
              )
            )
          )
         )
       )
      )
      (T
       (cond
         ((_DmtDigitCharP ch)
          (setq token (strcat token ch) hasDigit T))
         ((and (= ch ".") (not hasDot))
          (setq token (strcat token ch) hasDot T))
         (T
          (setq i (1+ n)))
       )
      )
    )
    (setq i (1+ i))
  )
  (if hasDigit token nil)
)

(defun _NumFromStr (s / token)
  (setq token (_DmtFirstNumberToken s))
  (if token (atof token) nil)
)

(defun _ToRealDef (s def / v)
  (setq v (_NumFromStr (_Trim (_s s))))
  (if v v def)
)

(defun _FormatNum (x / s)
  (if (= x (fix x))
    (itoa (fix x))
    (progn
      (setq s (rtos x 2 4))
      (while (and (> (strlen s) 0) (= (substr s (strlen s) 1) "0"))
        (setq s (substr s 1 (1- (strlen s)))))
      (if (and (> (strlen s) 0) (= (substr s (strlen s) 1) "."))
        (setq s (substr s 1 (1- (strlen s)))))
      s
    )
  )
)

(defun _FormatNumCsv (x / s)
  (setq s (_FormatNum x))
  (if (= DMT_CSV_DEC_SEP ",")
    (_ReplaceAll s "." ",")
    s
  )
)

(defun _NumToStrCsv (x)
  (if (null x) ""
    (if (= x (fix x)) (itoa (fix x)) (_FormatNumCsv x))
  )
)

;;; ===================== CSV escape =====================

(defun _csvEsc (s)
  (setq s (_ReplaceAll (_CleanVal (_s s)) "\"" "\"\""))
  (strcat "\"" s "\"")
)

(defun _csvNum (s)
  (setq s (_CleanVal (_s s)))
  (setq s (_ReplaceAll s "\"" ""))
  s
)

(defun _csvLine (cells / cList)
  (if (null cells)
    ""
    (progn
      (setq cList (mapcar '(lambda (c) (_csvEsc (_s c))) cells))
      (substr (apply 'strcat (mapcar '(lambda (x) (strcat "," x)) cList)) 2)
    )
  )
)

;;; ===================== Loglama =====================

(defun _DmtLog (level context message)
  (setq DMT_LOG
    (append DMT_LOG (list (list (_s level) (_s context) (_s message))))
  )
  (princ (strcat "\n[" level "] " context " " message))
)

(defun _DmtLogClear ()
  (setq DMT_LOG nil)
)

(defun _DmtLogCountByLevel (level / n entry)
  (setq n 0)
  (foreach entry DMT_LOG
    (if (= (strcase (car entry)) (strcase level))
      (setq n (1+ n)))
  )
  n
)

(defun _DmtLogFormatEntry (entry)
  (strcat (_PadR (car entry) 6) (_PadR (cadr entry) 12) (caddr entry))
)

(defun _DmtLogSaveToFile ( / path fh entry)
  (setq path (strcat
    (getvar "DWGPREFIX")
    (vl-filename-base (getvar "DWGNAME"))
    "_DMTLOG.txt"
  ))
  (setq fh (open path "w"))
  (if fh
    (progn
      (write-line (strcat "DMT Log - v" DMT_VERSION) fh)
      (write-line (strcat "Toplam: " (itoa (length DMT_LOG))
                          " (WARN:" (itoa (_DmtLogCountByLevel "WARN"))
                          " ERROR:" (itoa (_DmtLogCountByLevel "ERROR")) ")") fh)
      (write-line "---" fh)
      (foreach entry DMT_LOG
        (write-line (_DmtLogFormatEntry entry) fh)
      )
      (close fh)
      path
    )
    nil
  )
)

;;; ===================== Platform-safe dosya/klasor acma =====================

;;; ===================== Platform-safe dosya/klasor acma =====================

(defun _DmtQuoteArg (s)
  (strcat "\"" (_ReplaceAll (_s s) "\"" "\"\"") "\"")
)

(defun _DmtSafeStartApp (target / q r)
  ;; Platform-safe dosya/klasor acma.
  ;; Windows'ta yolu quote ederek ac.
  (setq q (_DmtQuoteArg target))
  (setq r (vl-catch-all-apply 'startapp (list "explorer.exe" q)))
  (if (vl-catch-all-error-p r)
    (progn
      (setq r (vl-catch-all-apply 'startapp (list "cmd.exe" (strcat "/c start \"\" " q))))
      (if (vl-catch-all-error-p r)
        (progn
          (setq r (vl-catch-all-apply 'startapp (list (_s target))))
          (if (vl-catch-all-error-p r)
            (progn
              (princ (strcat "\nDosya/klasor acilamadi: " (_s target)))
              nil
            )
            T
          )
        )
        T
      )
    )
    T
  )
)

(defun _DmtOpenFolderForFile (filePath / path dir q r)
  (setq path (_s filePath))
  (setq dir (vl-filename-directory path))
  (setq q (_DmtQuoteArg path))
  (setq r (vl-catch-all-apply 'startapp (list "explorer.exe" (strcat "/select," q))))
  (if (vl-catch-all-error-p r)
    (if (and dir (/= dir ""))
      (_DmtSafeStartApp dir)
      (_DmtSafeStartApp path)
    )
    T
  )
)

(defun _DmtSortModeIndex ( / idx i key)
  (setq idx 0 i 0)
  (foreach key DMT_SORT_MODE_KEYS
    (if (= (strcase (_s key)) (strcase (_s DMT_SORT_MODE)))
      (setq idx i))
    (setq i (1+ i))
  )
  idx
)

(defun _DmtSortModeLabel ( / idx)
  (setq idx (_DmtSortModeIndex))
  (if (and (>= idx 0) (< idx (length DMT_SORT_MODE_LABELS)))
    (nth idx DMT_SORT_MODE_LABELS)
    (car DMT_SORT_MODE_LABELS)
  )
)

;;; ===================== Command-line sonuc ozeti =====================

(defun _DmtPrintResultSummary (command written skipped warnings errors csvPath)
  ;; DCL olmadan da sonucu gostermek icin command-line ozet
  (princ "\n--- DMTPRO Islem Sonucu ---")
  (princ (strcat "\nKomut:    " (_s command)))
  (princ (strcat "\nYazilan:  " (itoa written)))
  (princ (strcat "\nAtlanan:  " (itoa skipped)))
  (princ (strcat "\nUyari:    " (itoa warnings)))
  (princ (strcat "\nHata:     " (itoa errors)))
  (princ (strcat "\nCSV:      " (_s csvPath)))
  (princ "\n------------------------")
)

;;; ===================== Command-line log dump =====================

(defun _DmtPrintLogSummary ( / entry shown)
  ;; DMT_LOG icerigini command line'a yaz (DCL fallback)
  (if (null DMT_LOG)
    (princ "\nLog bos.")
    (progn
      (princ (strcat "\n--- DMT Log (" (itoa (length DMT_LOG)) " kayit) ---"))
      (setq shown 0)
      (foreach entry DMT_LOG
        (if (< shown 50)
          (progn
            (princ (strcat "\n" (_DmtLogFormatEntry entry)))
            (setq shown (1+ shown))
          )
        )
      )
      (if (> (length DMT_LOG) 50)
        (princ (strcat "\n... ve " (itoa (- (length DMT_LOG) 50)) " kayit daha."))
      )
      (princ "\n------------------------")
    )
  )
)

(princ)

;;; ============================================================
;;; DMT v35 - dmt_entity.lsp
;;; Entity erisim katmani: attrib okuma, EffectiveName, XDATA
;;; Bu modul disinda entget/entnext/vla-get-* cagrilmaz.
;;; ============================================================

;;; ===================== Attribute okuma =====================

(defun _GetAttribAlist (ins / al e ed tag val)
  ;; INSERT entity'sinden attribute tag-value alist doner
  (setq al '() e (entnext ins))
  (while e
    (setq ed (entget e))
    (cond
      ((= (cdr (assoc 0 ed)) "ATTRIB")
       (setq tag (strcase (_s (cdr (assoc 2 ed)))))
       (setq val (_s (cdr (assoc 1 ed))))
       (setq al (cons (cons tag val) al)))
      ((= (cdr (assoc 0 ed)) "SEQEND")
       (setq e nil))
    )
    (if e (setq e (entnext e)))
  )
  (reverse al)
)

(defun _AlGet (al tag / p)
  ;; alist icinden tag degerini oku
  (setq p (assoc (strcase (_s tag)) al))
  (if p (cdr p) "")
)

(defun _AlGetAny (al tags / v tg)
  ;; Birden fazla tag dene, ilk dolu olan degeri dondur
  (setq v "")
  (foreach tg tags
    (if (= v "")
      (progn
        (setq v (_Trim (_AlGet al tg)))
        (if (= v "") (setq v ""))
      )
    )
  )
  v
)

;;; ===================== EffectiveName =====================

(defun _DmtEffName (ins / obj)
  ;; Dynamic block icin gercek adi dondurur
  (setq obj (vlax-ename->vla-object ins))
  (cond
    ((vlax-property-available-p obj 'EffectiveName)
     (strcase (vla-get-EffectiveName obj)))
    ((vlax-property-available-p obj 'Name)
     (strcase (vla-get-Name obj)))
    (T (strcase (_s (cdr (assoc 2 (entget ins))))))
  )
)

;;; ===================== Guvenli okuyucular =====================

(defun _DmtSafeHandle (ins / ed)
  (setq ed (entget ins))
  (_s (cdr (assoc 5 ed)))
)

(defun _DmtSafeBlockName (ins / obj)
  (setq obj (vlax-ename->vla-object ins))
  (strcase (_s (vla-get-Name obj)))
)

(defun _DmtSafeLayer (ins / obj)
  (setq obj (vlax-ename->vla-object ins))
  (_s (vla-get-Layer obj))
)

(defun _DmtSafePoint (ins / obj pt)
  (setq obj (vlax-ename->vla-object ins))
  ;; vlax-get safely returns a native LISP list without variant/safearray wrapper conflicts
  (setq pt (vl-catch-all-apply 'vlax-get (list obj 'InsertionPoint)))
  (if (vl-catch-all-error-p pt)
    '(0.0 0.0 0.0)
    (if (and pt (= (type pt) 'LIST)) pt '(0.0 0.0 0.0))
  )
)

(defun _DmtSafeEffName (ins / obj r)
  (setq obj (vlax-ename->vla-object ins))
  (setq r (vl-catch-all-apply 'vla-get-EffectiveName (list obj)))
  (if (vl-catch-all-error-p r)
    (strcase (_s (vla-get-Name obj)))
    (strcase (_s r))
  )
)

(defun _DmtSafeAttribs (ins / r)
  ;; vl-catch-all-apply ile guvenli attribute okuma
  (setq r (vl-catch-all-apply '_GetAttribAlist (list ins)))
  (if (vl-catch-all-error-p r) nil r)
)

;;; ===================== XDATA yonetimi =====================

(defun _RegApp (app)
  (if (null (tblsearch "APPID" app))
    (entmake (list '(0 . "APPID") (cons 2 app)))
  )
  app
)

;;; ===================== Dictionary / XRecord =====================

(defun _DmtNamedDictGet (dictName / rec)
  (setq rec (dictsearch (namedobjdict) (_s dictName)))
  (if rec (cdr (assoc -1 rec)) nil)
)

(defun _DmtNamedDictEnsure (dictName / dictE)
  (setq dictE (_DmtNamedDictGet dictName))
  (if dictE
    dictE
    (progn
      (setq dictE
        (entmakex
          '((0 . "DICTIONARY")
            (100 . "AcDbDictionary"))))
      (if dictE
        (progn
          (dictadd (namedobjdict) (_s dictName) dictE)
          dictE
        )
        nil
      )
    )
  )
)

(defun _DmtDictEntryGet (dictE key / rec)
  (if (and dictE (/= (_s key) ""))
    (progn
      (setq rec (dictsearch dictE (_s key)))
      (if rec (cdr (assoc -1 rec)) nil)
    )
    nil
  )
)

(defun _DmtXrecBuildLineData (lines / out ln)
  (setq out
    (list
      '(0 . "XRECORD")
      '(100 . "AcDbXrecord")
      '(280 . 1)))
  (foreach ln lines
    (setq out (append out (list (cons 300 (_s ln)))))
  )
  out
)

(defun _DmtXrecReadLines (dictName key / dictE xrecE ed out it)
  (setq dictE (_DmtNamedDictGet dictName))
  (if (null dictE)
    nil
    (progn
      (setq xrecE (_DmtDictEntryGet dictE key))
      (if (null xrecE)
        nil
        (progn
          (setq ed (entget xrecE))
          (setq out '())
          (foreach it ed
            (if (or (= (car it) 300) (= (car it) 1))
              (setq out (cons (_s (cdr it)) out))
            )
          )
          (reverse out)
        )
      )
    )
  )
)

(defun _DmtXrecWriteLines (dictName key lines / dictE oldE newE removed)
  (setq dictE (_DmtNamedDictEnsure dictName))
  (if (and dictE (/= (_s key) ""))
    (progn
      (setq oldE (_DmtDictEntryGet dictE key))
      (setq newE (entmakex (_DmtXrecBuildLineData lines)))
      (if newE
        (progn
          (if oldE
            (progn
              (setq removed (dictremove dictE (_s key)))
              (if removed
                (if (dictadd dictE (_s key) newE)
                  (progn
                    (entdel removed)
                    T
                  )
                  (progn
                    (dictadd dictE (_s key) removed)
                    (entdel newE)
                    nil
                  )
                )
                (if (dictadd dictE (_s key) newE)
                  T
                  (progn
                    (entdel newE)
                    nil
                  )
                )
              )
            )
            (if (dictadd dictE (_s key) newE)
              T
              (progn
                (entdel newE)
                nil
              )
            )
          )
        )
        nil
      )
    )
    nil
  )
)

(defun _DmtXrecDelete (dictName key / dictE oldE)
  (setq dictE (_DmtNamedDictGet dictName))
  (if (and dictE (/= (_s key) ""))
    (progn
      (setq oldE (dictremove dictE (_s key)))
      (if oldE
        (progn
          (entdel oldE)
          T
        )
        T
      )
    )
    T
  )
)

(defun _RemoveAppXdata (ed app / out it)
  (setq out '())
  (foreach it ed
    (if (and (= (car it) -3)
             (= (type (cdr it)) 'LIST)
             (= (car (cdr it)) app))
      (progn) ; skip
      (setq out (cons it out))
    )
  )
  (reverse out)
)

(defun _DmtDoneHandle (ins)
  (strcase (_DmtSafeHandle ins))
)

(defun _DmtDoneReadHandles ( / lines out line)
  (setq lines (_DmtXrecReadLines DMT_NOD_DICT_NAME DMT_DONE_XREC_KEY))
  (setq out '())
  (foreach line lines
    (if (/= (_Trim (_s line)) "")
      (setq out (cons (strcase (_Trim (_s line))) out))
    )
  )
  (reverse out)
)

(setq DMT_DONE_CACHE nil)
(setq DMT_DONE_CACHE_LOADED nil)

(defun _DmtDoneWriteHandles (handles)
  (if handles
    (_DmtXrecWriteLines DMT_NOD_DICT_NAME DMT_DONE_XREC_KEY handles)
    (_DmtXrecDelete DMT_NOD_DICT_NAME DMT_DONE_XREC_KEY)
  )
  (setq DMT_DONE_CACHE handles)
  (setq DMT_DONE_CACHE_LOADED T)
)

(defun _DmtDoneAddHandle (ins / h)
  (setq h (_DmtDoneHandle ins))
  (if (/= h "")
    (progn
      (if (not DMT_DONE_CACHE_LOADED)
        (progn
          (setq DMT_DONE_CACHE (_DmtDoneReadHandles))
          (setq DMT_DONE_CACHE_LOADED T)
        )
      )
      (if (not (member h DMT_DONE_CACHE))
        (progn
          (setq DMT_DONE_CACHE (cons h DMT_DONE_CACHE))
          (setq DMT_DONE_CACHE_DIRTY T)
        )
      )
    )
  )
)

(defun _DmtDoneRemoveHandle (ins / h out item)
  (setq h (_DmtDoneHandle ins))
  (if (/= h "")
    (progn
      (if (not DMT_DONE_CACHE_LOADED)
        (progn
          (setq DMT_DONE_CACHE (_DmtDoneReadHandles))
          (setq DMT_DONE_CACHE_LOADED T)
        )
      )
      (setq out '())
      (foreach item DMT_DONE_CACHE
        (if (/= item h)
          (setq out (cons item out))
        )
      )
      (setq DMT_DONE_CACHE (reverse out))
      (setq DMT_DONE_CACHE_DIRTY T)
    )
  )
)

(defun _DmtDoneCommit ()
  (if (_DmtAdvUiModeP)
    nil
    (if DMT_DONE_CACHE_DIRTY
      (progn
        (_DmtDoneWriteHandles DMT_DONE_CACHE)
        (setq DMT_DONE_CACHE_DIRTY nil)
      )
    )
  )
)

(defun _DmtXdataEntgetAppPayload (ed app / payload it body nested)
  ;; entget -3 verisini AutoCAD'in gercek list yapisina gore cozer.
  ;; Beklenen temel bicim: (-3 ("DMETRAJ" (1000 . "DONE") (1070 . 999)))
  (setq payload nil)
  (foreach it ed
    (if (and (null payload) (= (car it) -3) (= (type (cdr it)) 'LIST))
      (progn
        (setq body (cdr it))
        (cond
          ((and (> (length body) 0)
                (= (type (car body)) 'STR)
                (= (strcase (car body)) (strcase app)))
           (setq payload (cdr body)))
          ((and (= (length body) 1)
                (= (type (car body)) 'LIST))
           (setq nested (car body))
           (if (and (> (length nested) 0)
                    (= (type (car nested)) 'STR)
                    (= (strcase (car nested)) (strcase app)))
             (setq payload (cdr nested))
           ))
        )
      )
    )
  )
  payload
)

(defun _DmtXdataSeqFromPairs (pairs / seq pair val)
  (setq seq nil)
  (foreach pair pairs
    (if (and (null seq)
             (= (type pair) 'LIST)
             (= (car pair) 1070))
      (progn
        (setq val (cdr pair))
        (if (and (or (= (type val) 'INT) (= (type val) 'REAL))
                 (> (fix val) 0))
          (setq seq (fix val))
        )
      )
    )
  )
  seq
)

(defun _DmtXdataSeqFromVlaReport (rep / types vals seq tCode val)
  (setq types (cdr (assoc 'TYPES rep)))
  (setq vals (cdr (assoc 'VALUES rep)))
  (setq seq nil)
  (while (and types vals (null seq))
    (setq tCode (car types))
    (setq val (car vals))
    (if (and (or (= (type tCode) 'INT) (= (type tCode) 'REAL))
             (= (fix tCode) 1070)
             (or (= (type val) 'INT) (= (type val) 'REAL))
             (> (fix val) 0))
      (setq seq (fix val))
    )
    (setq types (cdr types))
    (setq vals (cdr vals))
  )
  seq
)

(defun _DmtReadMarkInfo (ins / edAll handle pt vlaRep seq payload source)
  ;; Kanonik mark reader: once VLA GetXData, sonra entget -3 fallback.
  (setq edAll (entget ins '("*")))
  (if edAll
    (progn
      (setq handle (_s (cdr (assoc 5 edAll))))
      (setq pt (cdr (assoc 10 edAll)))
      (if (not (and pt (= (type pt) 'LIST)))
        (setq pt '(0.0 0.0 0.0))
      )
      (setq seq nil source nil)
      (setq vlaRep (_DmtXLabVlaGetReport ins))
      (if (cdr (assoc 'OK vlaRep))
        (progn
          (setq seq (_DmtXdataSeqFromVlaReport vlaRep))
          (if seq (setq source "VLA"))
        )
      )
      (if (null seq)
        (progn
          (setq payload (_DmtXdataEntgetAppPayload edAll DMT_XDATA_APP))
          (setq seq (_DmtXdataSeqFromPairs payload))
          (if seq (setq source "ENTGET-ALL"))
        )
      )
      (if (null seq)
        (progn
          (setq payload (_DmtXdataEntgetAppPayload (entget ins (list DMT_XDATA_APP)) DMT_XDATA_APP))
          (setq seq (_DmtXdataSeqFromPairs payload))
          (if seq (setq source "ENTGET-FILTERED"))
        )
      )
      (if seq
        (list (cons 'SEQ seq)
              (cons 'HANDLE handle)
              (cons 'POINT pt)
              (cons 'SOURCE source))
        nil
      )
    )
    nil
  )
)

(defun _DmtIsMarkedByXdata (ins)
  (if (_DmtReadMarkInfo ins) T nil)
)

(defun _DmtMarkedInfo (ins)
  ;; Tum sistemin kullandigi tek kanonik reader.
  (_DmtReadMarkInfo ins)
)

(defun _DmtMarkedIndex (ins / info)
  (setq info (_DmtReadMarkInfo ins))
  (if info (cdr (assoc 'SEQ info)) nil)
)

(defun _DmtDbgHasAppXdata (ed app)
  (if (_DmtXdataEntgetAppPayload ed app) T nil)
)

(setq DMT_MARKDBG_LAST nil)

(defun _DmtMarkDbgPut (key val / pair)
  (setq pair (assoc key DMT_MARKDBG_LAST))
  (if pair
    (setq DMT_MARKDBG_LAST (subst (cons key val) pair DMT_MARKDBG_LAST))
    (setq DMT_MARKDBG_LAST (cons (cons key val) DMT_MARKDBG_LAST))
  )
  val
)

(defun _DmtLayerLockedP (lname / rec flags)
  (setq rec (tblsearch "LAYER" lname))
  (setq flags (if rec (cdr (assoc 70 rec)) 0))
  (/= 0 (logand flags 4))
)

(defun _DmtBlockFlags (bname / rec)
  (setq rec (tblsearch "BLOCK" bname))
  (if rec (cdr (assoc 70 rec)) 0)
)

(defun _DmtBlockXrefLikeP (bname / flags)
  (setq flags (_DmtBlockFlags bname))
  (or (/= 0 (logand flags 4))
      (/= 0 (logand flags 8))
      (/= 0 (logand flags 16))
      (/= 0 (logand flags 32))
      (/= 0 (logand flags 64)))
)

(defun _DmtBlockDependentP (bname / flags)
  (setq flags (_DmtBlockFlags bname))
  (or (/= 0 (logand flags 16))
      (/= 0 (logand flags 32))
      (/= 0 (logand flags 64)))
)

(defun _DmtBlockAnonymousP (bname / flags)
  (setq flags (_DmtBlockFlags bname))
  (/= 0 (logand flags 1))
)

(defun _DmtDynamicBlockP (ins / obj res)
  (setq obj (vlax-ename->vla-object ins))
  (if (vlax-property-available-p obj 'IsDynamicBlock)
    (progn
      (setq res (vl-catch-all-apply 'vla-get-IsDynamicBlock (list obj)))
      (if (vl-catch-all-error-p res)
        nil
        (= res :vlax-true)
      )
    )
    nil
  )
)

(defun _DmtMarkWriteAllowedReason (ins / ed layer bname)
  (setq ed (entget ins '("*")))
  (setq layer (_s (cdr (assoc 8 ed))))
  (setq bname (_s (cdr (assoc 2 ed))))
  (cond
    ((/= (_s (cdr (assoc 0 ed))) "INSERT") "Hedef entity INSERT degil.")
    ((_DmtLayerLockedP layer) (strcat "Layer locked: " layer))
    ((_DmtBlockXrefLikeP bname) (strcat "Xref/dependent block: " bname))
    (T nil)
  )
)

(defun _DmtClearAppXdataByEntmod (ins app / ed modRes updRes)
  (setq ed (entget ins '("*")))
  (setq ed (_RemoveAppXdata ed app))
  (setq modRes (entmod ed))
  (setq updRes (entupd ins))
  (and modRes (not (_DmtDbgHasAppXdata (entget ins '("*")) app)))
)

(defun _DmtClearAppXdataByVla (ins app / obj typeArr valArr result updRes)
  (setq obj (vlax-ename->vla-object ins))
  (setq typeArr (vlax-make-safearray vlax-vbinteger '(0 . 0)))
  (setq valArr (vlax-make-safearray vlax-vbVariant '(0 . 0)))
  (vlax-safearray-fill typeArr '(1001))
  (vlax-safearray-put-element valArr 0 app)
  (setq result (vl-catch-all-apply 'vla-SetXData (list obj typeArr valArr)))
  (if (vl-catch-all-error-p result)
    nil
    (progn
      (setq updRes (vl-catch-all-apply 'vla-Update (list obj)))
      (not (_DmtDbgHasAppXdata (entget ins '("*")) app))
    )
  )
)

(defun _DmtMarkInsViaVla (ins idx / obj typeArr valArr result updRes errMsg postFiltered postAll postInfo)
  ;; Uretim yolu: COM SetXData + roundtrip verify.
  (_RegApp DMT_XDATA_APP)
  (_DmtMarkDbgPut 'VLA_TYPES "1001,1000,1070")
  (_DmtMarkDbgPut 'VLA_VALUES (strcat DMT_XDATA_APP ",DONE," (itoa (fix idx))))
  (_DmtMarkDbgPut 'VLA_ERROR "")
  (_DmtMarkDbgPut 'VLA_UPDATE_ERROR "")
  (setq obj (vlax-ename->vla-object ins))
  (setq typeArr (vlax-make-safearray vlax-vbinteger '(0 . 2)))
  (setq valArr (vlax-make-safearray vlax-vbVariant '(0 . 2)))
  (vlax-safearray-fill typeArr '(1001 1000 1070))
  (vlax-safearray-put-element valArr 0 DMT_XDATA_APP)
  (vlax-safearray-put-element valArr 1 "DONE")
  (vlax-safearray-put-element valArr 2 (fix idx))
  (setq result (vl-catch-all-apply 'vla-SetXData (list obj typeArr valArr)))
  (if (vl-catch-all-error-p result)
    (progn
      (setq errMsg (vl-catch-all-error-message result))
      (_DmtMarkDbgPut 'VLA_ERROR errMsg)
      (_DmtMarkDbgPut 'ENTUPD_OK nil)
      nil
    )
    (progn
      (setq updRes (vl-catch-all-apply 'vla-Update (list obj)))
      (if (vl-catch-all-error-p updRes)
        (progn
          (_DmtMarkDbgPut 'VLA_UPDATE_ERROR (vl-catch-all-error-message updRes))
          (_DmtMarkDbgPut 'ENTUPD_OK nil)
        )
        (progn
          (_DmtMarkDbgPut 'VLA_UPDATE_ERROR "")
          (_DmtMarkDbgPut 'ENTUPD_OK T)
        )
      )
      (setq postFiltered (_DmtDbgHasAppXdata (entget ins (list DMT_XDATA_APP)) DMT_XDATA_APP))
      (setq postAll (_DmtDbgHasAppXdata (entget ins '("*")) DMT_XDATA_APP))
      (setq postInfo (_DmtMarkedInfo ins))
      (_DmtMarkDbgPut 'POST_FILTERED postFiltered)
      (_DmtMarkDbgPut 'POST_ALL postAll)
      (_DmtMarkDbgPut 'POST_SEQ (if postInfo (cdr (assoc 'SEQ postInfo)) nil))
      (if postInfo T nil)
    )
  )
)

(defun _DmtXLabMaybeVariantValue (v / out)
  (setq out (vl-catch-all-apply 'vlax-variant-value (list v)))
  (if (vl-catch-all-error-p out) v out)
)

(defun _DmtXLabVariantArrayToList (v / raw arr out item)
  (setq raw (_DmtXLabMaybeVariantValue v))
  (setq arr (vl-catch-all-apply 'vlax-safearray->list (list raw)))
  (if (vl-catch-all-error-p arr)
    nil
    (progn
      (setq out '())
      (foreach item arr
        (setq out (append out (list (_DmtXLabMaybeVariantValue item))))
      )
      out
    )
  )
)

(defun _DmtXLabVlaGetReport (ins / obj types vals res)
  ;; Production-safe VLA readback helper.
  ;; dmt_dev.lsp yuklenirse debug/lab komutlari da ayni helper'i kullanir.
  (setq obj (vlax-ename->vla-object ins))
  (setq types nil vals nil)
  (setq res (vl-catch-all-apply 'vla-GetXData (list obj DMT_XDATA_APP 'types 'vals)))
  (if (vl-catch-all-error-p res)
    (list (cons 'OK nil)
          (cons 'ERROR (vl-catch-all-error-message res))
          (cons 'TYPES nil)
          (cons 'VALUES nil))
    (list (cons 'OK T)
          (cons 'ERROR "")
          (cons 'TYPES (_DmtXLabVariantArrayToList types))
          (cons 'VALUES (_DmtXLabVariantArrayToList vals)))
  )
)

(defun _DmtIsMarkedByXrec (ins / h)
  (setq h (_DmtDoneHandle ins))
  (if (= h "")
    nil
    (member h (_DmtDoneReadHandles))
  )
)

(defun _IsMarked (ins)
  (if (_DmtAdvUiModeP)
    nil
    (or (_DmtReadMarkInfo ins) (_DmtIsMarkedByXrec ins)))
)

(defun _MarkIns (ins idx / edAll handle typ space reason finalOk)
  ;; Uretim yolu: once yazilabilirlik kontrolu, sonra yalnizca roundtrip dogrulanmis VLA write.
  (setq edAll (entget ins '("*")))
  (setq handle (_s (cdr (assoc 5 edAll))))
  (setq typ (_s (cdr (assoc 0 edAll))))
  (setq space (_s (cdr (assoc 410 edAll))))
  (_DmtMarkDbgPut 'MARK_HANDLE handle)
  (_DmtMarkDbgPut 'MARK_TYPE typ)
  (_DmtMarkDbgPut 'MARK_410 space)
  (_DmtMarkDbgPut 'MARK_IDX (fix idx))
  (_DmtMarkDbgPut 'PRE_FILTERED (_DmtDbgHasAppXdata (entget ins (list DMT_XDATA_APP)) DMT_XDATA_APP))
  (_DmtMarkDbgPut 'PRE_ALL (_DmtDbgHasAppXdata edAll DMT_XDATA_APP))
  (_RegApp DMT_XDATA_APP)
  (_DmtMarkDbgPut 'REGAPP_OK (if (tblsearch "APPID" DMT_XDATA_APP) T nil))
  (setq reason (_DmtMarkWriteAllowedReason ins))
  (_DmtMarkDbgPut 'WRITE_REASON (if reason reason ""))
  (_DmtMarkDbgPut 'ENTMOD_OK nil)
  (_DmtMarkDbgPut 'ENTUPD_OK nil)
  (_DmtMarkDbgPut 'VLA_FALLBACK nil)
  (_DmtMarkDbgPut 'VLA_TYPES "")
  (_DmtMarkDbgPut 'VLA_VALUES "")
  (_DmtMarkDbgPut 'VLA_ERROR "")
  (_DmtMarkDbgPut 'VLA_UPDATE_ERROR "")
  (_DmtMarkDbgPut 'POST_FILTERED nil)
  (_DmtMarkDbgPut 'POST_ALL nil)
  (_DmtMarkDbgPut 'POST_SEQ nil)
  (_DmtMarkDbgPut 'FINAL_OK nil)
  (if reason
    (progn
      (_DmtLog "WARN" "mark" (strcat "Yazma engellendi h=" handle " : " reason))
      nil
    )
    (progn
      (_DmtMarkDbgPut 'VLA_FALLBACK T)
      (setq finalOk (_DmtMarkInsViaVla ins idx))
      (_DmtMarkDbgPut 'FINAL_OK finalOk)
      (if finalOk
        (_DmtDoneAddHandle ins)
        (_DmtLog "WARN" "mark" (strcat "XDATA yazilamadi h=" handle)))
      finalOk
    )
  )
)

(defun _UnmarkIns (ins / ok)
  ;; Uretim yolu COM oldugu icin remove tarafinda da verify + fallback kullan.
  (setq ok (_DmtClearAppXdataByEntmod ins DMT_XDATA_APP))
  (if (not ok)
    (setq ok (_DmtClearAppXdataByVla ins DMT_XDATA_APP))
  )
  (_DmtDoneRemoveHandle ins)
  (entupd ins)
  ok
)

;;; ===================== Layer yonetimi =====================

(defun _EnsureLayer (lname aci / layObj lays err)
  (setq lays (vla-get-Layers (_DmtCurrentDoc)))
  (setq err (vl-catch-all-apply 'vla-Item (list lays lname)))
  (if (vl-catch-all-error-p err)
    (setq layObj (vla-Add lays lname))
    (setq layObj err)
  )
  (vla-put-color layObj aci)
  lname
)

;;; ===================== Scan record olusturucu =====================

(defun _DmtBuildScanRecord (ins / atts pt)
  ;; Tek INSERT icin scan record uretir
  ;; nil donerse: attribute yok veya hata
  (setq atts (_DmtSafeAttribs ins))
  (if (and atts (> (length atts) 0))
    (progn
      (setq pt (_DmtSafePoint ins))
      (list
        (cons 'ENAME ins)
        (cons 'HANDLE (_DmtSafeHandle ins))
        (cons 'BLOCK_NAME (_DmtSafeBlockName ins))
        (cons 'EFFECTIVE_NAME (_DmtSafeEffName ins))
        (cons 'LAYER (_DmtSafeLayer ins))
        (cons 'X (nth 0 pt))
        (cons 'Y (nth 1 pt))
        (cons 'Z (nth 2 pt))
        (cons 'ATTRIBS atts)
      )
    )
    nil
  )
)

(princ)

;;; ============================================================
;;; DMT v35 - dmt_config.lsp
;;; Mapping yonetimi: XRecord + cfg fallback, validate, auto-suggest
;;; Ayar yonetimi: setenv/getenv
;;; ============================================================

(setq DMT_MAP_DATA        nil)
(setq DMT_MAP_OPTIONS     nil)  ; popup display list: "(bos)" "POZ_NO (342)" ...
(setq DMT_MAP_OPTIONS_KEYS nil) ; paralel key list: "" "POZ_NO" ...
(setq DMT_MAP_CFG_PATH    nil)
(setq DMT_MAP_CAP_WARNED  nil)  ; CAP bos uyarisi gosterildi mi

;;; ===================== cfg dosya islemleri (legacy) =====================

(defun _DmtMapCfgPath ( / p base)
  (setq p (getvar "DWGPREFIX"))
  (if (or (null p) (= p "")) (setq p (getvar "TEMPPREFIX")))
  (setq base (vl-filename-base (getvar "DWGNAME")))
  (strcat p base "_DMTMAP.cfg")
)

(defun _DmtMapCfgExists ( / path)
  (setq path (_DmtMapCfgPath))
  (setq DMT_MAP_CFG_PATH path)
  (findfile path)
)

(defun _DmtMapFindEq (s / i ch pos)
  (setq i 1 pos nil)
  (while (and (<= i (strlen s)) (null pos))
    (if (= (substr s i 1) "=") (setq pos i))
    (setq i (1+ i))
  )
  pos
)

(defun _DmtMapParseCfgLine (line / pos k v)
  (setq line (_Trim (_s line)))
  (if (or (= line "") (= (substr line 1 2) "##"))
    nil
    (progn
      (setq pos (_DmtMapFindEq line))
      (if pos
        (cons
          (strcase (_Trim (substr line 1 (1- pos))))
          (strcase (_Trim (substr line (1+ pos))))
        )
        nil
      )
    )
  )
)

(defun _DmtMapLoadCfg ( / path fh line pair out)
  ;; cfg dosyasini oku, alist dondur
  (setq path (_DmtMapCfgPath))
  (setq DMT_MAP_CFG_PATH path)
  (setq out '())
  (setq fh (open path "r"))
  (if fh
    (progn
      (while (setq line (read-line fh))
        (setq pair (_DmtMapParseCfgLine line))
        (if pair (setq out (cons pair out)))
      )
      (close fh)
      (_DmtLog "INFO" "cfg" (strcat "Yuklendi: " path))
    )
    (_DmtLog "INFO" "cfg" (strcat "Bulunamadi: " path))
  )
  (reverse out)
)

(defun _DmtMapSaveCfg (al / path fh fld)
  ;; alist'i cfg dosyasina yaz
  (setq path (_DmtMapCfgPath))
  (setq DMT_MAP_CFG_PATH path)
  (setq fh (open path "w"))
  (if fh
    (progn
      (write-line (strcat "##VERSION=1") fh)
      (foreach fld DMT_MAP_FIELDS
        (write-line (strcat fld "=" (_s (_DmtMapGet al fld))) fh)
      )
      (close fh)
      path
    )
    nil
  )
)

(defun _DmtMapDeleteCfg ( / path)
  ;; legacy cfg kaydini sil
  (setq path (_DmtMapCfgPath))
  (setq DMT_MAP_CFG_PATH path)
  (if (_DmtMapCfgExists)
    (vl-file-delete path)
    T
  )
)

;;; ===================== Mapping alist helpers =====================

(defun _DmtMapGet (al key / p)
  ;; Mapping alist icinden deger oku
  (setq p (assoc (strcase (_s key)) al))
  (if p (cdr p) "")
)

(defun _DmtMapHasAny (al / ok fld)
  ;; En az bir eslesme var mi
  (setq ok nil)
  (foreach fld DMT_MAP_FIELDS
    (if (/= (_s (_DmtMapGet al fld)) "") (setq ok T))
  )
  ok
)

;;; ===================== Persistence wrappers =====================

(defun _DmtMapLinesToAlist (lines / out line pair)
  (setq out '())
  (foreach line lines
    (setq pair (_DmtMapParseCfgLine line))
    (if pair (setq out (cons pair out)))
  )
  (reverse out)
)

(defun _DmtMapAlistToLines (al / out fld)
  (setq out (list (strcat "##VERSION=" DMT_MAP_STORE_VERSION)))
  (foreach fld DMT_MAP_FIELDS
    (setq out
      (append out (list (strcat fld "=" (_s (_DmtMapGet al fld))))))
  )
  out
)

(defun _DmtMapLoadXRecord ( / lines)
  (setq lines (_DmtXrecReadLines DMT_NOD_DICT_NAME DMT_MAP_XREC_KEY))
  (if lines
    (_DmtMapLinesToAlist lines)
    nil
  )
)

(defun _DmtMapLoad ( / cfgExists xLines cfgData)
  (setq cfgExists (_DmtMapCfgExists))
  (setq xLines (_DmtXrecReadLines DMT_NOD_DICT_NAME DMT_MAP_XREC_KEY))
  (if xLines
    (progn
      (if cfgExists
        (_DmtLog "INFO" "map" "XRecord tercih edildi; cfg yok sayildi.")
        (_DmtLog "INFO" "map" "XRecord yuklendi."))
      (_DmtMapLinesToAlist xLines)
    )
    (progn
      (setq cfgData (_DmtMapLoadCfg))
      (if cfgExists
        (_DmtLog "INFO" "map" "cfg fallback kullanildi."))
      cfgData
    )
  )
)

(defun _DmtMapSave (al / ok)
  (setq ok
    (_DmtXrecWriteLines
      DMT_NOD_DICT_NAME
      DMT_MAP_XREC_KEY
      (_DmtMapAlistToLines al)))
  (if ok
    (_DmtLog "INFO" "map" "XRecord kaydedildi."))
  ok
)

(defun _DmtMapDelete ( / xOk cfgOk)
  (setq xOk (_DmtXrecDelete DMT_NOD_DICT_NAME DMT_MAP_XREC_KEY))
  (setq cfgOk (_DmtMapDeleteCfg))
  (if (and xOk cfgOk)
    (progn
      (_DmtLog "INFO" "map" "Kayitli mapping silindi.")
      T
    )
    (progn
      (_DmtLog "WARN" "map" "Mapping silme islemi kismen basarisiz.")
      nil
    )
  )
)

;;; ===================== Dogrulama =====================

(defun _DmtMapValidate (al)
  ;; Mapping dogrulamasi.
  ;; Doner: nil (OK) veya hata mesaji string
  ;; POZ bos -> engelle. CAP bos -> uyar ama gecilebilir.
  (cond
    ((= (_Trim (_DmtMapGet al "POZ")) "")
     "POZ alani zorunludur. Bir tag secin.")
    (T nil) ; gecerli
  )
)

(defun _DmtMapCapEmpty (al)
  ;; CAP bos mu kontrol
  (= (_Trim (_DmtMapGet al "CAP")) "")
)

;;; ===================== Auto-suggest =====================

(defun _DmtMapAutoSuggest (tagNames / out fld candidates tg found)
  ;; Tag listesi icinde bilinen isimleri ara, oneri alist'i dondur
  ;; tagNames: scan'den gelen tag isimlerinin listesi (strcase)
  (setq out '())
  (foreach fld (list
    (list "POZ"      '("POZ" "POZ_NO" "POZEMIR" "POZ_ADI"))
    (list "CAP"      '("CAP" "CAP_MM" "DONATI_CAPI" "DONATI_CAP"))
    (list "ADET"     '("ADET" "ADET_SAYISI" "MIKTAR"))
    (list "BOY"      '("BOY" "UZUNLUK" "LENGTH" "BOY_CM"))
    (list "CARPAN"   '("CARPAN" "MULTIPLIER" "CARPAN_KATSAYI"))
    (list "KONUM"    '("KONUM" "YER" "LOKASYON" "BOLGE"))
    (list "EK1"      '("EK1" "ALT_UST" "ALTUST" "ALT_UST_BILGI"))
    (list "EK2"      '("EK2" "ILAVE"))
    (list "EK3"      '("EK3" "ACIKLAMA" "ACIK" "NOT" "NOTLAR"))
  )
    (setq candidates (cadr fld))
    (setq found nil)
    (foreach tg candidates
      (if (and (null found) (member (strcase tg) tagNames))
        (setq found (strcase tg))
      )
    )
    (setq out (cons (cons (car fld) (if found found "")) out))
  )
  (reverse out)
)

;;; ===================== Default legacy mapping =====================

(defun _DmtMapDefaultLegacy ()
  ;; LEGACY uyumluluk: identity mapping
  (list
    (cons "POZ" "POZ") (cons "CAP" "CAP") (cons "ADET" "ADET")
    (cons "BOY" "BOY") (cons "CARPAN" "CARPAN") (cons "KONUM" "YER")
    (cons "EK1" "") (cons "EK2" "") (cons "EK3" "")
  )
)

;;; ===================== Ayarlar: setenv / getenv =====================

(defun _DmtSettingsNormalizeSortMode (mode / m)
  (setq m (strcase (_s mode)))
  (cond
    ((= m "") "Y_DESC_X_ASC")
    ((= m "POS") "Y_DESC_X_ASC")
    ((= m "NONE") "Y_DESC_X_ASC")
    ((member m DMT_SORT_MODE_KEYS) m)
    (T "Y_DESC_X_ASC")
  )
)

(defun _DmtSettingsLoad ()
  ;; setenv'den ayarlari oku, yoksa varsayilan kullan
  (setq DMT_MARK_SIZE_MODE
    (if (getenv "DMT_MARK_MODE") (getenv "DMT_MARK_MODE") "MANUEL"))
  (setq DMT_CIRCLE_DIAM
    (if (getenv "DMT_CIRCLE_DIAM") (atof (getenv "DMT_CIRCLE_DIAM")) 100.0))
  (setq DMT_PAPER_CIRCLE_DIAM
    (if (getenv "DMT_PAPER_DIAM") (atof (getenv "DMT_PAPER_DIAM")) 8.0))
  (setq DMT_CSV_DEC_SEP
    (if (getenv "DMT_DEC_SEP") (getenv "DMT_DEC_SEP") ","))
  (setq DMT_SORT_MODE
    (_DmtSettingsNormalizeSortMode (getenv "DMT_SORT_MODE")))
)

(defun _DmtSettingsSave ()
  ;; Ayarlari setenv'ye yaz
  (setenv "DMT_MARK_MODE"   (_s DMT_MARK_SIZE_MODE))
  (setenv "DMT_CIRCLE_DIAM" (_FormatNum DMT_CIRCLE_DIAM))
  (setenv "DMT_PAPER_DIAM"  (_FormatNum DMT_PAPER_CIRCLE_DIAM))
  (setenv "DMT_DEC_SEP"     (_s DMT_CSV_DEC_SEP))
  (setenv "DMT_SORT_MODE"   (_DmtSettingsNormalizeSortMode DMT_SORT_MODE))
)

(defun _GetMarkDiam ( / ds)
  ;; Aktif isaret capini hesapla
  (if (= (strcase (_s DMT_MARK_SIZE_MODE)) "AUTO")
    (progn
      (setq ds (getvar "DIMSCALE"))
      (if (or (null ds) (<= ds 0.0)) (setq ds 1.0))
      (* (float ds) (float DMT_PAPER_CIRCLE_DIAM))
    )
    (float DMT_CIRCLE_DIAM)
  )
)

(princ)

;;; ============================================================
;;; DMT v34 ??? dmt_scan.lsp
;;; Tarama motoru: Model Space INSERT toplama, tag istatistik,
;;; hedef filtreleme, scan cache
;;; ============================================================

(setq DMT_SCAN_DATA      nil)
(setq DMT_SCAN_ERRORS    nil)
(setq DMT_SCAN_COUNT     0)
(setq DMT_SCAN_TAG_STATS nil)
(setq DMT_SCAN_CACHED    nil) ; T ise scan sonucu gecerli

;;; ===================== Model Space taramas =====================

(defun _DmtSsToList (ss / i out)
  (if ss
    (progn
      (setq i (sslength ss) out '())
      (while (> i 0)
        (setq i (1- i))
        (setq out (cons (ssname ss i) out))
      )
      out
    )
  )
)

(defun _DmtScanCollectModelInserts ()
  (_DmtSsToList (ssget "X" '((0 . "INSERT") (410 . "Model"))))
)

(defun _DmtScanPushError (ins msg / h)
  (setq h (_DmtSafeHandle ins))
  (setq DMT_SCAN_ERRORS
    (cons (list (cons 'ENAME ins) (cons 'HANDLE h) (cons 'MESSAGE (_s msg)))
          DMT_SCAN_ERRORS))
)

(defun _DmtScanRun ( / inserts ins item)
  ;; Ana tarama: tum INSERT'leri oku, scan_record listesi olustur
  (setq DMT_SCAN_DATA nil DMT_SCAN_ERRORS nil DMT_SCAN_COUNT 0)
  (setq inserts (_DmtScanCollectModelInserts))
  (foreach ins inserts
    (setq item (vl-catch-all-apply '_DmtBuildScanRecord (list ins)))
    (cond
      ((vl-catch-all-error-p item)
       (_DmtScanPushError ins (vl-catch-all-error-message item)))
      ((and item (= (type item) 'LIST))
       (setq DMT_SCAN_DATA (cons item DMT_SCAN_DATA))
       (setq DMT_SCAN_COUNT (1+ DMT_SCAN_COUNT)))
    )
  )
  (setq DMT_SCAN_DATA (reverse DMT_SCAN_DATA))
  (setq DMT_SCAN_CACHED T)
  DMT_SCAN_DATA
)

(defun _DmtScanEnsure ()
  ;; Cache varsa tekrar tarama, yoksa tara
  (if (not DMT_SCAN_CACHED) (_DmtScanRun))
  DMT_SCAN_DATA
)

(defun _DmtScanInvalidate ()
  ;; Cache'i gecersiz kil (DMTRESET sonrasi vb.)
  (setq DMT_SCAN_CACHED nil)
)

;;; ===================== Tag istatistik =====================

(defun _DmtAddUnique (s lst)
  (if (or (null s) (= (_s s) "")) lst
    (if (member s lst) lst (cons s lst))
  )
)

(defun _DmtAddUniqueLimited (s lst maxn)
  ;; En fazla maxn eleman tut
  (if (or (null s) (= (_Trim (_s s)) "")) lst
    (if (>= (length lst) maxn) lst
      (if (member s lst) lst (cons s lst))
    )
  )
)

(defun _DmtScanFindTagEntry (tag stats / found e)
  (setq found nil)
  (foreach e stats
    (if (= (strcase (_s (cdr (assoc 'TAG e)))) (strcase tag))
      (setq found e))
  )
  found
)

(defun _DmtScanReplaceTagEntry (tag newentry stats / out e)
  (setq out '())
  (foreach e stats
    (if (= (strcase (_s (cdr (assoc 'TAG e)))) (strcase tag))
      (setq out (cons newentry out))
      (setq out (cons e out))
    )
  )
  (reverse out)
)

(defun _DmtScanBuildTagStats ( / stats rec atts bname ename a tag val old new)
  ;; Tag frekans + blok tip + ornek deger istatistigi olustur
  (setq stats '())
  (foreach rec DMT_SCAN_DATA
    (setq bname (_s (cdr (assoc 'BLOCK_NAME rec))))
    (setq ename (_s (cdr (assoc 'EFFECTIVE_NAME rec))))
    (setq atts  (cdr (assoc 'ATTRIBS rec)))
    (foreach a atts
      (setq tag (strcase (_s (car a))))
      (setq val (_s (cdr a)))
      (if (/= tag "")
        (progn
          (setq old (_DmtScanFindTagEntry tag stats))
          (if old
            (progn
              (setq new
                (list
                  (cons 'TAG tag)
                  (cons 'COUNT (1+ (cdr (assoc 'COUNT old))))
                  (cons 'BLOCK_NAMES (_DmtAddUnique bname (cdr (assoc 'BLOCK_NAMES old))))
                  (cons 'EFFECTIVE_NAMES (_DmtAddUnique ename (cdr (assoc 'EFFECTIVE_NAMES old))))
                  (cons 'SAMPLE_VALUES
                    (_DmtAddUniqueLimited val (cdr (assoc 'SAMPLE_VALUES old)) 5))
                )
              )
              (setq stats (_DmtScanReplaceTagEntry tag new stats))
            )
            (setq stats
              (cons
                (list
                  (cons 'TAG tag)
                  (cons 'COUNT 1)
                  (cons 'BLOCK_NAMES (if (/= bname "") (list bname) nil))
                  (cons 'EFFECTIVE_NAMES (if (/= ename "") (list ename) nil))
                  (cons 'SAMPLE_VALUES
                    (if (and val (/= (_Trim val) "")) (list val) nil))
                )
                stats
              )
            )
          )
        )
      )
    )
  )
  ;; Sirala ve kaydet
  (setq DMT_SCAN_TAG_STATS
    (vl-sort stats
      '(lambda (a b)
         (< (strcase (_s (cdr (assoc 'TAG a))))
            (strcase (_s (cdr (assoc 'TAG b)))))
       )
    )
  )
)

(defun _DmtTagStatByName (tag / e found)
  ;; Tek bir tag icin stat record dondur
  (setq found nil)
  (foreach e DMT_SCAN_TAG_STATS
    (if (= (strcase (_s (cdr (assoc 'TAG e)))) (strcase (_s tag)))
      (setq found e))
  )
  found
)

(defun _DmtScanEnsureStats ()
  ;; scan + tag stats ikisi de hazir olsun
  (_DmtScanEnsure)
  (if (null DMT_SCAN_TAG_STATS) (_DmtScanBuildTagStats))
)

;;; ===================== Hedef filtreleme =====================

(defun _DmtFilterTargets (scanData mapData / pozTag targets rec atts pozVal)
  ;; Mapping'e gore hedef kayitlari filtrele:
  ;; POZ eslesmis tag'i dolu olan scan record'lari dondur
  (setq pozTag (strcase (_s (_DmtMapGet mapData "POZ"))))
  (if (= pozTag "")
    nil ; POZ esleme yoksa hedef yok
    (progn
      (setq targets '())
      (foreach rec scanData
        (setq atts (cdr (assoc 'ATTRIBS rec)))
        (setq pozVal (_Trim (_AlGet atts pozTag)))
        (if (/= pozVal "")
          (setq targets (cons rec targets))
        )
      )
      (reverse targets)
    )
  )
)

(defun _DmtScanRecordPoint (rec / x y z en)
  ;; Scan record icin nokta bilgisini oncelikle cache'den, gerekirse entity'den al.
  (setq x (cdr (assoc 'X rec)))
  (setq y (cdr (assoc 'Y rec)))
  (setq z (cdr (assoc 'Z rec)))
  (if (and (or (= (type x) 'INT) (= (type x) 'REAL))
           (or (= (type y) 'INT) (= (type y) 'REAL)))
    (list (float x) (float y)
          (if (or (= (type z) 'INT) (= (type z) 'REAL))
            (float z)
            0.0))
    (progn
      (setq en (cdr (assoc 'ENAME rec)))
      (if en
        (_DmtSafePoint en)
        '(0.0 0.0 0.0))
    )
  )
)

(defun _DmtFilterScanRecordsByArea (scanData p1 p2 mode / rect out rec pt entityBounds keep en)
  ;; Secili alandaki scan record'lari pencere/crossing mantigi ile filtrele.
  ;; Once insertion point kontrol edilir, gerekirse bounding-box fallback kullanilir.
  (setq rect (_DmtKntrlRectBounds p1 p2))
  (setq out '())
  (foreach rec scanData
    (setq pt (_DmtScanRecordPoint rec))
    (setq keep (_DmtKntrlPointInRect pt rect))
    (if (not keep)
      (progn
        (setq en (cdr (assoc 'ENAME rec)))
        (setq entityBounds
          (if en
            (_DmtKntrlEntityBounds en)
            nil))
        (setq keep
          (if entityBounds
            (if (= (_s mode) "_W")
              (_DmtKntrlRectContainsBounds rect entityBounds)
              (_DmtKntrlRectIntersectsBounds rect entityBounds))
            nil))
      )
    )
    (if keep
      (setq out (cons rec out))
    )
  )
  (reverse out)
)

;;; ===================== Siralama ve islenmi filtreleme =====================

(defun _DmtSortHandleLess (a b / ha hb la lb i)
  (setq ha (strcase (_s (cdr (assoc 'HANDLE a)))))
  (setq hb (strcase (_s (cdr (assoc 'HANDLE b)))))
  (setq la (strlen ha))
  (setq lb (strlen hb))
  (cond
    ((< la lb) T)
    ((> la lb) nil)
    (T
      (setq i 1)
      (while (and (<= i la) (= (substr ha i 1) (substr hb i 1)))
        (setq i (1+ i))
      )
      (if (> i la)
        nil
        (< (ascii (substr ha i 1)) (ascii (substr hb i 1)))
      )
    )
  )
)

(defun _DmtSortByPosition (records / mode)
  (setq mode (_DmtSettingsNormalizeSortMode DMT_SORT_MODE))
  (vl-sort records
    '(lambda (a b / ax ay bx by)
       (setq ax (cdr (assoc 'X a)))
       (setq ay (cdr (assoc 'Y a)))
       (setq bx (cdr (assoc 'X b)))
       (setq by (cdr (assoc 'Y b)))
       (cond
         ((= mode "Y_DESC")
          (cond
            ((> ay by) T)
            ((< ay by) nil)
            (T (_DmtSortHandleLess a b))))
         ((= mode "Y_ASC")
          (cond
            ((< ay by) T)
            ((> ay by) nil)
            (T (_DmtSortHandleLess a b))))
         ((= mode "X_ASC")
          (cond
            ((< ax bx) T)
            ((> ax bx) nil)
            (T (_DmtSortHandleLess a b))))
         ((= mode "X_DESC")
          (cond
            ((> ax bx) T)
            ((< ax bx) nil)
            (T (_DmtSortHandleLess a b))))
         ((= mode "X_ASC_Y_DESC")
          (cond
            ((< ax bx) T)
            ((> ax bx) nil)
            ((> ay by) T)
            ((< ay by) nil)
            (T (_DmtSortHandleLess a b))))
         (T
          (cond
            ((> ay by) T)
            ((< ay by) nil)
            ((< ax bx) T)
            ((> ax bx) nil)
            (T (_DmtSortHandleLess a b)))))
       )
     )
  )

(defun _DmtRemoveMarked (records / out rec)
  ;; Zaten XDATA ile isareletlenmis olanlari cikar
  (setq out '())
  (foreach rec records
    (if (not (_IsMarked (cdr (assoc 'ENAME rec))))
      (setq out (cons rec out))
    )
  )
  (reverse out)
)

(defun _DmtCountMarked (records / n rec)
  ;; Isaretetli kayit sayisi
  (setq n 0)
  (foreach rec records
    (if (_IsMarked (cdr (assoc 'ENAME rec)))
      (setq n (1+ n)))
  )
  n
)

;;; ===================== Tag rapor CSV =====================

(defun _DmtScanWriteTagReport ( / path fh e blocks effs)
  (setq path (strcat
    (getvar "DWGPREFIX")
    (vl-filename-base (getvar "DWGNAME"))
    "_DMTSCAN_TAG_RAPOR.csv"
  ))
  (setq fh (open path "w"))
  (if fh
    (progn
      (write-line (_csvLine (list "TAG" "COUNT" "BLOCK_NAMES" "EFFECTIVE_NAMES" "SAMPLE_VALUES")) fh)
      (foreach e DMT_SCAN_TAG_STATS
        (setq blocks (_JoinStrList (cdr (assoc 'BLOCK_NAMES e)) " | "))
        (setq effs   (_JoinStrList (cdr (assoc 'EFFECTIVE_NAMES e)) " | "))
        (write-line
          (_csvLine
            (list
              (cdr (assoc 'TAG e))
              (itoa (cdr (assoc 'COUNT e)))
              blocks effs
              (_JoinStrList (cdr (assoc 'SAMPLE_VALUES e)) " | ")
            )
          )
          fh
        )
      )
      (close fh)
      path
    )
    nil
  )
)

(princ)

;;; ============================================================
;;; DMT v34 ??? dmt_normalize.lsp
;;; Veri normalizasyonu: BOY, ADET, CARPAN, CAP, agirlik
;;; Entity erisimi YOKTUR. Saf veri donusumu.
;;; ============================================================

;;; ===================== BOY normalizasyonu =====================

(defun _NormalizeBoy (boy / s pos left right a b avg)
  ;; "L=125" -> "125", "125~130" -> "127.5", "," -> "."
  (setq s (_Trim boy))
  (if (= s "") ""
    (progn
      (setq s (_ReplaceAll s " " ""))
      (setq s (strcase s))
      (setq s (_ReplaceAll s "L=" ""))
      (setq s (_ReplaceAll s "," "."))
      (setq pos (vl-string-search "~" s))
      (if pos
        (progn
          (setq left  (substr s 1 pos))
          (setq right (substr s (+ pos 2)))
          (if (and (_HasDigit left) (_HasDigit right))
            (progn
              (setq a (atof left) b (atof right))
              (setq avg (/ (+ a b) 2.0))
              (_FormatNum avg)
            )
            s
          )
        )
        s
      )
    )
  )
)

(defun _CmToMStr (cmStr / v)
  ;; cm string -> metre string
  (setq cmStr (_Trim (_s cmStr)))
  (if (= cmStr "") ""
    (progn
      (setq v (_NumFromStr cmStr))
      (if v (_FormatNumCsv (/ v 100.0)) cmStr)
    )
  )
)

(defun _NormalizeBoyM (boyRaw)
  ;; Ham BOY (cm) -> metre string
  (_CmToMStr (_NormalizeBoy boyRaw))
)

;;; ===================== ADET x CARPAN parse =====================

(defun _AdetCarpanParse (adetStr / s pos left right a b)
  ;; "3X2" -> (3.0 2.0), "3" -> nil, "" -> nil
  (setq s (_Trim adetStr))
  (if (= s "") nil
    (progn
      (setq s (_ReplaceAll s " " ""))
      (setq s (strcase s))
      (setq s (_ReplaceAll s "\xD7" "X")) ; ??
      (setq s (_ReplaceAll s "*" "X"))
      (setq pos (vl-string-search "X" s))
      (if pos
        (progn
          (setq left  (substr s 1 pos))
          (setq right (substr s (+ pos 2)))
          (setq a (_NumFromStr left))
          (setq b (_NumFromStr right))
          (if (and a b) (list a b) nil)
        )
        nil
      )
    )
  )
)

;;; ===================== CAP normalizasyonu =====================

(defun _NormalizeCap (capStr / v)
  ;; "??12", "12mm", "?? 14" -> sayisal deger (mm)
  (setq v (_NumFromStr (_Trim (_s capStr))))
  (if v v 0.0)
)

;;; ===================== Agirlik hesabi =====================

(defun _CalcWeightKg (capMM boyM adetNum carpanNum)
  ;; kg = adet * carpan * boy(m) * (d^2 / 162)
  (if (and (> capMM 0.0) (> boyM 0.0))
    (* (float adetNum) (float carpanNum) (float boyM)
       (/ (* capMM capMM) 162.0))
    0.0
  )
)

;;; ===================== Normalize record =====================

(defun _DmtNormalizeRecord (rec mapData / atts handle
  rawPoz rawCap rawAdet rawCarpan rawBoy rawKonum rawEk1 rawEk2 rawEk3
  pair adetNum carpanNum capMM boyCmNorm boyM weightKg warnings)
  ;; scan_record + mapping -> norm_record olustur
  ;; Uyarilar warnings listesinde toplanir

  (setq atts (cdr (assoc 'ATTRIBS rec)))
  (setq handle (_s (cdr (assoc 'HANDLE rec))))
  (setq warnings '())

  ;; Mapping uzerinden ham degerleri oku
  (setq rawPoz     (_Trim (_AlGet atts (_DmtMapGet mapData "POZ"))))
  (setq rawCap     (_Trim (_AlGet atts (_DmtMapGet mapData "CAP"))))
  (setq rawAdet    (_Trim (_AlGet atts (_DmtMapGet mapData "ADET"))))
  (setq rawBoy     (_Trim (_AlGet atts (_DmtMapGet mapData "BOY"))))
  (setq rawCarpan  (_Trim (_AlGet atts (_DmtMapGet mapData "CARPAN"))))
  (setq rawKonum   (_Trim (_AlGet atts (_DmtMapGet mapData "KONUM"))))
  (setq rawEk1     (_Trim (_AlGet atts (_DmtMapGet mapData "EK1"))))
  (setq rawEk2     (_Trim (_AlGet atts (_DmtMapGet mapData "EK2"))))
  (setq rawEk3     (_Trim (_AlGet atts (_DmtMapGet mapData "EK3"))))

  ;; ADET / CARPAN parse
  (setq pair (_AdetCarpanParse rawAdet))
  (if pair
    (progn
      (setq adetNum (car pair))
      (setq carpanNum (cadr pair))
    )
    (progn
      (setq adetNum (_ToRealDef rawAdet 1.0))
      (setq carpanNum (_ToRealDef rawCarpan 1.0))
      ;; ADET var ama parse edilemiyorsa uyar
      (if (and (/= rawAdet "") (null (_NumFromStr rawAdet)))
        (setq warnings (cons (strcat "ADET format hatali: " rawAdet) warnings))
      )
    )
  )

  ;; CAP
  (setq capMM (_NormalizeCap rawCap))
  (if (and (= capMM 0.0) (/= rawCap ""))
    (setq warnings (cons (strcat "CAP sayiya cevrilemedi: " rawCap) warnings))
  )
  (if (= rawCap "")
    (setq warnings (cons "CAP bos, agirlik hesaplanamaz" warnings))
  )

  ;; BOY
  (setq boyCmNorm (_NormalizeBoy rawBoy))
  (setq boyM (_CmToMStr boyCmNorm))
  (if (and (/= rawBoy "") (= boyM ""))
    (setq warnings (cons (strcat "BOY parse hatasi: " rawBoy) warnings))
  )
  (if (= rawBoy "")
    (setq warnings (cons "BOY bos" warnings))
  )

  ;; BOY ortalama uyarisi
  (if (and (/= rawBoy "") (vl-string-search "~" rawBoy))
    (setq warnings (cons (strcat "BOY ortalama alindi: " rawBoy) warnings))
  )

  ;; Agirlik
  (setq weightKg
    (_CalcWeightKg capMM
      (if (= boyM "") 0.0 (/ (_ToRealDef boyCmNorm 0.0) 100.0))
      adetNum carpanNum
    )
  )

  ;; Warnings'i log'a yaz
  (foreach w (reverse warnings)
    (_DmtLog "WARN" (strcat "h=" handle) w)
  )

  ;; norm_record dondur
  (list
    (cons 'ENAME          (cdr (assoc 'ENAME rec)))
    (cons 'HANDLE         handle)
    (cons 'BLOCK_NAME     (cdr (assoc 'BLOCK_NAME rec)))
    (cons 'EFFECTIVE_NAME (cdr (assoc 'EFFECTIVE_NAME rec)))
    (cons 'LAYER          (cdr (assoc 'LAYER rec)))
    (cons 'X              (cdr (assoc 'X rec)))
    (cons 'Y              (cdr (assoc 'Y rec)))
    (cons 'POZ            rawPoz)
    (cons 'CAP_MM         capMM)
    (cons 'ADET           adetNum)
    (cons 'CARPAN         carpanNum)
    (cons 'BOY_CM_NORM    boyCmNorm)
    (cons 'BOY_M          boyM)
    (cons 'KONUM          rawKonum)
    (cons 'KIRIS_KOLON    "")
    (cons 'EK1            rawEk1)
    (cons 'EK2            rawEk2)
    (cons 'EK3            rawEk3)
    (cons 'AGIRLIK_KG     weightKg)
    (cons 'WARNINGS       (reverse warnings))
    (cons 'RAW_ADET       rawAdet)
    (cons 'RAW_BOY        rawBoy)
    (cons 'RAW_CAP        rawCap)
  )
)

;;; ===================== YER birlestirme =====================

(defun _DmtNormYer (normRec)
  ;; KONUM + EK1 + EK2 + EK3 -> birlesik gorunum
  (_JoinStrList
    (list
      (_s (cdr (assoc 'KONUM normRec)))
      (_s (cdr (assoc 'EK1 normRec)))
      (_s (cdr (assoc 'EK2 normRec)))
      (_s (cdr (assoc 'EK3 normRec)))
    )
    " "
  )
)

(princ)

;;; ============================================================
;;; DMT v34.1 ??? dmt_export.lsp
;;; CSV cikti: dosya yonetimi, header, satir yazma
;;; ============================================================

(setq DMT_CSV_NAME "donati_metraj.csv")

;;; ===================== Dosya yolu =====================

(defun _DmtCsvPath ( / p)
  (setq p (getvar "DWGPREFIX"))
  (if (or (null p) (= p "")) (setq p (getvar "TEMPPREFIX")))
  (strcat p DMT_CSV_NAME)
)

;;; ===================== Header =====================

(defun _DmtCsvHeader ()
  "SIRA;POZ;ADET;CAP;ARALIK;BOY;KONUM;CARPAN;EK1;EK2;EK3;AGIRLIK;HANDLE;DWG_FILE"
)

(defun _DmtLiveCsvHeader ()
  "SIRA;POZ;ADET;CAP;ARALIK;BOY;KONUM;KIRIS_KOLON;CARPAN;EK1;EK2;EK3;AGIRLIK;HANDLE;DWG_FILE"
)

;;; ===================== Satir sayma =====================

(defun _DmtCsvCountRows (file / fh line n first)
  (setq n 0)
  (setq fh (open file "r"))
  (if fh
    (progn
      (setq first T)
      (while (setq line (read-line fh))
        (if (not first)
          (if (/= (_Trim line) "") (setq n (1+ n)))
        )
        (setq first nil)
      )
      (close fh)
      n
    )
    0
  )
)

(defun _DmtCsvNextIndex ()
  (if (_DmtAdvUiModeP)
    (1+ (_DmtAdvRecordCount))
    (1+ (_DmtCsvCountRows (_DmtCsvPath))))
)

;;; ===================== Dosya ac / kapat =====================

(defun _DmtCsvHeaderMatchesP (line expected)
  (= (strcase (_Trim (_s line)))
     (strcase (_Trim (_s expected))))
)

(defun _DmtCsvSchemaCurrentP (file / fh line)
  (setq fh (open file "r"))
  (if fh
    (progn
      (setq line (read-line fh))
      (close fh)
      (_DmtCsvHeaderMatchesP line (_DmtLiveCsvHeader))
    )
    nil
  )
)

(defun _DmtCsvOpen ( / file existed schemaOk fh)
  ;; CSV dosyasini append modda ac
  ;; Doner: (file existed fh) listesi --- fh nil ise yazma basarisiz
  (if (_DmtAdvSuppressLegacyCsvP)
    (list "" nil 'DMTPRO_SESSION_CSV)
    (progn
      (setq file (_DmtCsvPath))
      (setq existed (findfile file))
      (setq schemaOk
        (if existed
          (_DmtCsvSchemaCurrentP file)
          T
        )
      )
      (if (and existed (not schemaOk))
        (progn
          (setq fh (open file "w"))
          (if fh
            (_DmtLog "WARN" "csv" "CSV basligi eski surumde bulundu; dosya yeni baslikla sifirlandi.")
          )
          (setq existed nil)
        )
        (setq fh (open file "a"))
      )
      (if (null fh)
        (_DmtLog "ERROR" "csv"
          (strcat "CSV acilamadi: " file
                  " | Excel acik olabilir veya yazma izni yok."))
      )
      (list file existed fh)
    )
  )
)

(defun _DmtCsvClose (fh)
  (if (_DmtAdvSuppressLegacyCsvP)
    T
    (if fh (close fh))
  )
)

(defun _DmtCsvWriteHeaderIfNew (fh existed)
  (if (_DmtAdvSuppressLegacyCsvP)
    T
    (if (null existed)
      (write-line (_DmtLiveCsvHeader) fh)
    )
  )
)

;;; ===================== Tek satir yazma =====================

(defun _DmtCsvWriteRow (fh idx normRec / adetOut carpanOut boyOut kgStr capStr)
  (setq adetOut
    (if (cdr (assoc 'RAW_ADET normRec))
      (_NumToStrCsv (cdr (assoc 'ADET normRec)))
      ""
    )
  )
  (if (= adetOut "")
    (setq adetOut (_NumToStrCsv (cdr (assoc 'ADET normRec))))
  )

  (setq carpanOut (_NumToStrCsv (cdr (assoc 'CARPAN normRec))))
  (setq boyOut (_s (cdr (assoc 'BOY_M normRec))))
  (setq capStr
    (if (> (cdr (assoc 'CAP_MM normRec)) 0.0)
      (_FormatNumCsv (cdr (assoc 'CAP_MM normRec)))
      ""
    )
  )

  (setq kgStr
    (if (> (cdr (assoc 'AGIRLIK_KG normRec)) 0.0)
      (_FormatNumCsv (cdr (assoc 'AGIRLIK_KG normRec)))
      ""
    )
  )

  (write-line
    (strcat
      (_csvEsc (itoa idx)) ";"
      (_csvEsc (_s (cdr (assoc 'POZ normRec)))) ";"
      (_csvEsc adetOut) ";"
      (_csvEsc capStr) ";"
      (_csvEsc "") ";"
      (_csvEsc boyOut) ";"
      (_csvEsc (_s (cdr (assoc 'KONUM normRec)))) ";"
      (_csvEsc carpanOut) ";"
      (_csvEsc (_s (cdr (assoc 'EK1 normRec)))) ";"
      (_csvEsc (_s (cdr (assoc 'EK2 normRec)))) ";"
      (_csvEsc (_s (cdr (assoc 'EK3 normRec)))) ";"
      (_csvEsc kgStr) ";"
      (_csvEsc (_s (cdr (assoc 'HANDLE normRec)))) ";"
      (_csvEsc (_s (getvar "DWGNAME")))
    )
    fh
  )
)

(defun _DmtLiveCsvWriteRow (fh idx normRec / adetOut carpanOut boyOut kgStr capStr)
  (setq adetOut
    (if (cdr (assoc 'RAW_ADET normRec))
      (_NumToStrCsv (cdr (assoc 'ADET normRec)))
      ""
    )
  )
  (if (= adetOut "")
    (setq adetOut (_NumToStrCsv (cdr (assoc 'ADET normRec))))
  )

  (setq carpanOut (_NumToStrCsv (cdr (assoc 'CARPAN normRec))))
  (setq boyOut (_s (cdr (assoc 'BOY_M normRec))))
  (setq capStr
    (if (> (cdr (assoc 'CAP_MM normRec)) 0.0)
      (_FormatNumCsv (cdr (assoc 'CAP_MM normRec)))
      ""
    )
  )

  (setq kgStr
    (if (> (cdr (assoc 'AGIRLIK_KG normRec)) 0.0)
      (_FormatNumCsv (cdr (assoc 'AGIRLIK_KG normRec)))
      ""
    )
  )

  (write-line
    (strcat
      (_csvEsc (itoa idx)) ";"
      (_csvEsc (_s (cdr (assoc 'POZ normRec)))) ";"
      (_csvEsc adetOut) ";"
      (_csvEsc capStr) ";"
      (_csvEsc "") ";"
      (_csvEsc boyOut) ";"
      (_csvEsc (_s (cdr (assoc 'KONUM normRec)))) ";"
      (_csvEsc (_s (cdr (assoc 'KIRIS_KOLON normRec)))) ";"
      (_csvEsc carpanOut) ";"
      (_csvEsc (_s (cdr (assoc 'EK1 normRec)))) ";"
      (_csvEsc (_s (cdr (assoc 'EK2 normRec)))) ";"
      (_csvEsc (_s (cdr (assoc 'EK3 normRec)))) ";"
      (_csvEsc kgStr) ";"
      (_csvEsc (_s (cdr (assoc 'HANDLE normRec)))) ";"
      (_csvEsc (_s (getvar "DWGNAME")))
    )
    fh
  )
)

;;; ===================== Toplu export (raw + mapped) =====================

(defun _DmtExportFullCsv (scanData mapData / rawPath mapPath)
  (setq rawPath (_DmtExportRawCsv scanData))
  (setq mapPath (_DmtExportMappedCsv scanData mapData))
  (list rawPath mapPath)
)

(defun _DmtExportGetAllTags ( / out e tag)
  (setq out '())
  (foreach e DMT_SCAN_TAG_STATS
    (setq tag (_s (cdr (assoc 'TAG e))))
    (if (/= tag "") (setq out (append out (list tag))))
  )
  out
)

(defun _DmtExportBasePath (suffix / p base)
  (setq p (getvar "DWGPREFIX"))
  (setq base (vl-filename-base (getvar "DWGNAME")))
  (strcat p base suffix)
)

(defun _DmtExportRawCsv (scanData / tags path fh rec atts row tg)
  (setq tags (_DmtExportGetAllTags))
  (setq path (_DmtExportBasePath "_DMTEXPORT_RAW.csv"))
  (setq fh (open path "w"))
  (if fh
    (progn
      (write-line
        (_csvLine (append (list "HANDLE" "BLOCK_NAME" "EFFECTIVE_NAME" "LAYER" "X" "Y" "Z") tags))
        fh)
      (foreach rec scanData
        (setq atts (cdr (assoc 'ATTRIBS rec)))
        (setq row
          (list
            (_s (cdr (assoc 'HANDLE rec)))
            (_s (cdr (assoc 'BLOCK_NAME rec)))
            (_s (cdr (assoc 'EFFECTIVE_NAME rec)))
            (_s (cdr (assoc 'LAYER rec)))
            (_FormatNum (cdr (assoc 'X rec)))
            (_FormatNum (cdr (assoc 'Y rec)))
            (_FormatNum (cdr (assoc 'Z rec)))
          )
        )
        (foreach tg tags
          (setq row (append row (list (_AlGet atts tg))))
        )
        (write-line (_csvLine row) fh)
      )
      (close fh)
      path
    )
    (progn
      (_DmtLog "ERROR" "export" (strcat "Raw CSV acilamadi: " path))
      nil
    )
  )
)

(defun _DmtExportMappedCsv (scanData mapData / path fh targets sorted rec idx normRec)
  (setq path (_DmtExportBasePath "_DMTEXPORT_MAPPED.csv"))
  (setq fh (open path "w"))
  (if fh
    (progn
      (write-line (_DmtCsvHeader) fh)
      (setq targets (_DmtFilterTargets scanData mapData))
      (setq sorted (_DmtSortByPosition targets))
      (setq idx 1)
      (foreach rec sorted
        (setq normRec (_DmtNormalizeRecord rec mapData))
        (_DmtCsvWriteRow fh idx normRec)
        (setq idx (1+ idx))
      )
      (close fh)
      path
    )
    (progn
      (_DmtLog "ERROR" "export" (strcat "Mapped CSV acilamadi: " path))
      nil
    )
  )
)

(princ)

;;; ============================================================
;;; DMT v34 ??? dmt_mark.lsp
;;; Isaretleme: daire + numara cizimi, mark boyut yonetimi
;;; ============================================================

;;; ===================== Daire + numara ciz =====================

(defun _DmtDrawMark (ins idx / lname ed pt d r h sty cObj tObj mSpat safePt alignRes)
  ;; INSERT entity uzerine daire + sira numarasi ciz (Tamamen guvenlik sarimli)
  (setq lname (_EnsureLayer DMT_MARK_LAYER DMT_LAYER_COLOR))
  (setq ed (entget ins))
  (setq pt (cdr (assoc 10 ed)))
  (setq safePt
    (if (and pt (>= (length pt) 2))
      (list (float (car pt)) (float (cadr pt)) (if (caddr pt) (float (caddr pt)) 0.0))
      '(0.0 0.0 0.0)
    )
  )
  (setq d (_GetMarkDiam))
  (setq r (/ d 2.0))
  (setq h (/ d 3.0))
  (setq sty (vl-catch-all-apply 'getvar (list "TEXTSTYLE")))
  (if (vl-catch-all-error-p sty) (setq sty "Standard"))
  (if pt
    (progn
      (setq mSpat (_DmtCurrentSpace))
      (setq cObj (vl-catch-all-apply 'vla-AddCircle (list mSpat (vlax-3d-point safePt) r)))
      (if (not (vl-catch-all-error-p cObj))
        (progn
          (vl-catch-all-apply 'vla-put-Layer (list cObj lname))
          (vl-catch-all-apply 'vla-put-Color (list cObj DMT_CIRCLE_COLOR))
        )
      )
      
      (setq tObj (vl-catch-all-apply 'vla-AddText (list mSpat (itoa idx) (vlax-3d-point safePt) h)))
      (if (not (vl-catch-all-error-p tObj))
        (progn
          (vl-catch-all-apply 'vla-put-Layer (list tObj lname))
          (vl-catch-all-apply 'vla-put-Color (list tObj DMT_TEXT_COLOR))
          (vl-catch-all-apply 'vla-put-StyleName (list tObj sty))
          ;; AutoCAD Text nesnesinde once Alignment, sonra TextAlignmentPoint atanmalidir.
          ;; 10 = acAlignmentMiddleCenter
          (setq alignRes (vl-catch-all-apply 'vla-put-Alignment (list tObj 10)))
          (if (not (vl-catch-all-error-p alignRes))
            (vl-catch-all-apply 'vla-put-TextAlignmentPoint (list tObj (vlax-3d-point safePt)))
          )
        )
      )
    )
  )
)

(defun _DmtNormRecSetKirisKolon (normRec val / pair)
  (setq pair (assoc 'KIRIS_KOLON normRec))
  (if pair
    (subst (cons 'KIRIS_KOLON (_CollapseSpaces (_s val))) pair normRec)
    (append normRec (list (cons 'KIRIS_KOLON (_CollapseSpaces (_s val)))))
  )
)

;;; ===================== Tek kayit isle =====================

(defun _DmtProcessOneRecord (fh idx normRec / ins markOk appendRes)
  ;; DMTPRO oturum modunda legacy otomatik CSV ve sonuc popup bastirilir.
  ;; Ancak poz/circle cizimi ve ic tablo toplama devam eder.
  (setq ins (cdr (assoc 'ENAME normRec)))
  (if (_DmtAdvUiModeP)
    (progn
      (setq appendRes (_DmtAdvAppendRecordSafe (_DmtAdvRecordFromNorm normRec)))
      (if (= appendRes 'ADDED)
        (progn
          (if (_DmtAdvAllowMarkDrawP)
            (progn
              (_EnsureLayer DMT_MARK_LAYER DMT_LAYER_COLOR)
              (_DmtDrawMark ins idx)))
          (_DmtLog "INFO" (strcat "h=" (_DmtAdvSafeStr (cdr (assoc 'HANDLE normRec))))
                   (strcat "DMTPRO_LISTE POZ=" (_DmtAdvSafeStr (cdr (assoc 'POZ normRec)))))
          T)
        nil
      )
    )
    (if (_IsMarked ins)
      nil
      (progn
        (setq markOk (_MarkIns ins idx))
        (if markOk
          (progn
            (_DmtLiveCsvWriteRow fh idx normRec)
            (_DmtDrawMark ins idx)
            (_DmtLog "INFO" (strcat "h=" (_s (cdr (assoc 'HANDLE normRec))))
                     (strcat "SIRA=" (itoa idx) " POZ=" (_s (cdr (assoc 'POZ normRec)))))
            (if (and (boundp 'DMTADV_COLLECT_MODE) DMTADV_COLLECT_MODE)
              (_DmtAdvAppendRecordSafe (_DmtAdvRecordFromNorm normRec)))
            T
          )
          (progn
            (_DmtLog "ERROR" (strcat "h=" (_s (cdr (assoc 'HANDLE normRec))))
                     "XDATA write basarisiz; kayit uretilmedi.")
            nil
          )
        )
      )
    )
  )
)

;;; ===================== Secim yardimcisi =====================

(defun _DmtMarkDbgSetSelection (rawEn ins)
  ;; Production paketinde debug helper zorunlu degil.
  ;; dmt_dev.lsp yuklenirse gercek implementasyon bu stub''i override eder.
  nil
)

(defun _DmtTextEntityP (en / ed typ)
  (setq ed (if en (entget en) nil))
  (setq typ (strcase (_s (cdr (assoc 0 ed)))))
  (or (= typ "TEXT") (= typ "MTEXT"))
)

(defun _DmtNormalizePickedText (s)
  (setq s (_CleanVal (_s s)))
  (setq s (_ReplaceAll s "\\P" " "))
  (setq s (_ReplaceAll s "\\p" " "))
  (setq s (_ReplaceAll s (chr 9) " "))
  (_CollapseSpaces s)
)

(defun _DmtReadPickedText (en / ed typ obj raw)
  (setq ed (if en (entget en) nil))
  (setq typ (strcase (_s (cdr (assoc 0 ed)))))
  (cond
    ((= typ "TEXT")
     (_DmtNormalizePickedText (cdr (assoc 1 ed))))
    ((= typ "MTEXT")
     (setq obj (vlax-ename->vla-object en))
     (setq raw (vl-catch-all-apply 'vla-get-TextString (list obj)))
     (if (vl-catch-all-error-p raw)
       (_DmtNormalizePickedText (cdr (assoc 1 ed)))
       (_DmtNormalizePickedText raw)
     )
    )
    (T ""))
)

(defun _DmtPromptKirisKolonText ( / picked en txt done)
  ;; Her DMTEK kaydi icin istege bagli TEXT/MTEXT secimi.
  (setq txt "" done nil)
  (while (not done)
    (setq picked (entsel "\nKiris/Kolon text sec (Enter=bos): "))
    (if (null picked)
      (progn
        (setq txt "")
        (setq done T)
      )
      (progn
        (setq en (car picked))
        (if (_DmtTextEntityP en)
          (progn
            (setq txt (_DmtReadPickedText en))
            (setq done T)
          )
          (princ "\nLutfen yalnizca TEXT veya MTEXT secin.")
        )
      )
    )
  )
  txt
)

(defun _DmtSetActiveKirisKolon (txt)
  (setq DMT_ACTIVE_KIRIS_KOLON (_CollapseSpaces (_s txt)))
)

(defun _DmtGetActiveKirisKolon ()
  (_CollapseSpaces (_s DMT_ACTIVE_KIRIS_KOLON))
)

(defun _DmtSelToPozInsert (e mapData / rawE ed ins atts pozTag pozVal result)
  ;; Kullanicinin sectigi entity'den hedef INSERT'i bul.
  ;; Debug icin ham secim ile normalize INSERT handle'lari kaydedilir.
  (setq rawE e)
  (setq ins nil result nil)
  ;; Entity'den INSERT'e yuksel
  (while (and e (null ins))
    (setq ed (entget e))
    (cond
      ((null ed) (setq e nil))
      ((= (cdr (assoc 0 ed)) "INSERT") (setq ins e) (setq e nil))
      (T (setq e (cdr (assoc 330 ed))))
    )
  )
  ;; INSERT hedef mi kontrol et
  (if ins
    (progn
      (setq atts (_DmtSafeAttribs ins))
      (setq pozTag (strcase (_s (_DmtMapGet mapData "POZ"))))
      (if (and atts (/= pozTag ""))
        (progn
          (setq pozVal (_Trim (_AlGet atts pozTag)))
          (if (/= pozVal "")
            (setq result ins)
            (setq result nil)
          )
        )
        (setq result nil)
      )
    )
    (setq result nil)
  )
  (_DmtMarkDbgSetSelection rawE result)
  result
)

(princ)

;;; ============================================================
;;; DMT v35 - dmt_ui.lsp
;;; DCL entegrasyonu: tum dialog yasam dongusu, callback,
;;; veri formatlama. Tek DCL dosyasi: dmt.dcl
;;; Tum dialog fonksiyonlari DCL bulunamazsa command-line fallback icerir.
;;; ============================================================

(setq DMT_MAP_TEMP nil) ; dialog arasi gecici mapping verisi

;;; ===================== Yardimci: DCL dosya kontrolu =====================

(defun _DmtDclCheck ()
  ;; DCL bulunamazsa uyari ver, nil doner
  (if (_DmtDclPath) T
    (progn
      (princ "\nGomulu DCL temp dosyasi olusturulamadi.")
      nil
    )
  )
)

;;; ============================================================
;;; MAPPING DIALOG
;;; ============================================================

(defun _DmtMapBuildOptionsWithCount ( / e tag cnt out outKeys)
  (_DmtScanEnsureStats)
  (setq out (list "(bos)"))
  (setq outKeys (list ""))
  (foreach e DMT_SCAN_TAG_STATS
    (setq tag (_s (cdr (assoc 'TAG e))))
    (setq cnt (cdr (assoc 'COUNT e)))
    (if (/= tag "")
      (progn
        (setq out (append out (list (strcat tag " (" (itoa cnt) ")"))))
        (setq outKeys (append outKeys (list tag)))
      )
    )
  )
  (setq DMT_MAP_OPTIONS out)
  (setq DMT_MAP_OPTIONS_KEYS outKeys)
)

(defun _DmtMapFindKeyIndex (tagName / i idx)
  (setq tagName (strcase (_s tagName)))
  (setq i 0 idx 0)
  (foreach k DMT_MAP_OPTIONS_KEYS
    (if (= (strcase (_s k)) tagName) (setq idx i))
    (setq i (1+ i))
  )
  idx
)

(defun _DmtMapFillPopup (key)
  (start_list key)
  (foreach o DMT_MAP_OPTIONS (add_list o))
  (end_list)
)

(defun _DmtMapInitAllPopups (mapData / fld val idx)
  (foreach fld DMT_MAP_FIELDS
    (_DmtMapFillPopup fld)
    (setq val (_DmtMapGet mapData fld))
    (setq idx (_DmtMapFindKeyIndex val))
    (set_tile fld (itoa idx))
  )
)

(defun _DmtMapUpdateTagInfo (tileKey tileValue / idx tag stat samples)
  (setq idx (atoi tileValue))
  (if (and (> idx 0) (< idx (length DMT_MAP_OPTIONS_KEYS)))
    (progn
      (setq tag (nth idx DMT_MAP_OPTIONS_KEYS))
      (setq stat (_DmtTagStatByName tag))
      (if stat
        (progn
          (set_tile "tag_info_name"
            (strcat "Tag: " tag))
          (set_tile "tag_info_count"
            (strcat "Gorulme: " (itoa (cdr (assoc 'COUNT stat))) " blokta"))
          (set_tile "tag_info_blocks"
            (strcat "Blok: " (_TruncStr
              (_JoinStrList (cdr (assoc 'BLOCK_NAMES stat)) " | ") 50)))
          (setq samples (cdr (assoc 'SAMPLE_VALUES stat)))
          (set_tile "tag_info_samples"
            (strcat "Ornekler: " (_TruncStr
              (_JoinStrList samples ", ") 50)))
        )
        (progn
          (set_tile "tag_info_name" "Tag: -")
          (set_tile "tag_info_count" "Gorulme: -")
          (set_tile "tag_info_blocks" "Blok: -")
          (set_tile "tag_info_samples" "Ornekler: -")
        )
      )
    )
    (progn
      (set_tile "tag_info_name" "Tag: -")
      (set_tile "tag_info_count" "Gorulme: -")
      (set_tile "tag_info_blocks" "Blok: -")
      (set_tile "tag_info_samples" "Ornekler: -")
    )
  )
)

(defun _DmtMapCollect ( / out fld idx val)
  (setq out '())
  (foreach fld DMT_MAP_FIELDS
    (setq idx (atoi (get_tile fld)))
    (if (and (>= idx 0) (< idx (length DMT_MAP_OPTIONS_KEYS)))
      (setq val (_s (nth idx DMT_MAP_OPTIONS_KEYS)))
      (setq val "")
    )
    (setq out (cons (cons fld val) out))
  )
  (reverse out)
)

(defun _DmtMapOnAccept ( / mapData err)
  (setq mapData (_DmtMapCollect))
  (setq err (_DmtMapValidate mapData))
  (if err
    (set_tile "error" err)
    (progn
      (if (and (_DmtMapCapEmpty mapData) (not DMT_MAP_CAP_WARNED))
        (progn
          (setq DMT_MAP_CAP_WARNED T)
          (set_tile "error" "CAP bos - agirlik hesaplanamaz. Devam icin tekrar Kaydet.")
        )
        (progn
          (setq DMT_MAP_TEMP mapData)
          (done_dialog 1)
        )
      )
    )
  )
)

(defun _DmtMapOnAcceptAndClose ()
  (setq DMT_MAP_TEMP (_DmtMapCollect))
  (setq err (_DmtMapValidate DMT_MAP_TEMP))
  (if err
    (set_tile "error" err)
    (progn
      (if (and (_DmtMapCapEmpty DMT_MAP_TEMP) (not DMT_MAP_CAP_WARNED))
        (progn
          (setq DMT_MAP_CAP_WARNED T)
          (set_tile "error" "CAP bos - agirlik hesaplanamaz. Devam icin tekrar Kaydet."))
        (_DmtDialogDone "dmt_map" 1)))))

(defun _DmtMapDialog ( / dclId dclPath result fld)
  ;; Doner: 1=kaydet, 0=iptal, 3=onizle, 2=temizle
  (setq dclPath (_DmtDclPath))
  (if (null dclPath)
    (progn (princ "\nDCL bulunamadi.") 0)
    (progn
      (setq dclId (load_dialog dclPath))
      (if (and dclId (_DmtDialogNew "dmt_map" dclId))
        (progn
          (set_tile "scan_summary"
            (strcat "Blok: " (itoa (length DMT_SCAN_DATA))
                    "  |  Tag: " (itoa (length DMT_SCAN_TAG_STATS))
                    "  |  Hata: " (itoa (length DMT_SCAN_ERRORS))))

          (_DmtMapInitAllPopups
            (if DMT_MAP_TEMP DMT_MAP_TEMP DMT_MAP_DATA))

          (setq DMT_MAP_CAP_WARNED nil)

          (foreach fld DMT_MAP_FIELDS
            (action_tile fld
              (strcat "(_DmtMapUpdateTagInfo \"" fld "\" $value)"))
          )

          (action_tile "accept"  "(_DmtMapOnAcceptAndClose)")
          (action_tile "cancel"  "(_DmtDialogDone \"dmt_map\" 0)")
          (action_tile "preview"
            "(setq DMT_MAP_TEMP (_DmtMapCollect))(_DmtDialogDone \"dmt_map\" 3)")
          (action_tile "reset"   "(_DmtDialogDone \"dmt_map\" 2)")

          (setq result (start_dialog))
          (unload_dialog dclId)
          result
        )
        (progn
          (if dclId (unload_dialog dclId))
          (princ "\nDialog acilamadi: dmt_map")
          0
        )
      )
    )
  )
)

;;; ============================================================
;;; PREVIEW DIALOG
;;; ============================================================

(defun _DmtPreviewBuildLines (mapData / targets sorted shown normRec
  lines totalTargets warnCount i ln1 ln2 ln3 ln4 warns kgStr)
  (setq targets (_DmtFilterTargets DMT_SCAN_DATA mapData))
  (setq totalTargets (length targets))
  (setq sorted (_DmtSortByPosition targets))
  (setq shown (if (> (length sorted) 3) 3 (length sorted)))
  (setq lines '() warnCount 0 i 0)
  (while (< i shown)
    (setq normRec (_DmtNormalizeRecord (nth i sorted) mapData))
    (setq warns (cdr (assoc 'WARNINGS normRec)))

    (setq ln1 (strcat
      "#" (itoa (1+ i))
      "  POZ=" (_s (cdr (assoc 'POZ normRec)))
      "  CAP=" (if (> (cdr (assoc 'CAP_MM normRec)) 0)
                 (_FormatNum (cdr (assoc 'CAP_MM normRec))) "-")
      "  ADET=" (_s (cdr (assoc 'RAW_ADET normRec)))
      ">" (_NumToStrCsv (cdr (assoc 'ADET normRec)))
      "  BOY=" (_s (cdr (assoc 'RAW_BOY normRec)))
      ">" (_s (cdr (assoc 'BOY_M normRec))) "m"
    ))

    (setq ln2 (strcat
      "   KONUM=" (if (= (_s (cdr (assoc 'KONUM normRec))) "") "-"
                     (_s (cdr (assoc 'KONUM normRec))))
      "  CARPAN=" (_NumToStrCsv (cdr (assoc 'CARPAN normRec)))
    ))

    (setq ln3 (strcat
      "   EK1=" (if (= (_s (cdr (assoc 'EK1 normRec))) "") "-"
                   (_s (cdr (assoc 'EK1 normRec))))
      "  EK2=" (if (= (_s (cdr (assoc 'EK2 normRec))) "") "-"
                   (_s (cdr (assoc 'EK2 normRec))))
      "  EK3=" (if (= (_s (cdr (assoc 'EK3 normRec))) "") "-"
                   (_s (cdr (assoc 'EK3 normRec))))
    ))

    (setq kgStr
      (if (> (cdr (assoc 'AGIRLIK_KG normRec)) 0.0)
        (_FormatNum (cdr (assoc 'AGIRLIK_KG normRec)))
        "-"
      )
    )

    (if warns
      (progn
        (setq ln4 (strcat "   UYARI: " (_JoinStrList warns " | ")))
        (setq warnCount (1+ warnCount))
      )
      (setq ln4 (strcat "   KG=" kgStr))
    )

    (setq lines (append lines (list ln1 ln2 ln3 ln4 "----")))
    (setq i (1+ i))
  )
  (list lines totalTargets warnCount)
)

(defun _DmtPreviewDialog (mapData / dclId dclPath pack lines total warns)
  (setq pack (_DmtPreviewBuildLines mapData))
  (setq lines (car pack))
  (setq total (cadr pack))
  (setq warns (caddr pack))

  (setq dclPath (_DmtDclPath))
  (if (null dclPath)
    (progn
      (princ "\n--- Onizleme (DCL yok, command-line) ---")
      (foreach ln lines (princ (strcat "\n" ln)))
      (princ (strcat "\nHedef: " (itoa total) " | Uyarili: " (itoa warns)))
      (princ "\n---")
    )
    (progn
      (setq dclId (load_dialog dclPath))
      (if (and dclId (_DmtDialogNew "dmt_preview" dclId))
        (progn
          (start_list "preview_list")
          (foreach ln lines (add_list ln))
          (end_list)

          (set_tile "prv_target_count"
            (strcat "Hedef blok: " (itoa total)
                    " (gosterilen: " (itoa (min total 3)) ")"))
          (set_tile "prv_warn_count"
            (strcat "Uyari iceren: " (itoa warns) "/" (itoa (min total 3))))

          (action_tile "accept" "(_DmtDialogDone \"dmt_preview\" 1)")
          (start_dialog)
          (unload_dialog dclId)
        )
        (progn
          (if dclId (unload_dialog dclId))
          (princ "\nDialog acilamadi: dmt_preview")
          (foreach ln lines (princ (strcat "\n" ln)))
        )
      )
    )
  )
)

;;; ============================================================
;;; RESULT DIALOG
;;; ============================================================

(setq DMT_LAST_RESULT nil)

(defun _DmtShowResult (command written skipped warnings errors csvPath)
  (setq DMT_LAST_RESULT
    (list
      (cons 'COMMAND  command)
      (cons 'WRITTEN  written)
      (cons 'SKIPPED  skipped)
      (cons 'WARNINGS warnings)
      (cons 'ERRORS   errors)
      (cons 'CSV_PATH csvPath)
    )
  )
  (if (_DmtAdvSuppressLegacyResultP)
    DMT_LAST_RESULT
    (if (_DmtDclPath)
      (_DmtResultDialog)
      (_DmtPrintResultSummary command written skipped warnings errors csvPath)
    )
  )
)

(defun _DmtResultDialog ( / dclId dclPath result csvPath done)
  (if (null DMT_LAST_RESULT)
    (princ "\nSonuc yok.")
    (progn
      (setq dclPath (_DmtDclPath))
      (if (null dclPath)
        (_DmtPrintResultSummary
          (_s (cdr (assoc 'COMMAND DMT_LAST_RESULT)))
          (cdr (assoc 'WRITTEN DMT_LAST_RESULT))
          (cdr (assoc 'SKIPPED DMT_LAST_RESULT))
          (cdr (assoc 'WARNINGS DMT_LAST_RESULT))
          (cdr (assoc 'ERRORS DMT_LAST_RESULT))
          (_s (cdr (assoc 'CSV_PATH DMT_LAST_RESULT))))
        (progn
          (setq csvPath (_s (cdr (assoc 'CSV_PATH DMT_LAST_RESULT))))
          (setq done nil)
          (while (not done)
            (setq dclId (load_dialog dclPath))
            (if (and dclId (_DmtDialogNew "dmt_result" dclId))
              (progn
                (set_tile "res_written"
                  (itoa (cdr (assoc 'WRITTEN DMT_LAST_RESULT))))
                (set_tile "res_skipped"
                  (itoa (cdr (assoc 'SKIPPED DMT_LAST_RESULT))))
                (set_tile "res_warnings"
                  (itoa (cdr (assoc 'WARNINGS DMT_LAST_RESULT))))
                (set_tile "res_errors"
                  (itoa (cdr (assoc 'ERRORS DMT_LAST_RESULT))))
                (set_tile "res_filepath" (strcat "CSV: " csvPath))
                (set_tile "res_mode" (strcat "Islem: "
                  (_s (cdr (assoc 'COMMAND DMT_LAST_RESULT)))))

                (action_tile "btn_open_csv" "(_DmtDialogDone \"dmt_result\" 3)")
                (action_tile "btn_show_log" "(_DmtDialogDone \"dmt_result\" 2)")
                (action_tile "accept" "(_DmtDialogDone \"dmt_result\" 1)")

                (setq result (start_dialog))
                (unload_dialog dclId)

                (cond
                  ((= result 2) (_DmtLogDialog))
                  ((= result 3) (_DmtOpenFolderForFile csvPath))
                  (T (setq done T)))
              )
              (progn
                (if dclId (unload_dialog dclId))
                (princ "\nDialog acilamadi: dmt_result")
                (_DmtPrintResultSummary
                  (_s (cdr (assoc 'COMMAND DMT_LAST_RESULT)))
                  (cdr (assoc 'WRITTEN DMT_LAST_RESULT))
                  (cdr (assoc 'SKIPPED DMT_LAST_RESULT))
                  (cdr (assoc 'WARNINGS DMT_LAST_RESULT))
                  (cdr (assoc 'ERRORS DMT_LAST_RESULT))
                  (_s (cdr (assoc 'CSV_PATH DMT_LAST_RESULT))))
                (setq done T)
              )
            )
          )
        )
      )
    )
  )
)

;;; ============================================================
;;; LOG DIALOG
;;; ============================================================

(defun _DmtLogDialog ( / dclId dclPath lines entry)
  (setq dclPath (_DmtDclPath))
  (if (null dclPath)
    (_DmtPrintLogSummary)
    (progn
      (setq dclId (load_dialog dclPath))
      (if (and dclId (_DmtDialogNew "dmt_log" dclId))
        (progn
          (set_tile "log_header"
            (if DMT_LAST_RESULT
              (strcat "Son islem: " (_s (cdr (assoc 'COMMAND DMT_LAST_RESULT))))
              "Son islem: -"
            )
          )
          (set_tile "log_summary"
            (strcat "Toplam: " (itoa (length DMT_LOG))
                    " (WARN:" (itoa (_DmtLogCountByLevel "WARN"))
                    " ERROR:" (itoa (_DmtLogCountByLevel "ERROR")) ")"))

          (setq lines '())
          (foreach entry DMT_LOG
            (setq lines (append lines (list (_DmtLogFormatEntry entry))))
          )
          (start_list "log_list")
          (foreach ln lines (add_list ln))
          (end_list)

          (action_tile "btn_save"
            "(progn (setq _logPath (_DmtLogSaveToFile))
                    (if _logPath
                      (set_tile \"log_summary\" (strcat \"Kaydedildi: \" _logPath))
                      (set_tile \"log_summary\" \"Dosya kaydedilemedi.\")))")
          (action_tile "accept" "(_DmtDialogDone \"dmt_log\" 1)")

          (start_dialog)
          (unload_dialog dclId)
        )
        (progn
          (if dclId (unload_dialog dclId))
          (princ "\nDialog acilamadi: dmt_log")
          (_DmtPrintLogSummary)
        )
      )
    )
  )
)

;;; ============================================================
;;; SETTINGS DIALOG
;;; ============================================================

; LEGACY_KEPT_DO_NOT_USE: eski cap hesap yardimcisi, aktif ayar ekraninda kullanilmiyor.
(defun _DmtSettingsCalcDiam ( / ds paperD)
  (setq ds (getvar "DIMSCALE"))
  (if (or (null ds) (<= ds 0.0)) (setq ds 1.0))
  (setq paperD (atof (get_tile "edit_paper_diam")))
  (if (<= paperD 0.0) (setq paperD DMT_PAPER_CIRCLE_DIAM))
  (set_tile "lbl_calc_diam" (_FormatNum (* ds paperD)))
)

(defun _DmtSettingsFillSortModes ( / lbl)
  (start_list "sort_mode")
  (foreach lbl DMT_SORT_MODE_LABELS (add_list lbl))
  (end_list)
  (set_tile "sort_mode" (itoa (_DmtSortModeIndex)))
)

(defun _DmtSettingsDialog ( / dclId dclPath result)
  (if (_DmtAdvUiModeP)
    0
    (progn
      (setq dclPath (_DmtDclPath))
      (if (null dclPath)
        (princ (strcat "\nAyarlar (DCL yok): Ayirici=" DMT_CSV_DEC_SEP
                       " Siralama=" (_DmtSortModeLabel)))
        (progn
          (setq dclId (load_dialog dclPath))
          (if (and dclId (_DmtDialogNew "dmt_settings" dclId))
            (progn
              (if (= DMT_CSV_DEC_SEP ".")
                (set_tile "dec_dot" "1")
                (set_tile "dec_comma" "1")
              )
              (_DmtSettingsFillSortModes)
              (action_tile "accept"
                "(progn
                   (setq DMT_CSV_DEC_SEP
                     (if (= (get_tile \"dec_dot\") \"1\") \".\" \",\"))
                   (setq DMT_SORT_MODE
                     (nth (atoi (get_tile \"sort_mode\")) DMT_SORT_MODE_KEYS))
                   (_DmtSettingsSave)
                   (_DmtDialogDone \"dmt_settings\" 1))")
              (action_tile "cancel" "(_DmtDialogDone \"dmt_settings\" 0)")

              (setq result (start_dialog))
              (unload_dialog dclId)

              (if (= result 1)
                (princ (strcat "\nAyarlar kaydedildi."
                               " Ayirici=" DMT_CSV_DEC_SEP
                               " Siralama=" (_DmtSortModeLabel)))
              )
            )
            (progn
              (if dclId (unload_dialog dclId))
              (princ "\nAyarlar ekrani acilamadi.")
            )
          )
        )
      )
    )
  )
)

;;; ============================================================
;;; CONFIRM DIALOG
;;; ============================================================

(defun _DmtConfirm (msg / dclId dclPath result response)
  (setq dclPath (_DmtDclPath))
  (if (null dclPath)
    (progn
      (initget "Evet Hayir")
      (setq response (getkword (strcat "\n" (_s msg) " [Evet/Hayir] <Hayir>: ")))
      (= (strcase (_s response)) "EVET")
    )
    (progn
      (setq dclId (load_dialog dclPath))
      (if (and dclId (_DmtDialogNew "dmt_confirm" dclId))
        (progn
          (set_tile "confirm_msg" msg)
          (action_tile "accept" "(_DmtDialogDone \"dmt_confirm\" 1)")
          (action_tile "cancel" "(_DmtDialogDone \"dmt_confirm\" 0)")
          (setq result (start_dialog))
          (unload_dialog dclId)
          (= result 1)
        )
        (progn
          (if dclId (unload_dialog dclId))
          (initget "Evet Hayir")
          (setq response (getkword (strcat "\n" (_s msg) " [Evet/Hayir] <Hayir>: ")))
          (= (strcase (_s response)) "EVET")
        )
      )
    )
  )
)

;;; ============================================================
;;; MAPPING AKISI (dongu: map -> preview -> map -> save)
;;; ============================================================

(defun _DmtMapFullFlow ( / result saveOk)
  (princ "\nTarama yapiliyor...")
  (_DmtScanEnsureStats)
  (_DmtMapBuildOptionsWithCount)
  (setq DMT_MAP_DATA (_DmtMapLoad))

  (if (not (_DmtMapHasAny DMT_MAP_DATA))
    (progn
      (setq DMT_MAP_DATA
        (_DmtMapAutoSuggest
          (mapcar '(lambda (e) (strcase (_s (cdr (assoc 'TAG e)))))
                  DMT_SCAN_TAG_STATS)))
      (_DmtLog "INFO" "map" "Auto-suggest uygulandi")
    )
  )

  (setq DMT_MAP_TEMP DMT_MAP_DATA)
  (setq result 99)

  (while (and (/= result 1) (/= result 0))
    (setq result (_DmtMapDialog))
    (cond
      ((= result 3)
       (_DmtPreviewDialog DMT_MAP_TEMP)
       (setq result 99)
      )
      ((= result 2)
       (if (_DmtConfirm "Kayitli mapping'i silmek istediginizden emin misiniz?")
         (progn
           (if (_DmtMapDelete)
             (princ "\nKayitli mapping silindi.")
             (princ "\nMapping silme islemi kismen basarisiz; ekran temizlendi."))
           (setq DMT_MAP_DATA nil)
           (setq DMT_MAP_TEMP nil)
         )
       )
       (setq result 99)
      )
    )
  )

  (if (= result 1)
    (progn
      (setq DMT_MAP_DATA DMT_MAP_TEMP)
      (setq saveOk (_DmtMapSave DMT_MAP_DATA))
      (if saveOk
        (progn
          (princ "\nMapping kaydedildi.")
          (foreach fld DMT_MAP_FIELDS
            (princ (strcat "\n  " fld " = "
              (if (= (_DmtMapGet DMT_MAP_DATA fld) "") "<bos>"
                (_DmtMapGet DMT_MAP_DATA fld)))))
          (princ "\nKayit: DWG icinde XRecord")
          T
        )
        (progn (princ "\nMapping kaydedilemedi.") nil)
      )
    )
    (progn (princ "\nMapping iptal.") nil)
  )
)

;;; ============================================================
;;; DMTKNTRL DIALOG
;;; ============================================================

(setq DMT_KNTRL_RECORDS      nil)
(setq DMT_KNTRL_NAV_RECORDS  nil)
(setq DMT_KNTRL_ACTIVE_INDEX nil)
(setq DMT_KNTRL_ACTIVE_HANDLE "")
(setq DMT_KNTRL_MODE         "SIRALI")
(setq DMT_KNTRL_SINGLE_INPUT "")
(setq DMT_KNTRL_LIST_INPUT   "")
(setq DMT_KNTRL_STATUS       "")
(setq DMT_KNTRL_ZOOM_SIZE    DMT_KNTRL_DEFAULT_ZOOM)
(setq DMT_KNTRL_LAST_POINT   nil)
(setq DMT_KNTRL_DIALOG_POS   nil)
(setq DMT_UI_DIALOG_POS_MAP   nil)

(defun _DmtDialogPosValidP (pos)
  (and (= (type pos) 'LIST)
       (>= (length pos) 2)
       (numberp (car pos))
       (numberp (cadr pos))))

(defun _DmtDialogPosGet (dlg / pair)
  (setq pair (assoc (strcase (_s dlg)) DMT_UI_DIALOG_POS_MAP))
  (if pair (cdr pair) nil)
)

(defun _DmtDialogPosSet (dlg pos / key pair)
  (setq key (strcase (_s dlg)))
  (if (_DmtDialogPosValidP pos)
    (if (setq pair (assoc key DMT_UI_DIALOG_POS_MAP))
      (setq DMT_UI_DIALOG_POS_MAP (subst (cons key pos) pair DMT_UI_DIALOG_POS_MAP))
      (setq DMT_UI_DIALOG_POS_MAP (cons (cons key pos) DMT_UI_DIALOG_POS_MAP))))
  pos
)

(defun _DmtDialogNew (dlgName dclId / pos)
  (setq pos (_DmtDialogPosGet dlgName))
  (if (_DmtDialogPosValidP pos)
    (new_dialog dlgName dclId "" pos)
    (new_dialog dlgName dclId))
)

(defun _DmtDialogDone (dlgName status / pos)
  (setq pos (done_dialog status))
  (_DmtDialogPosSet dlgName pos)
)

(defun _DmtKntrlResetState ()
  (setq DMT_KNTRL_RECORDS nil)
  (setq DMT_KNTRL_NAV_RECORDS nil)
  (setq DMT_KNTRL_ACTIVE_INDEX nil)
  (setq DMT_KNTRL_ACTIVE_HANDLE "")
  (setq DMT_KNTRL_MODE "SIRALI")
  (setq DMT_KNTRL_SINGLE_INPUT "")
  (setq DMT_KNTRL_LIST_INPUT "")
  (setq DMT_KNTRL_STATUS "")
  (setq DMT_KNTRL_ZOOM_SIZE DMT_KNTRL_DEFAULT_ZOOM)
  (setq DMT_KNTRL_LAST_POINT nil)
)

; LEGACY_DISABLED_DO_NOT_USE: eski _DmtKntrlDialog kopyasi stage7 temizliginde kaldirildi.

(defun _DmtKntrlNewDialog (dlgName dclId)
  ;; DMTKNTRL reopen akisinda kullanicinin tasidigi son ekran pozisyonunu koru.
  (progn
    (setq DMT_KNTRL_DIALOG_POS (_DmtDialogPosGet dlgName))
    (_DmtDialogNew dlgName dclId)
  )
)

(defun _DmtKntrlDoneDialog (status)
  ;; done_dialog mevcut dialog konumunu dondurur; sonraki reopen bunu kullanir.
  (setq DMT_KNTRL_DIALOG_POS (_DmtDialogDone "dmt_kntrl" status))
)

(defun _DmtKntrlSetStatus (msg)
  (setq DMT_KNTRL_STATUS (_s msg))
  (if (/= DMT_KNTRL_STATUS "")
    (princ (strcat "\nDMTKNTRL: " DMT_KNTRL_STATUS))
  )
  DMT_KNTRL_STATUS
)

(defun _DmtKntrlNormalizeMode ()
  (if (not (member DMT_KNTRL_MODE '("TEK" "SIRALI" "LISTE")))
    (setq DMT_KNTRL_MODE "SIRALI")
  )
  DMT_KNTRL_MODE
)

(defun _DmtKntrlHandleEq (a b)
  (= (strcase (_s a)) (strcase (_s b)))
)

(defun _DmtKntrlRecordHandle (rec)
  (_s (cdr (assoc 'HANDLE rec)))
)

(defun _DmtKntrlCurrentRecords ()
  (if (= (_DmtKntrlNormalizeMode) "LISTE")
    DMT_KNTRL_NAV_RECORDS
    DMT_KNTRL_RECORDS
  )
)

(defun _DmtKntrlFindIndexByHandle (records handle / i idx rec)
  (setq i 0 idx nil)
  (foreach rec records
    (if (and (null idx)
             (_DmtKntrlHandleEq (_DmtKntrlRecordHandle rec) handle))
      (setq idx i)
    )
    (setq i (1+ i))
  )
  idx
)

(defun _DmtKntrlFindRecordByHandle (records handle / idx)
  (setq idx (_DmtKntrlFindIndexByHandle records handle))
  (if idx (nth idx records) nil)
)

(defun _DmtKntrlFindFirstIndexBySeq (records seq / i idx rec)
  ;; Duplicate sira durumunda zaten siralanmis listenin ilk kaydini al.
  (setq i 0 idx nil)
  (foreach rec records
    (if (and (null idx)
             (= (cdr (assoc 'SEQ rec)) seq))
      (setq idx i)
    )
    (setq i (1+ i))
  )
  idx
)

(defun _DmtKntrlSetActiveIndex (idx / records rec)
  (setq records (_DmtKntrlCurrentRecords))
  (if (and records idx (>= idx 0) (< idx (length records)))
    (progn
      (setq DMT_KNTRL_ACTIVE_INDEX idx)
      (setq rec (nth idx records))
      (setq DMT_KNTRL_ACTIVE_HANDLE (_DmtKntrlRecordHandle rec))
      rec
    )
    (progn
      (setq DMT_KNTRL_ACTIVE_INDEX nil)
      (setq DMT_KNTRL_ACTIVE_HANDLE "")
      nil
    )
  )
)

(defun _DmtKntrlRecordValidP (rec / en)
  (setq en (if rec (cdr (assoc 'ENAME rec)) nil))
  (if en (entget en) nil)
)

(defun _DmtKntrlFilterValidRecords (records / out rec)
  ;; Panel acikken silinen insert'leri listeden dusur.
  (setq out '())
  (foreach rec records
    (if (_DmtKntrlRecordValidP rec)
      (setq out (cons rec out))
    )
  )
  (reverse out)
)

(defun _DmtKntrlSyncActiveIndex ( / records idx)
  (setq records (_DmtKntrlCurrentRecords))
  (cond
    ((null records)
     (setq DMT_KNTRL_ACTIVE_INDEX nil)
     (setq DMT_KNTRL_ACTIVE_HANDLE ""))
    ((/= (_s DMT_KNTRL_ACTIVE_HANDLE) "")
     (setq idx (_DmtKntrlFindIndexByHandle records DMT_KNTRL_ACTIVE_HANDLE))
     (if idx
       (setq DMT_KNTRL_ACTIVE_INDEX idx)
       (_DmtKntrlSetActiveIndex 0)
     ))
    ((or (null DMT_KNTRL_ACTIVE_INDEX)
         (< DMT_KNTRL_ACTIVE_INDEX 0)
         (>= DMT_KNTRL_ACTIVE_INDEX (length records)))
     (_DmtKntrlSetActiveIndex 0))
  )
  DMT_KNTRL_ACTIVE_INDEX
)

(defun _DmtKntrlRefreshState ( / mainCount navCount oldHandle oldRecords oldRec oldSeq
  records oldLost idx reboundRec statusMsg)
  ;; Secili alan veya liste acikken silinen kayitlari temizle.
  ;; Aktif handle kirildiysa once ayni sira numarasina yeniden baglanmayi dener.
  (setq mainCount (length DMT_KNTRL_RECORDS))
  (setq navCount (length DMT_KNTRL_NAV_RECORDS))
  (setq oldHandle (_s DMT_KNTRL_ACTIVE_HANDLE))
  (setq oldRecords (_DmtKntrlCurrentRecords))
  (setq oldRec
    (if (/= oldHandle "")
      (_DmtKntrlFindRecordByHandle oldRecords oldHandle)
      nil
    )
  )
  (setq oldSeq (if oldRec (cdr (assoc 'SEQ oldRec)) nil))
  (setq DMT_KNTRL_RECORDS (_DmtKntrlFilterValidRecords DMT_KNTRL_RECORDS))
  (setq DMT_KNTRL_NAV_RECORDS (_DmtKntrlFilterValidRecords DMT_KNTRL_NAV_RECORDS))
  (if (and (= DMT_KNTRL_MODE "LISTE") (null DMT_KNTRL_NAV_RECORDS))
    (setq DMT_KNTRL_MODE "SIRALI")
  )
  (setq records (_DmtKntrlCurrentRecords))
  (setq oldLost
    (and (/= oldHandle "")
         (null (_DmtKntrlFindIndexByHandle records oldHandle)))
  )
  (cond
    ((null records)
     (setq DMT_KNTRL_ACTIVE_INDEX nil)
     (setq DMT_KNTRL_ACTIVE_HANDLE ""))
    (oldLost
     (setq idx
       (if oldSeq
         (_DmtKntrlFindFirstIndexBySeq records oldSeq)
         nil
       )
     )
     (if idx
       (progn
         (setq reboundRec (_DmtKntrlSetActiveIndex idx))
         (setq statusMsg
           (strcat
             "Handle gecersizdi, ayni sira numarasindaki kayda yeniden baglandi: "
             (_DmtKntrlRecordSummary reboundRec)))
         (_DmtKntrlSetStatus statusMsg))
       (progn
         (setq reboundRec (_DmtKntrlSetActiveIndex 0))
         (setq statusMsg
           (if reboundRec
             (strcat
               "Handle gecersizdi, ayni sira bulunamadi, fallback uygulandi: "
               (_DmtKntrlRecordSummary reboundRec))
             "Handle gecersizdi, ayni sira bulunamadi, fallback uygulanamadi."
           ))
         (_DmtKntrlSetStatus statusMsg)
       )
     )
    )
    (T
     (_DmtKntrlSyncActiveIndex))
  )
  (list
    (cons 'REMOVED_MAIN (- mainCount (length DMT_KNTRL_RECORDS)))
    (cons 'REMOVED_NAV (- navCount (length DMT_KNTRL_NAV_RECORDS)))
    (cons 'STATUS (_s statusMsg))
  )
)

(defun _DmtKntrlComposeStatus (refreshInfo baseMsg / refreshMsg)
  (setq refreshMsg (if refreshInfo (cdr (assoc 'STATUS refreshInfo)) nil))
  (if (and refreshMsg (/= refreshMsg ""))
    (strcat refreshMsg " " (_s baseMsg))
    (_s baseMsg)
  )
)

(defun _DmtKntrlSwitchMode (mode)
  ;; Liste modundan cikarken eski NAV state'i tasima.
  (setq mode (if (member mode '("TEK" "SIRALI" "LISTE")) mode "SIRALI"))
  (if (/= DMT_KNTRL_MODE mode)
    (progn
      (if (/= mode "LISTE")
        (setq DMT_KNTRL_NAV_RECORDS nil)
      )
      (setq DMT_KNTRL_MODE mode)
      (_DmtKntrlSyncActiveIndex)
    )
  )
  (if (and (= DMT_KNTRL_MODE "LISTE") (null DMT_KNTRL_NAV_RECORDS))
    (_DmtKntrlSetStatus "Liste modu secildi. Liste butonuyla yerel liste olusturun.")
  )
  DMT_KNTRL_MODE
)

(defun _DmtKntrlActiveRecord ( / records)
  (setq records (_DmtKntrlCurrentRecords))
  (if records
    (progn
      (_DmtKntrlSyncActiveIndex)
      (if (and DMT_KNTRL_ACTIVE_INDEX
               (>= DMT_KNTRL_ACTIVE_INDEX 0)
               (< DMT_KNTRL_ACTIVE_INDEX (length records)))
        (nth DMT_KNTRL_ACTIVE_INDEX records)
        nil
      )
    )
    nil
  )
)

(defun _DmtKntrlRecordSeqStr (rec / seq)
  (setq seq (if rec (cdr (assoc 'SEQ rec)) nil))
  (if seq (itoa (fix seq)) "-")
)

(defun _DmtKntrlSeqCount (seq records / n rec)
  (setq n 0)
  (foreach rec records
    (if (= (cdr (assoc 'SEQ rec)) seq)
      (setq n (1+ n))
    )
  )
  n
)

(defun _DmtKntrlSeqOccurrenceInfo (rec records / seq total pos item)
  (if (and rec records)
    (progn
      (setq seq (cdr (assoc 'SEQ rec)) total 0 pos 0)
      (foreach item records
        (if (= (cdr (assoc 'SEQ item)) seq)
          (progn
            (setq total (1+ total))
            (if (_DmtKntrlHandleEq (_DmtKntrlRecordHandle item)
                                   (_DmtKntrlRecordHandle rec))
              (setq pos total)
            )
          )
        )
      )
      (if (> total 0)
        (list pos total)
        nil
      )
    )
    nil
  )
)

(defun _DmtKntrlSeqLabel (rec / info)
  (if rec
    (progn
      (setq info (_DmtKntrlSeqOccurrenceInfo rec (_DmtKntrlCurrentRecords)))
      (if (and info (> (cadr info) 1))
        (strcat (_DmtKntrlRecordSeqStr rec)
                " (" (itoa (car info)) "/" (itoa (cadr info)) ")")
        (_DmtKntrlRecordSeqStr rec)
      )
    )
    "-"
  )
)

(defun _DmtKntrlRecordPosText (rec / records idx)
  (setq records (_DmtKntrlCurrentRecords))
  (if (and rec records)
    (progn
      (setq idx (_DmtKntrlFindIndexByHandle records (_DmtKntrlRecordHandle rec)))
      (if idx
        (strcat (itoa (1+ idx)) " / " (itoa (length records)))
        "- / 0"
      )
    )
    "- / 0"
  )
)

(defun _DmtKntrlRecordSummary (rec)
  (strcat (_DmtKntrlSeqLabel rec) " | " (_DmtKntrlRecordPosText rec))
)

(defun _DmtKntrlAreaInfoText ()
  (strcat "Alan kaydi: " (itoa (length DMT_KNTRL_RECORDS))
          (if DMT_KNTRL_NAV_RECORDS
            (strcat "  |  Liste: " (itoa (length DMT_KNTRL_NAV_RECORDS)))
            "")
          "  |  Zoom: " (_FormatNum DMT_KNTRL_ZOOM_SIZE))
)

(defun _DmtKntrlNavInfoText ( / records)
  (setq records (_DmtKntrlCurrentRecords))
  (if records
    (progn
      (_DmtKntrlSyncActiveIndex)
      (if DMT_KNTRL_ACTIVE_INDEX
        (strcat "Kayit: " (itoa (1+ DMT_KNTRL_ACTIVE_INDEX))
                " / " (itoa (length records)))
        (strcat "Kayit: - / " (itoa (length records)))
      )
    )
    "Kayit: - / 0"
  )
)

(defun _DmtKntrlActiveSeqText ()
  (_DmtKntrlSeqLabel (_DmtKntrlActiveRecord))
)

(defun _DmtKntrlSortRecords (records)
  (vl-sort records
    '(lambda (a b / sa sb)
       (setq sa (cdr (assoc 'SEQ a)))
       (setq sb (cdr (assoc 'SEQ b)))
       (cond
         ((< sa sb) T)
         ((> sa sb) nil)
         (T (_DmtSortHandleLess a b))
       )
     )
  )
)

(defun _DmtKntrlSessionRecordFromAdv (advRec / h en pt seq)
  (setq h (_s (cdr (assoc 'HANDLE advRec))))
  (setq en (if (/= h "") (handent h) nil))
  (setq pt (cdr (assoc 'INSERT_PT advRec)))
  (if (not (and (= (type pt) 'LIST) (>= (length pt) 2)))
    (setq pt (if en (_DmtSafePoint en) nil))
  )
  (setq seq (cdr (assoc 'NO advRec)))
  (if (and (not (numberp seq)) (/= (_s seq) ""))
    (setq seq (atoi (_s seq)))
  )
  (list
    (cons 'SEQ seq)
    (cons 'HANDLE h)
    (cons 'POINT pt)
    (cons 'ENAME en)
    (cons 'POZ (_s (cdr (assoc 'POZ advRec))))
    (cons 'SOURCE "DMTPRO")
  )
)

(defun _DmtKntrlSessionRecords ( / out rec mapped)
  (setq out '())
  (if (and (boundp 'DMTADV_RECORDS) DMTADV_RECORDS)
    (foreach rec DMTADV_RECORDS
      (setq mapped (_DmtKntrlSessionRecordFromAdv rec))
      (if (/= (_s (cdr (assoc 'HANDLE mapped))) "")
        (setq out (cons mapped out))
      )
    )
  )
  (_DmtKntrlSortRecords (reverse out))
)

(defun _DmtKntrlCollectSessionRecordsFromSs (ss / session out i en h rec)
  (setq session (_DmtKntrlSessionRecords))
  (setq out '())
  (if (and ss session)
    (progn
      (setq i 0)
      (while (< i (sslength ss))
        (setq en (ssname ss i))
        (setq h (_s (cdr (assoc 5 (entget en)))))
        (foreach rec session
          (if (_DmtKntrlHandleEq (_DmtKntrlRecordHandle rec) h)
            (setq out (cons rec out))
          )
        )
        (setq i (1+ i))
      )
    )
  )
  (_DmtKntrlSortRecords (reverse out))
)

(defun _DmtKntrlCollectSessionRecordsFromArea (p1 p2 mode / rect session out rec pt en entityBounds keep)
  (setq rect (_DmtKntrlRectBounds p1 p2))
  (setq session (_DmtKntrlSessionRecords))
  (setq out '())
  (foreach rec session
    (setq pt (_DmtKntrlRecordPoint rec))
    (setq keep (and pt (_DmtKntrlPointInRect pt rect)))
    (if (not keep)
      (progn
        (setq en (cdr (assoc 'ENAME rec)))
        (if en
          (progn
            (setq entityBounds (_DmtKntrlEntityBounds en))
            (setq keep
              (if entityBounds
                (if (= (_s mode) "_W")
                  (_DmtKntrlRectContainsBounds rect entityBounds)
                  (_DmtKntrlRectIntersectsBounds rect entityBounds))
                nil))
          )
        )
      )
    )
    (if keep
      (setq out (cons rec out))
    )
  )
  (_DmtKntrlSortRecords (reverse out))
)

(defun _DmtKntrlCollectMarkedRecordsFromSs (ss / i en marked out)
  ;; Selection set'i tek geciste oku; XDATA, handle ve insert noktasi reuse edilir.
  (setq i 0 out '())
  (while (< i (sslength ss))
    (setq en (ssname ss i))
    (setq marked (_DmtMarkedInfo en))
    (if marked
      (setq out
        (cons (append marked (list (cons 'ENAME en))) out)
      )
    )
    (setq i (1+ i))
  )
  (_DmtKntrlSortRecords (reverse out))
)

(defun _DmtKntrlRecordPoint (rec / pt en)
  ;; DMTKNTRL alandaki kaydi once insert insertion point'ine gore degerlendirir.
  (setq pt (if rec (cdr (assoc 'POINT rec)) nil))
  (if (and pt (= (type pt) 'LIST))
    pt
    (progn
      (setq en (if rec (cdr (assoc 'ENAME rec)) nil))
      (if en (_DmtSafePoint en) '(0.0 0.0 0.0))
    )
  )
)

(defun _DmtKntrlMergeUniqueRecords (base extra / out seen rec h)
  ;; Secim seti ve alan fallback taramasini handle bazli tek listeye indir.
  (setq out '() seen '())
  (foreach rec (append base extra)
    (setq h (strcase (_DmtKntrlRecordHandle rec)))
    (if (or (= h "") (not (member h seen)))
      (progn
        (setq out (cons rec out))
        (if (/= h "")
          (setq seen (cons h seen))
        )
      )
    )
  )
  (_DmtKntrlSortRecords (reverse out))
)

(defun _DmtKntrlRectBounds (p1 p2 / x1 x2 y1 y2)
  (setq x1 (min (car p1) (car p2)))
  (setq x2 (max (car p1) (car p2)))
  (setq y1 (min (cadr p1) (cadr p2)))
  (setq y2 (max (cadr p1) (cadr p2)))
  (list x1 y1 x2 y2)
)

(defun _DmtKntrlPointInRect (pt bounds / x y)
  (setq x (car pt))
  (setq y (cadr pt))
  (and (>= x (nth 0 bounds))
       (<= x (nth 2 bounds))
       (>= y (nth 1 bounds))
       (<= y (nth 3 bounds)))
)

(defun _DmtKntrlEntityBounds (en / obj res minPt maxPt)
  (setq obj (vlax-ename->vla-object en))
  (setq res (vl-catch-all-apply 'vla-GetBoundingBox (list obj 'minPt 'maxPt)))
  (if (vl-catch-all-error-p res)
    nil
    (progn
      (setq minPt (vlax-safearray->list minPt))
      (setq maxPt (vlax-safearray->list maxPt))
      (list (car minPt) (cadr minPt) (car maxPt) (cadr maxPt))
    )
  )
)

(defun _DmtKntrlRectContainsBounds (rect bounds)
  (and bounds
       (>= (nth 0 bounds) (nth 0 rect))
       (<= (nth 2 bounds) (nth 2 rect))
       (>= (nth 1 bounds) (nth 1 rect))
       (<= (nth 3 bounds) (nth 3 rect)))
)

(defun _DmtKntrlRectIntersectsBounds (rect bounds)
  (and bounds
       (not (or (< (nth 2 bounds) (nth 0 rect))
                (> (nth 0 bounds) (nth 2 rect))
                (< (nth 3 bounds) (nth 1 rect))
                (> (nth 1 bounds) (nth 3 rect)))))
)

(defun _DmtKntrlCollectMarkedRecordsFromArea (p1 p2 mode / ss i en marked pt rect out entityBounds keep rec)
  ;; Kaydi once insertion point ile dahil et; extents sadece ikinci kontrol olsun.
  (setq rect (_DmtKntrlRectBounds p1 p2))
  (setq ss (ssget "_X" '((0 . "INSERT") (410 . "Model"))))
  (setq i 0 out '())
  (if ss
    (while (< i (sslength ss))
      (setq en (ssname ss i))
      (setq marked (_DmtMarkedInfo en))
      (if marked
        (progn
          (setq rec (append marked (list (cons 'ENAME en))))
          (setq pt (_DmtKntrlRecordPoint rec))
          (setq keep (_DmtKntrlPointInRect pt rect))
          (if (not keep)
            (progn
              (setq entityBounds (_DmtKntrlEntityBounds en))
              (setq keep
                (if entityBounds
                  (if (= (_s mode) "_W")
                    (_DmtKntrlRectContainsBounds rect entityBounds)
                    (_DmtKntrlRectIntersectsBounds rect entityBounds))
                  nil
                )
              )
            )
          )
          (if keep
            (setq out (cons rec out))
          )
        )
      )
      (setq i (1+ i))
    )
  )
  (_DmtKntrlSortRecords (reverse out))
)

(defun _DmtKntrlSeqListToText (lst / out item)
  (setq out "")
  (foreach item lst
    (setq out
      (if (= out "")
        (itoa item)
        (strcat out ", " (itoa item))
      )
    )
  )
  out
)

(defun _DmtKntrlTextListToText (lst / out item)
  (setq out "")
  (foreach item lst
    (setq out
      (if (= out "")
        (_s item)
        (strcat out ", " (_s item))
      )
    )
  )
  out
)

(defun _DmtKntrlDuplicateSeqs (records / seen out rec seq)
  (setq seen '() out '())
  (foreach rec records
    (setq seq (cdr (assoc 'SEQ rec)))
    (if seq
      (if (member seq seen)
        (if (not (member seq out))
          (setq out (cons seq out))
        )
        (setq seen (cons seq seen))
      )
    )
  )
  (reverse out)
)

(defun _DmtKntrlLoadAreaRecords (records / dups msg)
  (setq DMT_KNTRL_RECORDS records)
  (setq DMT_KNTRL_NAV_RECORDS nil)
  (setq DMT_KNTRL_ACTIVE_INDEX nil)
  (setq DMT_KNTRL_ACTIVE_HANDLE "")
  (setq DMT_KNTRL_MODE "SIRALI")
  (setq DMT_KNTRL_LAST_POINT nil)
  (if records
    (progn
      (_DmtKntrlSetActiveIndex 0)
      (setq dups (_DmtKntrlDuplicateSeqs records))
      (setq msg (strcat "Secili alanda " (itoa (length records)) " DMT kaydi bulundu."))
      (if dups
        (setq msg (strcat msg " Yinelenen sira no: " (_DmtKntrlSeqListToText dups) "."))
      )
      (_DmtKntrlSetStatus msg)
    )
    (_DmtKntrlSetStatus
      "Secili alanda kayit bulunamadi. Alan Sec ile yeniden deneyin.")
  )
  records
)

(defun _DmtKntrlPickArea ( / mode kw p1 p2 ss)
  ;; Alan secimini tek insert tiklamasina dusurmeden Window/Crossing ile zorla.
  (initget "Pencere Crossing")
  (setq kw (getkword "\nSecim modu [Pencere/Crossing] <Crossing>: "))
  (if (= (_s kw) "Pencere")
    (setq mode "_W")
    (setq mode "_C")
  )
  (setq p1 (getpoint "\nIlk koseyi secin: "))
  (if p1
    (progn
      (setq p2 (getcorner p1 "\nKarsi koseyi secin: "))
      (if p2
        (progn
          (setq ss (ssget mode p1 p2 '((0 . "INSERT") (410 . "Model"))))
          (if ss
            (list (cons 'STATUS "OK") (cons 'SS ss)
                  (cons 'P1 p1) (cons 'P2 p2) (cons 'MODE mode))
            (list (cons 'STATUS "EMPTY") (cons 'SS nil)
                  (cons 'P1 p1) (cons 'P2 p2) (cons 'MODE mode))
          )
        )
        (list (cons 'STATUS "CANCEL") (cons 'SS nil)))
    )
    (list (cons 'STATUS "CANCEL") (cons 'SS nil))
  )
)

(defun _DmtKntrlSelectArea ( / picked status ss p1 p2 mode records areaRecords sessionRecords sessionArea mergedRecords)
  (prompt "\nDMTKNTRL: Pencere/Crossing ile calisma alani secin: ")
  (setq picked (_DmtKntrlPickArea))
  (setq status (_s (cdr (assoc 'STATUS picked))))
  (setq ss (cdr (assoc 'SS picked)))
  (setq p1 (cdr (assoc 'P1 picked)))
  (setq p2 (cdr (assoc 'P2 picked)))
  (setq mode (_s (cdr (assoc 'MODE picked))))
  (cond
    ((= status "OK")
     (setq records (_DmtKntrlCollectMarkedRecordsFromSs ss))
     (setq sessionRecords (_DmtKntrlCollectSessionRecordsFromSs ss))
     (if (and p1 p2)
       (progn
         (setq areaRecords (_DmtKntrlCollectMarkedRecordsFromArea p1 p2 mode))
         (setq sessionArea (_DmtKntrlCollectSessionRecordsFromArea p1 p2 mode)))
       (setq areaRecords nil sessionArea nil)
     )
     (setq mergedRecords (_DmtKntrlMergeUniqueRecords records areaRecords))
     (setq mergedRecords (_DmtKntrlMergeUniqueRecords mergedRecords sessionRecords))
     (setq mergedRecords (_DmtKntrlMergeUniqueRecords mergedRecords sessionArea))
     (_DmtKntrlLoadAreaRecords mergedRecords)
     T)
    ((= status "EMPTY")
     (if (and p1 p2)
       (progn
         (setq records (_DmtKntrlCollectMarkedRecordsFromArea p1 p2 mode))
         (setq sessionArea (_DmtKntrlCollectSessionRecordsFromArea p1 p2 mode)))
       (setq records nil sessionArea nil)
     )
     (setq mergedRecords (_DmtKntrlMergeUniqueRecords records sessionArea))
     (_DmtKntrlLoadAreaRecords mergedRecords)
     T)
    (T nil)
  )
)

(defun _DmtKntrlZoomPoint (pt / z p1 p2)
  (if (and (= (type pt) 'LIST) (>= (length pt) 2))
    (progn
      (setq z (float DMT_KNTRL_ZOOM_SIZE))
      (if (or (null z) (<= z 0.0))
        (setq z DMT_KNTRL_DEFAULT_ZOOM)
      )
      (setq p1 (list (- (car pt) z) (- (cadr pt) z)))
      (setq p2 (list (+ (car pt) z) (+ (cadr pt) z)))
      (command "_.ZOOM" "_W" p1 p2)
      (setq DMT_KNTRL_LAST_POINT pt)
      T
    )
    nil
  )
)

(defun _DmtKntrlZoomToRecord (rec / en pt)
  (if (_DmtKntrlRecordValidP rec)
    (progn
      (setq en (cdr (assoc 'ENAME rec)))
      (setq pt (cdr (assoc 'POINT rec)))
      (if (or (null pt) (/= (type pt) 'LIST))
        (setq pt (_DmtSafePoint en))
      )
      (if (_DmtKntrlZoomPoint pt)
        T
        (progn
          (_DmtKntrlSetStatus "Aktif kaydin zoom noktasi okunamadi.")
          nil
        )
      )
    )
    (progn
      (_DmtKntrlSetStatus "Aktif kayit gecersiz veya silinmis.")
      nil
    )
  )
)

(defun _DmtKntrlRezoom ( / refreshInfo)
  (setq refreshInfo (_DmtKntrlRefreshState))
  (if (_DmtKntrlActiveRecord)
    (_DmtKntrlZoomToRecord (_DmtKntrlActiveRecord))
    (if DMT_KNTRL_LAST_POINT
      (_DmtKntrlZoomPoint DMT_KNTRL_LAST_POINT)
      (_DmtKntrlSetStatus
        (_DmtKntrlComposeStatus refreshInfo "Tekrar zoom icin aktif hedef yok."))
    )
  )
)

(defun _DmtKntrlRecordsBySeq (seq records / out rec)
  (setq out '())
  (foreach rec records
    (if (= (cdr (assoc 'SEQ rec)) seq)
      (setq out (cons rec out))
    )
  )
  (reverse out)
)

(defun _DmtKntrlDigitsOnlyP (s / i ch ok)
  (setq s (_Trim (_s s)) i 1 ok (/= s ""))
  (while (and ok (<= i (strlen s)))
    (setq ch (substr s i 1))
    (if (or (< ch "0") (> ch "9"))
      (setq ok nil)
    )
    (setq i (1+ i))
  )
  ok
)

(defun _DmtKntrlParseSeq (s / clean v)
  (setq clean (_Trim (_s s)))
  (if (_DmtKntrlDigitsOnlyP clean)
    (progn
      (setq v (atoi clean))
      (if (> v 0) v nil)
    )
    nil
  )
)

(defun _DmtKntrlParseListToken (token / clean val)
  (setq clean (_Trim (_s token)))
  (cond
    ((= clean "") nil)
    ((_DmtKntrlDigitsOnlyP clean)
     (setq val (atoi clean))
     (if (> val 0) val 'INVALID))
    (T 'INVALID)
  )
)

(defun _DmtKntrlNormalizeListInput (s / src)
  ;; Excel paste ve karisik ayiricilari tek akisa indir.
  (setq src (_s s))
  (setq src (_ReplaceAll src "," " "))
  (setq src (_ReplaceAll src (chr 9) " "))
  (setq src (_ReplaceAll src (chr 10) " "))
  (setq src (_ReplaceAll src (chr 13) " "))
  src
)

(defun _DmtKntrlParseList (s / src i ch token seqs invalid dup seen val clean)
  ;; Liste girisini guvenli parse et; virgul, bosluk, tab ve satir sonlari desteklenir.
  (setq src (_DmtKntrlNormalizeListInput s))
  (setq i 1 token "" seqs '() invalid '() dup '() seen '())
  (while (<= i (strlen src))
    (setq ch (substr src i 1))
    (if (= ch " ")
      (progn
        (setq clean (_Trim token))
        (setq val (_DmtKntrlParseListToken clean))
        (cond
          ((= val 'INVALID)
           (setq invalid (append invalid (list clean))))
          (val
           (if (member val seen)
             (if (not (member val dup))
               (setq dup (append dup (list val))))
             (progn
               (setq seen (append seen (list val)))
               (setq seqs (append seqs (list val)))))))
        (setq token "")
      )
      (setq token (strcat token ch))
    )
    (setq i (1+ i))
  )
  (setq clean (_Trim token))
  (setq val (_DmtKntrlParseListToken clean))
  (cond
    ((= val 'INVALID)
     (setq invalid (append invalid (list clean))))
    (val
     (if (member val seen)
       (if (not (member val dup))
         (setq dup (append dup (list val))))
       (setq seqs (append seqs (list val))))))
  (list
    (cons 'SEQS seqs)
    (cons 'INVALID invalid)
    (cons 'DUPLICATES dup))
)

(defun _DmtKntrlFindIndexAtOrNext (seq records / i idx rec)
  (setq i 0 idx nil)
  (foreach rec records
    (if (and (null idx) (>= (cdr (assoc 'SEQ rec)) seq))
      (setq idx i)
    )
    (setq i (1+ i))
  )
  idx
)

(defun _DmtKntrlGoTek ( / seq records idx exactCount rec)
  ;; Tek sira arar; yoksa secili alandaki sonraki mevcut kayda gider.
  (_DmtKntrlRefreshState)
  (setq records DMT_KNTRL_RECORDS)
  (cond
    ((null records)
     (_DmtKntrlSetStatus "Secili alanda kayit yok."))
    ((null (setq seq (_DmtKntrlParseSeq DMT_KNTRL_SINGLE_INPUT)))
     (_DmtKntrlSetStatus "Gecerli bir sira no girin."))
    (T
     (_DmtKntrlSwitchMode "TEK")
     (setq idx (_DmtKntrlFindIndexAtOrNext seq records))
     (setq exactCount (_DmtKntrlSeqCount seq records))
     (if idx
       (progn
         (setq rec (_DmtKntrlSetActiveIndex idx))
         (_DmtKntrlZoomToRecord rec)
         (cond
           ((> exactCount 1)
            (_DmtKntrlSetStatus
              (strcat (itoa seq) " bulundu. " (itoa exactCount)
                      " kayit icinde ilk kayda gidildi: "
                      (_DmtKntrlRecordSummary rec))))
           ((= exactCount 1)
            (_DmtKntrlSetStatus
              (strcat (itoa seq) " bulundu, kayda gidildi: "
                      (_DmtKntrlRecordSummary rec))))
           (T
            (_DmtKntrlSetStatus
              (strcat (itoa seq)
                      " bulunamadi, sonraki mevcut kayda gidildi: "
                      (_DmtKntrlRecordSummary rec))))
         )
       )
       (progn
         (setq rec (_DmtKntrlSetActiveIndex (1- (length records))))
         (_DmtKntrlZoomToRecord rec)
         (_DmtKntrlSetStatus
           (strcat (itoa seq)
                   " bulunamadi, daha buyuk kayit yok. Son kayda gidildi: "
                   (_DmtKntrlRecordSummary rec)))
       )
     )
    )
  )
)

(defun _DmtKntrlGoSirali ( / refreshInfo rec)
  (setq refreshInfo (_DmtKntrlRefreshState))
  (cond
    ((null DMT_KNTRL_RECORDS)
     (_DmtKntrlSetStatus
       (_DmtKntrlComposeStatus refreshInfo "Secili alanda kayit yok.")))
    (T
     (_DmtKntrlSwitchMode "SIRALI")
     (setq rec (_DmtKntrlActiveRecord))
     (if rec
       (progn
         (_DmtKntrlZoomToRecord rec)
         (_DmtKntrlSetStatus
           (_DmtKntrlComposeStatus
             refreshInfo
             (strcat "Sirali gezinme aktif: " (_DmtKntrlRecordSummary rec)))))
       (_DmtKntrlSetStatus
         (_DmtKntrlComposeStatus refreshInfo "Gidilecek aktif kayit yok.")))
    )
  )
)

(defun _DmtKntrlActivateList ( / parsed seqs invalid dupInput nav missing seq matches rec msg)
  (_DmtKntrlRefreshState)
  (cond
    ((null DMT_KNTRL_RECORDS)
     (_DmtKntrlSetStatus "Secili alanda kayit yok."))
    (T
     (setq parsed (_DmtKntrlParseList DMT_KNTRL_LIST_INPUT))
     (setq seqs (cdr (assoc 'SEQS parsed)))
     (setq invalid (cdr (assoc 'INVALID parsed)))
     (setq dupInput (cdr (assoc 'DUPLICATES parsed)))
     (if (null seqs)
       (if invalid
         (_DmtKntrlSetStatus
           (strcat "Liste icinde gecerli sira yok. Gecersiz giris: "
                   (_DmtKntrlTextListToText invalid) "."))
         (_DmtKntrlSetStatus "Liste icin gecerli sira no girin. Ornek: 12,18,44 veya 12 18 44"))
       (progn
         (setq nav '() missing '())
         (foreach seq seqs
           (setq matches (_DmtKntrlRecordsBySeq seq DMT_KNTRL_RECORDS))
           (if matches
             (setq nav (append nav matches))
             (setq missing (append missing (list seq))))
         )
         (if nav
           (progn
             (setq DMT_KNTRL_MODE "LISTE")
             (setq DMT_KNTRL_NAV_RECORDS nav)
             (setq DMT_KNTRL_ACTIVE_INDEX nil)
             (setq DMT_KNTRL_ACTIVE_HANDLE "")
             (setq rec (_DmtKntrlSetActiveIndex 0))
             (_DmtKntrlZoomToRecord rec)
             (setq msg (strcat "Liste modu hazir. Kayit: " (itoa (length nav))
                               ". Aktif: " (_DmtKntrlRecordSummary rec) "."))
             (if missing
               (setq msg (strcat msg " Bulunamayan: " (_DmtKntrlSeqListToText missing) ".")))
             (if invalid
               (setq msg (strcat msg " Gecersiz giris: " (_DmtKntrlTextListToText invalid) ".")))
             (if dupInput
               (setq msg (strcat msg " Yinelenen liste girdileri teke indirildi: "
                                 (_DmtKntrlSeqListToText dupInput) ".")))
             (_DmtKntrlSetStatus msg)
           )
           (progn
             (setq msg "Liste icinde secili alanda bulunan kayit yok.")
             (if missing
               (setq msg (strcat msg " Bulunamayan: " (_DmtKntrlSeqListToText missing) ".")))
             (if invalid
               (setq msg (strcat msg " Gecersiz giris: " (_DmtKntrlTextListToText invalid) ".")))
             (_DmtKntrlSetStatus msg)
           )
         )
       )
     )
    )
  )
)

(defun _DmtKntrlPrev ( / refreshInfo records idx rec)
  (setq refreshInfo (_DmtKntrlRefreshState))
  (setq records (_DmtKntrlCurrentRecords))
  (cond
    ((null records)
     (if (= (_DmtKntrlNormalizeMode) "LISTE")
       (_DmtKntrlSetStatus
         (_DmtKntrlComposeStatus refreshInfo "Liste hazir degil. Once Liste butonunu kullanin."))
       (_DmtKntrlSetStatus
         (_DmtKntrlComposeStatus refreshInfo "Secili alanda kayit yok."))))
    (T
     (_DmtKntrlSyncActiveIndex)
     (setq idx DMT_KNTRL_ACTIVE_INDEX)
     (if (or (null idx) (<= idx 0))
       (progn
         (setq rec (_DmtKntrlSetActiveIndex 0))
         (_DmtKntrlZoomToRecord rec)
         (_DmtKntrlSetStatus
           (_DmtKntrlComposeStatus
             refreshInfo
             (strcat "Listenin ilk kaydindasiniz: " (_DmtKntrlRecordSummary rec)))))
       (progn
         (setq rec (_DmtKntrlSetActiveIndex (1- idx)))
         (_DmtKntrlZoomToRecord rec)
         (_DmtKntrlSetStatus
           (_DmtKntrlComposeStatus
             refreshInfo
             (strcat "Onceki kayda gidildi: " (_DmtKntrlRecordSummary rec))))))
    )
  )
)

(defun _DmtKntrlNext ( / refreshInfo records idx rec)
  (setq refreshInfo (_DmtKntrlRefreshState))
  (setq records (_DmtKntrlCurrentRecords))
  (cond
    ((null records)
     (if (= (_DmtKntrlNormalizeMode) "LISTE")
       (_DmtKntrlSetStatus
         (_DmtKntrlComposeStatus refreshInfo "Liste hazir degil. Once Liste butonunu kullanin."))
       (_DmtKntrlSetStatus
         (_DmtKntrlComposeStatus refreshInfo "Secili alanda kayit yok."))))
    (T
     (_DmtKntrlSyncActiveIndex)
     (setq idx DMT_KNTRL_ACTIVE_INDEX)
     (if (or (null idx) (>= idx (1- (length records))))
       (progn
         (setq rec (_DmtKntrlSetActiveIndex (1- (length records))))
         (_DmtKntrlZoomToRecord rec)
         (_DmtKntrlSetStatus
           (_DmtKntrlComposeStatus
             refreshInfo
             (strcat "Listenin son kaydindasiniz: " (_DmtKntrlRecordSummary rec)))))
       (progn
         (setq rec (_DmtKntrlSetActiveIndex (1+ idx)))
         (_DmtKntrlZoomToRecord rec)
         (_DmtKntrlSetStatus
           (_DmtKntrlComposeStatus
             refreshInfo
             (strcat "Sonraki kayda gidildi: " (_DmtKntrlRecordSummary rec))))))
    )
  )
)

(defun _DmtKntrlAskZoomSize ( / v)
  (initget 6)
  (setq v
    (getreal
      (strcat "\nZoom yari capi <"
              (_FormatNum DMT_KNTRL_ZOOM_SIZE) ">: ")))
  (if v
    (progn
      (setq DMT_KNTRL_ZOOM_SIZE v)
      (_DmtKntrlSetStatus
        (strcat "Zoom ayari guncellendi: " (_FormatNum DMT_KNTRL_ZOOM_SIZE))))
    (_DmtKntrlSetStatus "Zoom ayari degismedi."))
)

(defun _DmtKntrlRememberInputs ()
  (setq DMT_KNTRL_SINGLE_INPUT (_s (get_tile "kntrl_tek_input")))
  (setq DMT_KNTRL_LIST_INPUT (_s (get_tile "kntrl_list_input")))
)

(defun _DmtKntrlApplyModeUi ()
  (_DmtKntrlNormalizeMode)
  (set_tile "kntrl_mode_tek" (if (= DMT_KNTRL_MODE "TEK") "1" "0"))
  (set_tile "kntrl_mode_sirali" (if (= DMT_KNTRL_MODE "SIRALI") "1" "0"))
  (set_tile "kntrl_mode_liste" (if (= DMT_KNTRL_MODE "LISTE") "1" "0"))
  (cond
    ((= DMT_KNTRL_MODE "LISTE")
     (mode_tile "kntrl_tek_input" 1)
     (mode_tile "kntrl_go" 1)
     (mode_tile "kntrl_list_input" 0)
     (mode_tile "kntrl_list" 0))
    ((= DMT_KNTRL_MODE "SIRALI")
     (mode_tile "kntrl_tek_input" 1)
     (mode_tile "kntrl_go" 0)
     (mode_tile "kntrl_list_input" 1)
     (mode_tile "kntrl_list" 1))
    (T
     (mode_tile "kntrl_tek_input" 0)
     (mode_tile "kntrl_go" 0)
     (mode_tile "kntrl_list_input" 1)
     (mode_tile "kntrl_list" 1)))
)

(defun _DmtKntrlInitDialog ()
  (_DmtKntrlRefreshState)
  (set_tile "kntrl_active_seq" (_DmtKntrlActiveSeqText))
  (set_tile "kntrl_status"
    (if (= (_s DMT_KNTRL_STATUS) "") "Hazir." DMT_KNTRL_STATUS))
  (set_tile "kntrl_area_info" (_DmtKntrlAreaInfoText))
  (set_tile "kntrl_nav_info" (_DmtKntrlNavInfoText))
  (set_tile "kntrl_tek_input" (_s DMT_KNTRL_SINGLE_INPUT))
  (set_tile "kntrl_list_input" (_s DMT_KNTRL_LIST_INPUT))
  (_DmtKntrlApplyModeUi)
)

(defun _DmtKntrlDialog ( / dclId dclPath result)
  (setq dclPath (_DmtDclPath))
  (if dclPath
    (progn
      (setq dclId (load_dialog dclPath))
      (if (and dclId (_DmtKntrlNewDialog "dmt_kntrl" dclId))
        (progn
          (_DmtKntrlInitDialog)

          (action_tile "kntrl_mode_tek"
            "(progn (_DmtKntrlSwitchMode \"TEK\") (_DmtKntrlApplyModeUi))")
          (action_tile "kntrl_mode_sirali"
            "(progn (_DmtKntrlSwitchMode \"SIRALI\") (_DmtKntrlApplyModeUi))")
          (action_tile "kntrl_mode_liste"
            "(progn (_DmtKntrlSwitchMode \"LISTE\") (_DmtKntrlApplyModeUi))")

          (action_tile "kntrl_area" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 2))")
          (action_tile "kntrl_go" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 3))")
          (action_tile "kntrl_prev" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 4))")
          (action_tile "kntrl_next" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 5))")
          (action_tile "kntrl_list" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 6))")
          (action_tile "kntrl_zoom_set" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 7))")
          (action_tile "kntrl_rezoom" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 8))")
          (action_tile "cancel" "(progn (_DmtKntrlRememberInputs) (_DmtKntrlDoneDialog 0))")

          (setq result (start_dialog))
          (unload_dialog dclId)
          result
        )
        (progn
          (if dclId (unload_dialog dclId))
          (princ "\nDialog acilamadi: dmt_kntrl [embedded DCL]")
          0
        )
      )
    )
    (progn
      (princ "\nDialog acilamadi: dmt_kntrl [embedded DCL yolu olusturulamadi]")
      0
    )
  )
)

(defun _DmtKntrlFlow ( / result)
  (setq result 99)
  (while (/= result 0)
    (setq result (_DmtKntrlDialog))
    (cond
      ((= result 2)
       (if (not (_DmtKntrlSelectArea))
         (_DmtKntrlSetStatus "Alan secimi iptal edildi."))
       (setq result 99))
      ((= result 3)
       (cond
         ((= (_DmtKntrlNormalizeMode) "TEK") (_DmtKntrlGoTek))
         ((= DMT_KNTRL_MODE "SIRALI") (_DmtKntrlGoSirali))
         (T (_DmtKntrlSetStatus "Liste modunda Liste butonunu kullanin.")))
       (setq result 99))
      ((= result 4) (_DmtKntrlPrev) (setq result 99))
      ((= result 5) (_DmtKntrlNext) (setq result 99))
      ((= result 6) (_DmtKntrlActivateList) (setq result 99))
      ((= result 7) (_DmtKntrlAskZoomSize) (setq result 99))
      ((= result 8) (_DmtKntrlRezoom) (setq result 99))
    )
  )
)

(defun _DmtKntrlRun ()
  (if (_DmtDclCheck)
    (progn
      (_DmtKntrlResetState)
      (if (_DmtKntrlSelectArea)
        (_DmtKntrlFlow)
        (princ "\nIslem iptal edildi. Alan secilmedi.")))
    (princ "\nKontrol ekrani acilamadi."))
)
(princ)

;;; ============================================================
;;; DMT v35 - dmt_commands.lsp
;;; Komut tanimlari: orkestrasyon, is mantigi yok.
;;; Komutlar: DMTSCAN, DMTSCANRAPOR, DMTMAP, DMTEXPORT,
;;;           DMTALL, DMTALAN, DMTEXT, DMTEK, DMTRESET, DMTAYAR, DMTLOG
;;; v35 release: graceful return, DCL/CSV fallback, XRecord-first mapping persistence
;;; ============================================================

;;; ===================== DMTSCAN =====================

(defun _DmtCmdScan ( / )
  (princ "\nDMTSCAN: Model Space taraniyor...")
  (_DmtScanRun)
  (_DmtScanBuildTagStats)
  (princ (strcat "\nTamamlandi. Blok: " (itoa (length DMT_SCAN_DATA))
                 " | Tag: " (itoa (length DMT_SCAN_TAG_STATS))
                 " | Hata: " (itoa (length DMT_SCAN_ERRORS))))
  (princ)
)

;;; ===================== DMTSCANRAPOR =====================

(defun _DmtCmdScanRapor ( / path shown)
  (princ "\nDMTSCANRAPOR: Tarama ve rapor hazirlaniyor...")
  (_DmtScanRun)
  (_DmtScanBuildTagStats)
  (princ (strcat "\nBlok: " (itoa (length DMT_SCAN_DATA))
                 " | Tag: " (itoa (length DMT_SCAN_TAG_STATS))))
  (setq shown 0)
  (foreach e DMT_SCAN_TAG_STATS
    (if (< shown 20)
      (progn
        (princ (strcat "\n  " (_s (cdr (assoc 'TAG e)))
                       " = " (itoa (cdr (assoc 'COUNT e))) " kez"))
        (setq shown (1+ shown))
      )
    )
  )
  (if (> (length DMT_SCAN_TAG_STATS) 20)
    (princ (strcat "\n  ... ve " (itoa (- (length DMT_SCAN_TAG_STATS) 20)) " tag daha."))
  )
  (setq path (_DmtScanWriteTagReport))
  (if path
    (princ (strcat "\nRapor: " path))
    (princ "\nRapor olusturulamadi.")
  )
  (princ)
)

;;; ===================== DMTMAP =====================

(defun _DmtCmdMap ()
  (if (_DmtDclCheck)
    (_DmtMapFullFlow)
    (princ "\nMapping ekrani acilamadi.")
  )
  (princ)
)

;;; ===================== DMTEXPORT =====================

(defun _DmtCmdExport ( / paths rawPath mapPath)
  (_DmtScanEnsureStats)
  (setq DMT_MAP_DATA (_DmtMapLoad))
  (setq paths (_DmtExportFullCsv DMT_SCAN_DATA DMT_MAP_DATA))
  (setq rawPath (car paths))
  (setq mapPath (cadr paths))
  (if rawPath
    (princ (strcat "\nHam CSV: " rawPath))
    (princ "\nHam CSV olusturulamadi."))
  (if mapPath
    (princ (strcat "\nMapped CSV: " mapPath))
    (princ "\nMapped CSV olusturulamadi."))
  (princ)
)

;;; ===================== DMTALL =====================

(defun _DmtCmdAll ( / _abort pack file existed fh targets sorted unmarked
  idx count skipped warnN errN normRec ok)
  ;; Model Space tum hedef bloklari isle
  ;; v35: exit yerine _abort flag ile graceful return

  (_DmtInitSafeMode)
  (setq _abort nil)
  (setq uiMode (or (_DmtAdvUiModeP) (and (boundp 'DMTADV_COLLECT_MODE) DMTADV_COLLECT_MODE)))
  (_DmtSettingsLoad)

  ;; --- Mapping yukle ---
  (setq DMT_MAP_DATA (_DmtMapLoad))

  ;; --- Mapping yoksa yonlendir ---
  (if (and (not _abort) (not (_DmtMapHasAny DMT_MAP_DATA)))
    (progn
      (princ "\nMapping bulunamadi. Mapping ekranini kullanin.")
      (if (_DmtConfirm "Mapping bulunamadi. Mapping ekrani acilsin mi?")
        (progn
          (if (_DmtDclCheck)
            (_DmtMapFullFlow)
            (princ "\nMapping ekrani acilamadi."))
          (if (not (_DmtMapHasAny DMT_MAP_DATA))
            (progn
              (princ "\nMapping yapilmadi, islem iptal.")
              (setq _abort T)
            )
          )
        )
        (progn (princ "\nIslem iptal.") (setq _abort T))
      )
    )
  )

  ;; --- POZ kontrolu ---
  (if (and (not _abort)
           (= (_Trim (_DmtMapGet DMT_MAP_DATA "POZ")) ""))
    (progn
      (princ "\nPOZ eslenmemis. Once Mapping yapin.")
      (setq _abort T)
    )
  )

  ;; --- Isaret boyut ayari ---
  (if (and (not _abort) (not uiMode))
    (_DmtSettingsDialog)
  )

  ;; --- Ana islem ---
  (if (not _abort)
    (progn
      (_DmtLogClear)

      ;; CSV ac
      (if uiMode
        (progn
          (setq file "")
          (setq existed nil)
          (setq fh 'DMTPRO_SESSION_CSV))
        (progn
          (setq pack (_DmtCsvOpen))
          (setq file (nth 0 pack) existed (nth 1 pack) fh (nth 2 pack))))

      (if (null fh)
        (progn
          (princ (strcat "\nCSV yazilamadi: " (_s file)
                         "\nDosya Excel'de acik olabilir veya yazma izni yok."))
        )
        (progn
          (_DmtCsvWriteHeaderIfNew fh existed)
          (_EnsureLayer DMT_MARK_LAYER DMT_LAYER_COLOR)
          (_RegApp DMT_XDATA_APP)

          ;; Tara + filtrele + sirala
          (if (= (_DmtGetActiveKirisKolon) "")
            (princ "\nAktif KIRIS_KOLON yok. Bos birakmak icin devam edin veya once DMTEXT kullanin.")
            (princ (strcat "\nAktif KIRIS_KOLON: " (_DmtGetActiveKirisKolon)))
          )
          (princ "\nTaraniyor...")
          (_DmtStartUndo)
          (_DmtScanRun)
          (setq targets (_DmtFilterTargets DMT_SCAN_DATA DMT_MAP_DATA))

          (if (null targets)
            (progn
              (_DmtCsvClose fh)
              (_DmtDoneCommit)
              (_DmtEndUndo)
              (princ "\nHedef blok bulunamadi. Mapping'i kontrol edin."))
            (progn
              (setq skipped (_DmtCountMarked targets))
              (setq sorted (_DmtSortByPosition targets))
              (setq unmarked (_DmtRemoveMarked sorted))

              (setq idx (_DmtCsvNextIndex))
              (setq count 0)

              ;; Her kaydi isle
              (foreach rec unmarked
                (setq normRec
                  (vl-catch-all-apply '_DmtNormalizeRecord
                    (list rec DMT_MAP_DATA)))
                (if (vl-catch-all-error-p normRec)
                  (_DmtLog "ERROR"
                    (strcat "h=" (_s (cdr (assoc 'HANDLE rec))))
                    (vl-catch-all-error-message normRec))
                  (progn
                    (setq normRec
                      (_DmtNormRecSetKirisKolon normRec (_DmtGetActiveKirisKolon)))
                    (setq ok (vl-catch-all-apply '_DmtProcessOneRecord
                      (list fh idx normRec)))
                    (if (and (not (vl-catch-all-error-p ok)) ok)
                      (progn
                        (setq idx (1+ idx))
                        (setq count (1+ count))
                      )
                      (if (vl-catch-all-error-p ok)
                        (_DmtLog "ERROR"
                          (strcat "h=" (_s (cdr (assoc 'HANDLE rec))))
                          (vl-catch-all-error-message ok))
                      )
                    )
                  )
                )
              )

              (_DmtCsvClose fh)
              (_DmtDoneCommit)
              (_DmtEndUndo)
              (redraw)

              (setq warnN (_DmtLogCountByLevel "WARN"))
              (setq errN  (_DmtLogCountByLevel "ERROR"))

              ;; Ozet
              (princ (strcat "\nBitti. Yazilan: " (itoa count)
                             " | Atlanan: " (itoa skipped)
                             " | Dosya: " file))

              ;; Sonuc goster (DCL varsa dialog, yoksa command-line)
              (_DmtShowResult "DMTALL" count skipped warnN errN file)
            )
          )
        )
      )
    )
  )
  (_DmtRestoreSafeMode)
  (princ)
)

;;; ===================== DMTALAN =====================

(defun _DmtCmdAlan ( / _abort picked status p1 p2 mode uiMode
  areaScan targets pack file existed fh
  sorted unmarked idx count skipped warnN errN normRec ok)
  ;; Secili alandaki hedef bloklari toplu isle

  (_DmtInitSafeMode)
  (setq _abort nil)
  (setq uiMode (or (_DmtAdvUiModeP) (and (boundp 'DMTADV_COLLECT_MODE) DMTADV_COLLECT_MODE)))
  (_DmtSettingsLoad)

  ;; --- Mapping yukle ---
  (setq DMT_MAP_DATA (_DmtMapLoad))

  ;; --- Mapping yoksa yonlendir ---
  (if (and (not _abort) (not (_DmtMapHasAny DMT_MAP_DATA)))
    (progn
      (if (not uiMode)
        (progn
          (princ "\nMapping bulunamadi. Mapping ekranini kullanin.")
          (if (_DmtConfirm "Mapping bulunamadi. Mapping ekrani acilsin mi?")
            (progn
              (if (_DmtDclCheck)
                (_DmtMapFullFlow)
                (princ "\nMapping ekrani acilamadi."))
              (setq DMT_MAP_DATA (_DmtMapLoad))
              (if (not (_DmtMapHasAny DMT_MAP_DATA))
                (progn
                  (princ "\nMapping yapilmadi, islem iptal.")
                  (setq _abort T)
                )
              )
            )
            (progn
              (princ "\nIslem iptal.")
              (setq _abort T))))
        (setq _abort T))
    )
  )

  ;; --- POZ kontrolu ---
  (if (and (not _abort)
           (= (_Trim (_DmtMapGet DMT_MAP_DATA "POZ")) ""))
    (progn
      (if (not uiMode)
        (princ "\nPOZ eslenmemis. Once Mapping yapin."))
      (setq _abort T)
    )
  )

  ;; --- Isaret boyut ayari ---
  (if (and (not _abort) (not uiMode))
    (_DmtSettingsDialog)
  )

  ;; --- Alan sec ---
  (if (not _abort)
    (progn
      (if (and (boundp 'DMTADV_PRESET_AREA) DMTADV_PRESET_AREA)
        (progn
          (setq picked DMTADV_PRESET_AREA)
          (setq DMTADV_PRESET_AREA nil))
        (progn
          (prompt "\nToplu eklenecek alani secin: ")
          (setq picked (_DmtKntrlPickArea))))
      (setq status (_s (cdr (assoc 'STATUS picked))))
      (setq p1 (cdr (assoc 'P1 picked)))
      (setq p2 (cdr (assoc 'P2 picked)))
      (setq mode (_s (cdr (assoc 'MODE picked))))
      (if (not (and (member status '("OK" "EMPTY")) p1 p2))
        (progn
          (if (not uiMode)
            (princ "\nAlan secimi iptal edildi."))
          (setq _abort T)
        )
      )
    )
  )

  ;; --- Ana islem ---
  (if (not _abort)
    (progn
      (_DmtLogClear)
      (if (not uiMode)
        (if (= (_DmtGetActiveKirisKolon) "")
          (princ "\nAktif KIRIS_KOLON yok. Bos birakmak icin devam edin veya once DMTEXT kullanin.")
          (princ (strcat "\nAktif KIRIS_KOLON: " (_DmtGetActiveKirisKolon)))))
      (if (not uiMode)
        (princ "\nTaraniyor..."))
      (_DmtScanRun)
      (setq areaScan (_DmtFilterScanRecordsByArea DMT_SCAN_DATA p1 p2 mode))
      (setq targets (_DmtFilterTargets areaScan DMT_MAP_DATA))

      (if (null targets)
        (if (not uiMode)
          (princ "\nSecili alanda islenecek hedef blok bulunamadi. Mapping'i ve secim alanini kontrol edin."))
        (progn
          ;; CSV ac
          (if uiMode
            (progn
              (setq pack nil)
              (setq file "")
              (setq existed nil)
              (setq fh 'DMTPRO_SESSION_CSV))
            (progn
              (setq pack (_DmtCsvOpen))
              (setq file (nth 0 pack) existed (nth 1 pack) fh (nth 2 pack))))

          (if (null fh)
            (if (not uiMode)
              (princ (strcat "\nCSV yazilamadi: " (_s file) "\nDosya Excel'de acik olabilir veya yazma izni yok.")))
            (progn
              (_DmtCsvWriteHeaderIfNew fh existed)
              (if (or (not uiMode) (_DmtAdvAllowMarkDrawP))
                (_EnsureLayer DMT_MARK_LAYER DMT_LAYER_COLOR))
              (if (not uiMode)
                (_RegApp DMT_XDATA_APP))
              (_DmtStartUndo)

              (setq sorted (_DmtSortByPosition targets))
              (if uiMode
                (progn
                  (setq skipped 0)
                  (setq unmarked sorted))
                (progn
                  (setq skipped (_DmtCountMarked targets))
                  (setq unmarked (_DmtRemoveMarked sorted))))
              (setq idx (_DmtCsvNextIndex))
              (setq count 0)

              ;; Her kaydi isle
              (foreach rec unmarked
                (setq normRec
                  (vl-catch-all-apply '_DmtNormalizeRecord
                    (list rec DMT_MAP_DATA)))
                (if (vl-catch-all-error-p normRec)
                  (_DmtLog "ERROR"
                    (strcat "h=" (_s (cdr (assoc 'HANDLE rec))))
                    (vl-catch-all-error-message normRec))
                  (progn
                    (setq normRec
                      (_DmtNormRecSetKirisKolon normRec (_DmtGetActiveKirisKolon)))
                    (setq ok (vl-catch-all-apply '_DmtProcessOneRecord
                      (list fh idx normRec)))
                    (if (and (not (vl-catch-all-error-p ok)) ok)
                      (progn
                        (setq idx (1+ idx))
                        (setq count (1+ count)))
                      (if (vl-catch-all-error-p ok)
                        (_DmtLog "ERROR"
                          (strcat "h=" (_s (cdr (assoc 'HANDLE rec))))
                          (vl-catch-all-error-message ok)))))))

              (_DmtCsvClose fh)
              (if (not uiMode)
                (_DmtDoneCommit))
              (_DmtEndUndo)
              (redraw)

              (setq warnN (_DmtLogCountByLevel "WARN"))
              (setq errN  (_DmtLogCountByLevel "ERROR"))

              (if uiMode
                (setq DMT_LAST_RESULT
                  (list
                    (cons 'COMMAND  "Toplu Ekle")
                    (cons 'WRITTEN  count)
                    (cons 'SKIPPED  skipped)
                    (cons 'WARNINGS warnN)
                    (cons 'ERRORS   errN)
                    (cons 'CSV_PATH "")))
                (progn
                  (princ (strcat "\nBitti. Eklenen: " (itoa count) " | Atlanan: " (itoa skipped) " | Alan hedefi: " (itoa (length targets)) " | Dosya: " file))
                  (_DmtShowResult "Toplu Ekle" count skipped warnN errN file)))
            )
          )
        )
      )
    )
  )
  (_DmtRestoreSafeMode)
  (princ)
)

;;; ===================== DMTEXT =====================

(defun _DmtCmdText ( / txt)
  (setq txt (_DmtPromptKirisKolonText))
  (_DmtSetActiveKirisKolon txt)
  (if (= (_DmtGetActiveKirisKolon) "")
    (princ "\nAktif KIRIS_KOLON temizlendi.")
    (princ (strcat "\nAktif KIRIS_KOLON kaydedildi: " (_DmtGetActiveKirisKolon)))
  )
  (princ)
)

;;; ===================== DMTEK =====================

(defun _DmtCmdTek ( / _abort uiMode pack file existed fh count skipped done
  ss en ins normRec ok idx warnN errN)
  ;; Tek tek secim ile isle

  (_DmtInitSafeMode)
  (setq _abort nil)
  (setq uiMode (_DmtAdvUiModeP))
  (_DmtSettingsLoad)

  (setq DMT_MAP_DATA (_DmtMapLoad))

  ;; Mapping kontrolu
  (if (not (_DmtMapHasAny DMT_MAP_DATA))
    (progn
      (if (not uiMode)
        (princ "\nMapping bulunamadi. Once Mapping yapin."))
      (setq _abort T)
    )
  )

  (if (and (not _abort) (= (_Trim (_DmtMapGet DMT_MAP_DATA "POZ")) ""))
    (progn
      (if (not uiMode)
        (princ "\nPOZ eslenmemis. Once Mapping yapin."))
      (setq _abort T)
    )
  )

  (if (not _abort)
    (progn
      ;; Ayar
      (if (not uiMode) (_DmtSettingsDialog))
      (_DmtLogClear)

      ;; Scan
      (if (not uiMode)
        (princ "\nTaraniyor..."))
      (_DmtStartUndo)
      (_DmtScanRun)

      ;; CSV ac
      (if uiMode
        (progn
          (setq pack nil)
          (setq file "")
          (setq existed nil)
          (setq fh 'DMTPRO_SESSION_CSV))
        (progn
          (setq pack (_DmtCsvOpen))
          (setq file (nth 0 pack) existed (nth 1 pack) fh (nth 2 pack))))

      (if (null fh)
        (progn
          (_DmtEndUndo)
          (if (not uiMode)
            (princ (strcat "\nCSV yazilamadi: " (_s file)
                           "\nDosya Excel'de acik olabilir veya yazma izni yok."))))
        (progn
          (_DmtCsvWriteHeaderIfNew fh existed)
          (if (or (not uiMode) (_DmtAdvAllowMarkDrawP))
            (_EnsureLayer DMT_MARK_LAYER DMT_LAYER_COLOR))
          (if (not uiMode)
            (_RegApp DMT_XDATA_APP))

          (setq count 0 skipped 0 done nil)
          (setq idx (_DmtCsvNextIndex))

          (if (not uiMode)
            (progn
              (if (= (_DmtGetActiveKirisKolon) "")
                (princ "\nAktif KIRIS_KOLON yok. Bos birakmak icin devam edin veya once DMTEXT kullanin.")
                (princ (strcat "\nAktif KIRIS_KOLON: " (_DmtGetActiveKirisKolon))))
              (princ "\nSirayla POZ secin. Bitirmek icin ENTER.")))
          (while (not done)
            (prompt "\nPOZ sec (Enter=bitir): ")
            (setq ss (ssget ":S"))
            (if ss
              (progn
                (setq en (ssname ss 0))
                (setq ins (_DmtSelToPozInsert en DMT_MAP_DATA))
                (if ins
                  (if (and (not uiMode) (_IsMarked ins))
                    (progn
                      (princ "Bu blok daha once islenmis")
                      (setq skipped (1+ skipped)))
                    (progn
                      (setq normRec nil)
                      (setq normRec
                        (vl-catch-all-apply '_DmtBuildScanRecord (list ins)))
                      (if (and normRec (not (vl-catch-all-error-p normRec)))
                        (progn
                          (setq normRec
                            (_DmtNormalizeRecord normRec DMT_MAP_DATA))
                          (setq normRec
                            (_DmtNormRecSetKirisKolon normRec (_DmtGetActiveKirisKolon)))
                          (setq ok (_DmtProcessOneRecord fh idx normRec))
                          (if ok
                            (progn
                              (setq count (1+ count))
                              (setq idx (1+ idx))
                              (if (not uiMode)
                                (princ (strcat "  -> SIRA:" (itoa (1- idx))
                                               " POZ:" (_s (cdr (assoc 'POZ normRec)))))))
                            (if (not uiMode)
                              (princ "  -> Kayit uretilmedi"))))
                        (if (not uiMode)
                          (princ "  -> Attribute okunamadi")))))
                  (if (not uiMode)
                    (princ "  -> Hedef POZ degil, atlandi"))))
              (setq done T)))

          (_DmtCsvClose fh)
          (if (not uiMode)
            (_DmtDoneCommit))
          (_DmtEndUndo)
          (redraw)

          (setq warnN (_DmtLogCountByLevel "WARN"))
          (setq errN  (_DmtLogCountByLevel "ERROR"))

          (if uiMode
            (setq DMT_LAST_RESULT
              (list
                (cons 'COMMAND  "Tek Ekle")
                (cons 'WRITTEN  count)
                (cons 'SKIPPED  skipped)
                (cons 'WARNINGS warnN)
                (cons 'ERRORS   errN)
                (cons 'CSV_PATH "")))
            (progn
              (princ (strcat "\nBitti. Eklenen: " (itoa count) " | Atlanan: " (itoa skipped) " | Dosya: " file))
              (_DmtShowResult "Tek Ekle" count skipped warnN errN file)))
        )
      )
    )
  )
  (_DmtRestoreSafeMode)
  (princ)
)

;;; ===================== DMTRESET =====================

(defun _DmtCmdReset ( / n)
  (_DmtInitSafeMode)
  (_DmtSettingsLoad)

  (_RegApp DMT_XDATA_APP)
  (princ "\nTaraniyor...")
  (_DmtStartUndo)
  (_DmtScanRun)

  (if (null DMT_SCAN_DATA)
    (progn
      (_DmtEndUndo)
      (princ "\nModel Space'te attribute blok bulunamadi.")
    )
    (progn
      (setq n 0)
      (foreach rec DMT_SCAN_DATA
        (if (_IsMarked (cdr (assoc 'ENAME rec)))
          (progn
            (_UnmarkIns (cdr (assoc 'ENAME rec)))
            (setq n (1+ n))
          )
        )
      )
      (_DmtScanInvalidate)
      (_DmtDoneCommit)
      (_DmtEndUndo)
      (princ (strcat "\nSifirlandi. Temizlenen: " (itoa n)))
    )
  )
  (_DmtRestoreSafeMode)
  (princ)
)

;;; ===================== DMTKNTRL =====================

(defun c:DMTKNTRL ()
  (_DmtKntrlRun)
  (princ)
)

;;; ===================== DMTAYAR =====================

(defun _DmtCmdAyar ()
  (_DmtSettingsLoad)
  (_DmtSettingsDialog) ; kendi icinde DCL fallback var
  (princ)
)

;;; ===================== DMTLOG =====================

(defun _DmtCmdLog ()
  (if (null DMT_LOG)
    (princ "\nHenuz islem yapilmadi, log bos.")
    (_DmtLogDialog) ; kendi icinde DCL fallback var
  )
  (princ)
)

(princ)

;;; --- EMBEDDED DCL ---
(setq DMT_TEMP_DCL_PATH nil)
(defun _DmtDclPath ( / fh dir tmp)
  (if (and DMT_TEMP_DCL_PATH (findfile DMT_TEMP_DCL_PATH))
    DMT_TEMP_DCL_PATH
    (progn
      (setq tmp (vl-filename-mktemp "dmtpro_embed_v2.dcl"))
      (setq fh (open tmp "w"))
      (if fh
        (progn
          (write-line "// ============================================================" fh)
          (write-line "// DMT v35 - Dialog Tanimlari" fh)
          (write-line "// Dosya: dmt.dcl" fh)
          (write-line "// Dialoglar: dmt_map, dmt_preview, dmt_result," fh)
          (write-line "//            dmt_settings, dmt_log, dmt_confirm, dmt_kntrl" fh)
          (write-line "// ============================================================" fh)
          (write-line "" fh)
          (write-line "// ---- MAPPING EKRANI ----" fh)
          (write-line "dmt_map : dialog {" fh)
          (write-line "  label = \"DMTPRO | Tag Esleme\";" fh)
          (write-line "  initial_focus = \"POZ\";" fh)
          (write-line "" fh)
          (write-line "  : column {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Tarama Durumu\";" fh)
          (write-line "      : text { key = \"scan_summary\"; width = 62; value = \"Tarama bekleniyor...\"; }" fh)
          (write-line "      : text { width = 62; value = \"Zorunlu alan: POZ. Onerilen: CAP, ADET ve BOY.\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Alan Esleme\";" fh)
          (write-line "      : row { : text { label = \"POZ *\";   width = 14; } : popup_list { key = \"POZ\";    width = 44; } }" fh)
          (write-line "      : row { : text { label = \"CAP\";     width = 14; } : popup_list { key = \"CAP\";    width = 44; } }" fh)
          (write-line "      : row { : text { label = \"ADET\";    width = 14; } : popup_list { key = \"ADET\";   width = 44; } }" fh)
          (write-line "      : row { : text { label = \"BOY\";     width = 14; } : popup_list { key = \"BOY\";    width = 44; } }" fh)
          (write-line "      : row { : text { label = \"CARPAN\";  width = 14; } : popup_list { key = \"CARPAN\"; width = 44; } }" fh)
          (write-line "      : row { : text { label = \"KONUM\";   width = 14; } : popup_list { key = \"KONUM\";  width = 44; } }" fh)
          (write-line "      spacer;" fh)
          (write-line "      : row { : text { label = \"EK1\";     width = 14; } : popup_list { key = \"EK1\";    width = 44; } }" fh)
          (write-line "      : row { : text { label = \"EK2\";     width = 14; } : popup_list { key = \"EK2\";    width = 44; } }" fh)
          (write-line "      : row { : text { label = \"EK3\";     width = 14; } : popup_list { key = \"EK3\";    width = 44; } }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Secili Tag Ozeti\";" fh)
          (write-line "      : text { key = \"tag_info_name\";    width = 62; value = \"Tag: -\"; }" fh)
          (write-line "      : text { key = \"tag_info_count\";   width = 62; value = \"Gorulme: -\"; }" fh)
          (write-line "      : text { key = \"tag_info_blocks\";  width = 62; value = \"Blok: -\"; }" fh)
          (write-line "      : text { key = \"tag_info_samples\"; width = 62; value = \"Ornekler: -\"; }" fh)
          (write-line "      : text { width = 62; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      : button { key = \"reset\";   label = \"Sifirla\";   width = 14; }" fh)
          (write-line "      : button { key = \"preview\"; label = \"Onizleme\";  width = 14; }" fh)
          (write-line "      spacer;" fh)
          (write-line "      : button { key = \"accept\";  label = \"Kaydet\";    is_default = true; width = 14; }" fh)
          (write-line "      : button { key = \"cancel\";  label = \"Vazgec\";    is_cancel = true;  width = 14; }" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "" fh)
          (write-line "  errtile;" fh)
          (write-line "}" fh)
          (write-line "" fh)
          (write-line "// ---- ONIZLEME EKRANI ----" fh)
          (write-line "dmt_preview : dialog {" fh)
          (write-line "  label = \"DMTPRO | Esleme Onizlemesi\";" fh)
          (write-line "" fh)
          (write-line "  : column {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Onizleme\";" fh)
          (write-line "      : text { key = \"prv_header\"; width = 62; value = \"Ilk 3 hedef kaydin onizlemesi:\"; }" fh)
          (write-line "" fh)
          (write-line "      spacer;" fh)
          (write-line "" fh)
          (write-line "      : list_box {" fh)
          (write-line "        key = \"preview_list\";" fh)
          (write-line "        width = 62;" fh)
          (write-line "        height = 16;" fh)
          (write-line "      }" fh)
          (write-line "" fh)
          (write-line "      spacer;" fh)
          (write-line "" fh)
          (write-line "      : text { key = \"prv_target_count\"; width = 62; value = \"Hedef blok: -\"; }" fh)
          (write-line "      : text { key = \"prv_warn_count\";   width = 62; value = \"Uyari: -\"; }" fh)
          (write-line "      : text { width = 62; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      spacer;" fh)
          (write-line "      : button { key = \"accept\"; label = \"Kapat\"; is_default = true; width = 14; }" fh)
          (write-line "      spacer;" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "}" fh)
          (write-line "" fh)
          (write-line "// ---- SONUC EKRANI ----" fh)
          (write-line "dmt_result : dialog {" fh)
          (write-line "  label = \"DMTPRO | Islem Sonucu\";" fh)
          (write-line "" fh)
          (write-line "  : column {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Kayit Ozeti\";" fh)
          (write-line "      : row { : text { label = \"Olusturulan kayit:\"; width = 30; } : text { key = \"res_written\";  width = 28; } }" fh)
          (write-line "      : row { : text { label = \"Atlanan kayit:\";     width = 30; } : text { key = \"res_skipped\";  width = 28; } }" fh)
          (write-line "      : row { : text { label = \"Uyari sayisi:\";      width = 30; } : text { key = \"res_warnings\"; width = 28; } }" fh)
          (write-line "      : row { : text { label = \"Hata sayisi:\";       width = 30; } : text { key = \"res_errors\";   width = 28; } }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Dosya Bilgisi\";" fh)
          (write-line "      : text { key = \"res_filepath\"; width = 60; value = \"-\"; }" fh)
          (write-line "      : text { key = \"res_mode\";     width = 60; value = \"-\"; }" fh)
          (write-line "      : text { width = 60; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      : button { key = \"btn_open_csv\"; label = \"Klasoru Ac\";  width = 16; }" fh)
          (write-line "      : button { key = \"btn_show_log\"; label = \"Log Kayitlari\"; width = 16; }" fh)
          (write-line "      spacer;" fh)
          (write-line "      : button { key = \"accept\";       label = \"Kapat\";       is_default = true; width = 14; }" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "}" fh)
          (write-line "" fh)
          (write-line "// ---- AYARLAR PANELI ----" fh)
          (write-line "dmt_settings : dialog {" fh)
          (write-line "  label = \"DMTPRO | Ayarlar\";" fh)
          (write-line "" fh)
          (write-line "  : column {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"CSV\";" fh)
          (write-line "      : text { label = \"Ayirici\"; }" fh)
          (write-line "      : radio_row {" fh)
          (write-line "        : radio_button { key = \"dec_comma\"; label = \"Virgul (,)\"; value = \"1\"; }" fh)
          (write-line "        : radio_button { key = \"dec_dot\";   label = \"Nokta (.)\";  value = \"0\"; }" fh)
          (write-line "      }" fh)
          (write-line "      : text { width = 46; value = \"CSV ciktilarinda kullanilir.\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Liste\";" fh)
          (write-line "      : row {" fh)
          (write-line "        : text { label = \"Siralama\"; width = 16; }" fh)
          (write-line "        : popup_list { key = \"sort_mode\"; width = 36; }" fh)
          (write-line "      }" fh)
          (write-line "      : text { width = 46; value = \"Kayitlarin listede hangi duzende gorunecegini belirler.\"; }" fh)
          (write-line "      : text { width = 46; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      spacer;" fh)
          (write-line "      : button { key = \"accept\"; label = \"Kaydet\"; is_default = true; width = 14; }" fh)
          (write-line "      : button { key = \"cancel\"; label = \"Kapat\"; is_cancel = true;  width = 14; }" fh)
          (write-line "      spacer;" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "" fh)
          (write-line "  errtile;" fh)
          (write-line "}" fh)
          (write-line "" fh)
          (write-line "// ---- LOG GORUNTULEME ----" fh)
          (write-line "dmt_log : dialog {" fh)
          (write-line "  label = \"DMTPRO | Islem Logu\";" fh)
          (write-line "" fh)
          (write-line "  : column {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Son Calisma\";" fh)
          (write-line "      : text { key = \"log_header\";  width = 62; value = \"Son islem: -\"; }" fh)
          (write-line "      : text { key = \"log_summary\"; width = 62; value = \"Toplam: -\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Kayitlar\";" fh)
          (write-line "      : list_box {" fh)
          (write-line "        key = \"log_list\";" fh)
          (write-line "        width = 62;" fh)
          (write-line "        height = 16;" fh)
          (write-line "      }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    : text { width = 62; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      : button { key = \"btn_save\"; label = \"Disa Aktar\"; width = 16; }" fh)
          (write-line "      spacer;" fh)
          (write-line "      : button { key = \"accept\";   label = \"Kapat\"; is_default = true; width = 14; }" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "}" fh)
          (write-line "" fh)
          (write-line "// ---- ONAY DIALOG ----" fh)
          (write-line "dmt_confirm : dialog {" fh)
          (write-line "  label = \"DMTPRO | Onay\";" fh)
          (write-line "" fh)
          (write-line "  : column {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Onay Mesaji\";" fh)
          (write-line "      : text { key = \"confirm_msg\"; width = 52; value = \"Emin misiniz?\"; }" fh)
          (write-line "      : text { width = 52; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      spacer;" fh)
          (write-line "      : button { key = \"accept\"; label = \"Devam Et\"; is_default = true; width = 12; }" fh)
          (write-line "      : button { key = \"cancel\"; label = \"Vazgec\";   is_cancel = true;  width = 12; }" fh)
          (write-line "      spacer;" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "}" fh)
          (write-line "" fh)
          (write-line "// ---- DMTKNTRL KONTROL PANELI ----" fh)
          (write-line "dmt_kntrl : dialog {" fh)
          (write-line "  label = \"DMTPRO\";" fh)
          (write-line "  initial_focus = \"kntrl_go\";" fh)
          (write-line "" fh)
          (write-line "  : column {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Aktif Kayit\";" fh)
          (write-line "      : text { label = \"Aktif sira no\"; width = 18; }" fh)
          (write-line "      : text { key = \"kntrl_active_seq\"; width = 30; value = \"-\"; }" fh)
          (write-line "      spacer;" fh)
          (write-line "      : text { key = \"kntrl_nav_info\";  width = 58; value = \"Kayit: - / 0\"; }" fh)
          (write-line "      : text { key = \"kntrl_area_info\"; width = 58; value = \"Alan kaydi: 0 | Zoom: 100\"; }" fh)
          (write-line "      : text { width = 58; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Durum\";" fh)
          (write-line "      : text { key = \"kntrl_status\"; width = 58; value = \"Hazir.\"; }" fh)
          (write-line "      : text { width = 58; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Calisma Modu\";" fh)
          (write-line "      : radio_row {" fh)
          (write-line "        : radio_button { key = \"kntrl_mode_tek\";    label = \"Tek Git\";      value = \"0\"; }" fh)
          (write-line "        : radio_button { key = \"kntrl_mode_sirali\"; label = \"Sirali Gezin\"; value = \"1\"; }" fh)
          (write-line "        : radio_button { key = \"kntrl_mode_liste\";  label = \"Liste Gez\";    value = \"0\"; }" fh)
          (write-line "      }" fh)
          (write-line "" fh)
          (write-line "      spacer;" fh)
          (write-line "" fh)
          (write-line "      : row {" fh)
          (write-line "        : text { label = \"Tek sira no:\"; width = 16; }" fh)
          (write-line "        : edit_box { key = \"kntrl_tek_input\"; width = 36; }" fh)
          (write-line "      }" fh)
          (write-line "" fh)
          (write-line "      : row {" fh)
          (write-line "        : text { label = \"Liste:\"; width = 16; }" fh)
          (write-line "        : edit_box { key = \"kntrl_list_input\"; width = 36; }" fh)
          (write-line "      }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    spacer;" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      : button { key = \"kntrl_area\"; label = \"Alan Sec\"; width = 12; }" fh)
          (write-line "      : button { key = \"kntrl_go\";   label = \"Git\";      width = 12; }" fh)
          (write-line "      : button { key = \"kntrl_prev\"; label = \"Onceki\";   width = 12; }" fh)
          (write-line "      : button { key = \"kntrl_next\"; label = \"Sonraki\";  width = 12; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    : row {" fh)
          (write-line "      : button { key = \"kntrl_list\";     label = \"Listele\";     width = 12; }" fh)
          (write-line "      : button { key = \"kntrl_zoom_set\"; label = \"Zoom Ayari\";  width = 12; }" fh)
          (write-line "      : button { key = \"kntrl_rezoom\";   label = \"Tekrar Zoom\"; width = 12; }" fh)
          (write-line "      : button { key = \"cancel\";         label = \"Kapat\";       is_cancel = true; width = 12; }" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "}" fh)
          (write-line "" fh)
          (write-line "// ---- DMTPRO ANA EKRAN ----" fh)
          (write-line "dmt_adv_main : dialog {" fh)
          (write-line "  label = \"DMTPRO\";" fh)
          (write-line "" fh)
          (write-line "  : row {" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Kayit Listesi\";" fh)
          (write-line "      : text { key = \"adv_main_map_status\";   width = 94; value = \"Mapping: -\"; }" fh)
          (write-line "      : text { key = \"adv_main_dwg\";          width = 94; value = \"Cizim: -\"; }" fh)
          (write-line "      : text { key = \"adv_main_record_count\"; width = 94; value = \"Kayit: 0\"; }" fh)
          (write-line "      : text { key = \"adv_main_status\";       width = 94; value = \"Durum: Hazir\"; }" fh)
          (write-line "      : text { key = \"adv_main_header\";       width = 94; value = \"NO | POZ | ADET | CAP | ARALIK | BOY | TON | METIN\"; }" fh)
          (write-line "      : list_box { key = \"adv_main_list\"; width = 94; height = 18; }" fh)
          (write-line "      : text { key = \"adv_main_total\";        width = 94; value = \"Toplam: 0 kayit | 0 ton\"; }" fh)
          (write-line "      : text { key = \"adv_main_hint\";         width = 94; value = \"Kiris Kolon Ismi Sec ile once text, sonra Pencere/Crossing alani secin; secilen alandaki bloklar aninda bu isimle kaydolur.\"; }" fh)
          (write-line "      : text { width = 94; value = \"Bilgi icin: huseyinozdenbakir@gmail.com\"; }" fh)
          (write-line "    }" fh)
          (write-line "" fh)
          (write-line "    : boxed_column {" fh)
          (write-line "      label = \"Islemler\";" fh)
          (write-line "      : button { key = \"adv_main_mapping\";   label = \"Mapping\";   width = 18; }" fh)
          (write-line "      : button { key = \"adv_main_add\";       label = \"Ekle\";      width = 18; }" fh)
          (write-line "      : button { key = \"adv_main_add_one\";   label = \"Tek Ekle\";  width = 18; }" fh)
          (write-line "      : button { key = \"adv_main_text\";      label = \"Kiris Kolon Ismi Sec\"; width = 18; }" fh)
          (write-line "      : button { key = \"adv_main_settings\";  label = \"Ayarlar\";   width = 18; }" fh)
          (write-line "      spacer_1;" fh)
          (write-line "      : button { key = \"adv_main_csv\";       label = \"CSV Aktar\"; width = 18; }" fh)
          (write-line "      : button { key = \"adv_main_table\";     label = \"Tablo Ciz\"; width = 18; }" fh)
          (write-line "      : button { key = \"adv_main_zoom\";      label = \"Kayda Git\"; width = 18; }" fh)
          (write-line "      : button { key = \"adv_main_clear\";     label = \"Temizle\";   width = 18; }" fh)
          (write-line "      spacer_1;" fh)
          (write-line "      : button { key = \"cancel\";             label = \"Kapat\";     is_cancel = true; width = 18; }" fh)
          (write-line "    }" fh)
          (write-line "  }" fh)
          (write-line "}" fh)
          (write-line "" fh)
(write-line "// LEGACY_DISABLED_DO_NOT_USE ---- ESKI ADV DIALOG BLOKLARI KALDIRILDI ----" fh)
          (write-line "// Eski gelismis ADV dialoglari Stage Final Cleanup asamasinda aktif yoldan tamamen cikartildi." fh)
          (close fh)
          (setq DMT_TEMP_DCL_PATH tmp)
          DMT_TEMP_DCL_PATH
        )
        nil
      )
    )
  )
)
;;; --- END EMBEDDED DCL ---

;;; ============================================================
;;; DMT v35 - ADVANCED MODULE (RebarPro UI Entegrasyonu)
;;; ============================================================

; LEGACY_DISABLED_DO_NOT_USE: eski DMTADV_DATA yolu stage7 ile aktif akistan cikarildi.
(setq DMTADV_DIALOG_POS nil)
(setq DMTADV_STATE nil)
(setq DMTADV_RECORDS nil)
(setq DMTADV_LAST_STATUS "")
(setq DMTADV_MAP_READY nil)
(setq DMTADV_COLLECT_MODE nil)
(setq DMTADV_COLLECT_SOURCE "")
(setq DMTADV_RECORD_INDEX 0)
(setq DMTADV_COLLECT_ADDED 0)
(setq DMTADV_COLLECT_DUP 0)

(setq DMTADV_UI_MODE nil)
(setq DMTPRO_UI_MODE nil)
(setq DMTADV_SUPPRESS_LEGACY_CSV nil)
(setq DMTADV_SUPPRESS_LEGACY_RESULT nil)
(setq DMTADV_ALLOW_MARK_DRAW nil)
(setq DMTADV_SESSION_MODE "")
(setq DMTADV_SELECTED_INDEX nil)
(setq DMTADV_TEXT_ZONES nil)
(setq DMTADV_PRESET_AREA nil)

(defun _DmtAdvUiModeP ()
  (or (and (boundp 'DMTADV_UI_MODE) DMTADV_UI_MODE)
      (and (boundp 'DMTPRO_UI_MODE) DMTPRO_UI_MODE)
      (= (_s DMTADV_SESSION_MODE) "DMTPRO"))
)

(defun _DmtAdvSuppressLegacyCsvP ()
  (or (and (boundp 'DMTADV_SUPPRESS_LEGACY_CSV) DMTADV_SUPPRESS_LEGACY_CSV)
      (_DmtAdvUiModeP))
)

(defun _DmtAdvSuppressLegacyResultP ()
  (or (and (boundp 'DMTADV_SUPPRESS_LEGACY_RESULT) DMTADV_SUPPRESS_LEGACY_RESULT)
      (_DmtAdvUiModeP))
)

(defun _DmtAdvAllowMarkDrawP ()
  (and (_DmtAdvUiModeP)
       (boundp 'DMTADV_ALLOW_MARK_DRAW)
       DMTADV_ALLOW_MARK_DRAW)
)

(defun _DmtAdvSafeStr (v)
  (cond
    ((null v) "")
    ((= (type v) 'STR) v)
    ((numberp v)
     (if (= v (fix v))
       (itoa (fix v))
       (_FormatNumCsv v)))
    (T
     (vl-princ-to-string v)))
)

(defun _DmtAdvSetTileSafe (key val)
  (if (and key (/= (_s key) ""))
    (set_tile key (_DmtAdvSafeStr val)))
)

(defun _DmtAdvSafeInt (v)
  (cond
    ((numberp v) (fix v))
    ((= (_Trim (_s v)) "") 0)
    (T (atoi (_s v)))
  )
)

(defun _DmtAdvRecordCount ()
  (if DMTADV_RECORDS (length DMTADV_RECORDS) 0)
)

(defun _DmtAdvAssocPut (al key val / pair)
  (setq pair (assoc key al))
  (if pair
    (subst (cons key val) pair al)
    (append al (list (cons key val))))
)

(defun _DmtAdvClearRecords ()
  (setq DMTADV_RECORDS '())
  (setq DMTADV_RECORD_INDEX 0)
  (setq DMTADV_COLLECT_ADDED 0)
  (setq DMTADV_COLLECT_DUP 0)
  (setq DMTADV_COLLECT_MODE nil)
  (setq DMTADV_COLLECT_SOURCE "")
  (setq DMTADV_UI_MODE nil)
  (setq DMTPRO_UI_MODE nil)
  (setq DMTADV_SUPPRESS_LEGACY_CSV nil)
  (setq DMTADV_SUPPRESS_LEGACY_RESULT nil)
  (setq DMTADV_ALLOW_MARK_DRAW nil)
  (setq DMTADV_SESSION_MODE "")
  (setq DMTADV_SELECTED_INDEX nil)
  (setq DMTADV_TEXT_ZONES nil)
  T
)

(defun _DmtAdvRecordExistsByHandle (handle / found rec)
  (setq handle (strcase (_s handle)))
  (setq found nil)
  (if (/= handle "")
    (foreach rec DMTADV_RECORDS
      (if (= (strcase (_s (cdr (assoc 'HANDLE rec)))) handle)
        (setq found T)
      )
    )
  )
  found
)

(defun _DmtAdvNormHandle (normRec / h en ed)
  (setq h (_s (cdr (assoc 'HANDLE normRec))))
  (if (= h "")
    (progn
      (setq en (cdr (assoc 'ENAME normRec)))
      (if en
        (progn
          (setq ed (entget en))
          (setq h (_s (cdr (assoc 5 ed))))))))
  (_s h)
)

(defun _DmtAdvNormDwgFile (normRec / f)
  (setq f (_s (cdr (assoc 'DWG_FILE normRec))))
  (if (= f "")
    (setq f (_s (getvar "DWGNAME"))))
  (_s f)
)

(defun _DmtAdvZonePoint2D (pt)
  (if (and (= (type pt) 'LIST) (>= (length pt) 2))
    (list (car pt) (cadr pt))
    nil)
)

(defun _DmtAdvPointInRect (pt p1 p2 / x y minx maxx miny maxy)
  (setq pt (_DmtAdvZonePoint2D pt))
  (if (and pt p1 p2)
    (progn
      (setq x (car pt) y (cadr pt))
      (setq minx (min (car p1) (car p2)))
      (setq maxx (max (car p1) (car p2)))
      (setq miny (min (cadr p1) (cadr p2)))
      (setq maxy (max (cadr p1) (cadr p2)))
      (and (<= minx x) (<= x maxx) (<= miny y) (<= y maxy)))
    nil)
)

(defun _DmtAdvZoneTextForPoint (pt / txt zone)
  (setq txt "")
  (foreach zone DMTADV_TEXT_ZONES
    (if (_DmtAdvPointInRect pt (cdr (assoc 'P1 zone)) (cdr (assoc 'P2 zone)))
      (setq txt (_s (cdr (assoc 'TEXT zone)))))
  )
  (_CollapseSpaces txt)
)

(defun _DmtAdvApplyTextZonesToRecord (rec / zoneTxt baseTxt)
  (setq zoneTxt (_DmtAdvZoneTextForPoint (cdr (assoc 'INSERT_PT rec))))
  (setq baseTxt (_s (cdr (assoc 'KIRIS_KOLON rec))))
  (if (/= zoneTxt "")
    (_DmtAdvAssocPut rec 'KIRIS_KOLON zoneTxt)
    (_DmtAdvAssocPut rec 'KIRIS_KOLON (_CollapseSpaces baseTxt)))
)

(defun _DmtAdvRecordDisplayText (rec / txt)
  (setq txt (_s (cdr (assoc 'KIRIS_KOLON rec))))
  (if (= (_Trim txt) "")
    (_s (cdr (assoc 'ACIKLAMA rec)))
    txt)
)

(defun _DmtAdvApplyTextZonesToExistingRecords ( / out rec)
  (setq out '())
  (foreach rec DMTADV_RECORDS
    (setq out (append out (list (_DmtAdvApplyTextZonesToRecord rec))))
  )
  (setq DMTADV_RECORDS out)
  DMTADV_RECORDS
)

(defun _DmtAdvApplyTextToRect (p1 p2 txt / out rec matched)
  (setq out '())
  (setq matched 0)
  (foreach rec DMTADV_RECORDS
    (if (_DmtAdvPointInRect (cdr (assoc 'INSERT_PT rec)) p1 p2)
      (progn
        (setq rec (_DmtAdvAssocPut rec 'KIRIS_KOLON (_CollapseSpaces txt)))
        (setq matched (1+ matched)))
    )
    (setq out (append out (list rec)))
  )
  (setq DMTADV_RECORDS out)
  matched
)


(defun _DmtAdvPickZoneArea ( / mode kw p1 p2)
  (initget "Pencere Crossing")
  (setq kw (getkword "\nSecim modu [Pencere/Crossing] <Crossing>: "))
  (if (= (_s kw) "Pencere")
    (setq mode "_W")
    (setq mode "_C")
  )
  (setq p1 (getpoint "\nIlk koseyi secin: "))
  (if p1
    (progn
      (setq p2 (getcorner p1 "\nKarsi koseyi secin: "))
      (if p2
        (list (cons 'STATUS "OK") (cons 'P1 p1) (cons 'P2 p2) (cons 'MODE mode))
        (list (cons 'STATUS "CANCEL") (cons 'P1 p1) (cons 'P2 nil) (cons 'MODE mode))
      )
    )
    (list (cons 'STATUS "CANCEL") (cons 'P1 nil) (cons 'P2 nil) (cons 'MODE mode))
  )
)

(defun _DmtAdvCountBlocksInRect (p1 p2 mode / ss)
  (setq ss (ssget mode p1 p2 '((0 . "INSERT") (410 . "Model"))))
  (if ss (sslength ss) 0)
)

(defun _DmtAdvPromptTextZone ( / picked en txt area status p1 p2 mode blkCount)
  (setq picked (entsel "\nText secin: "))
  (if (null picked)
    nil
    (progn
      (setq en (car picked))
      (if (not (_DmtTextEntityP en))
        (progn
          (princ "\nLutfen yalnizca TEXT veya MTEXT secin.")
          nil
        )
        (progn
          (setq txt (_DmtReadPickedText en))
          (if (= (_Trim txt) "")
            (progn
              (princ "\nSecilen text bos.")
              nil
            )
            (progn
              (prompt (strcat "\n[" txt "] icin alan secin."))
              (setq area (_DmtAdvPickZoneArea))
              (setq status (_s (cdr (assoc 'STATUS area))))
              (setq p1 (cdr (assoc 'P1 area)))
              (setq p2 (cdr (assoc 'P2 area)))
              (setq mode (_s (cdr (assoc 'MODE area))))
              (if (not (and (= status "OK") p1 p2))
                nil
                (progn
                  (setq blkCount (_DmtAdvCountBlocksInRect p1 p2 mode))
                  (list
                    (cons 'TEXT (_CollapseSpaces txt))
                    (cons 'TEXT_HANDLE (_s (cdr (assoc 5 (entget en)))))
                    (cons 'P1 p1)
                    (cons 'P2 p2)
                    (cons 'MODE mode)
                    (cons 'BLOCK_COUNT blkCount)
                  )
                )
              )
            )
          )
        )
      )
    )
  )
)

(defun _DmtAdvRunTextZone ( / zone txt blkCount p1 p2 mode oldTxt runRes stats added dup total updated errMsg)
  (setq zone (_DmtAdvPromptTextZone))
  (if zone
    (progn
      (setq txt (_s (cdr (assoc 'TEXT zone))))
      (setq blkCount (cdr (assoc 'BLOCK_COUNT zone)))
      (setq p1 (cdr (assoc 'P1 zone)))
      (setq p2 (cdr (assoc 'P2 zone)))
      (setq mode (_s (cdr (assoc 'MODE zone))))
      (if (not (numberp blkCount))
        (setq blkCount 0)
      )
      (setq DMTADV_TEXT_ZONES (append DMTADV_TEXT_ZONES (list zone)))
      (setq updated (_DmtAdvApplyTextToRect p1 p2 txt))
      (setq oldTxt (_DmtGetActiveKirisKolon))
      (_DmtSetActiveKirisKolon txt)
      (if DMTADV_MAP_READY
        (progn
          (_DmtAdvCollectBegin "TEXT ALAN")
          (setq DMTADV_PRESET_AREA
            (list
              (cons 'STATUS "OK")
              (cons 'P1 p1)
              (cons 'P2 p2)
              (cons 'MODE mode)))
          (setq runRes (vl-catch-all-apply '_DmtCmdAlan '()))
          (setq stats (_DmtAdvCollectEnd))
          (setq added (cdr (assoc 'ADDED stats)))
          (setq dup   (cdr (assoc 'DUPLICATE stats)))
          (setq total (cdr (assoc 'TOTAL stats)))
          (if (vl-catch-all-error-p runRes)
            (progn
              (setq errMsg (vl-catch-all-error-message runRes))
              (setq DMTADV_LAST_STATUS
                (strcat "Text Alan islemi tamamlanamadi: " (_DmtAdvSafeStr errMsg))))
            (setq DMTADV_LAST_STATUS
              (strcat
                txt " metni uygulandi. "
                (itoa (_DmtAdvSafeInt added)) " yeni kayit eklendi"
                (if (> (_DmtAdvSafeInt dup) 0)
                  (strcat ", " (itoa (_DmtAdvSafeInt dup)) " kayit zaten vardi")
                  "")
                (if (> (_DmtAdvSafeInt updated) 0)
                  (strcat ", " (itoa (_DmtAdvSafeInt updated)) " mevcut kayit guncellendi")
                  "")
                ". Toplam kayit: " (itoa (_DmtAdvSafeInt total)) "."
              )))
        )
        (setq DMTADV_LAST_STATUS "Mapping eksik."))
      (_DmtSetActiveKirisKolon oldTxt)
      (setq DMTADV_PRESET_AREA nil)
      (_DmtAdvStateSync)
      T
    )
    (progn
      (setq DMTADV_LAST_STATUS "Text alani secimi iptal edildi.")
      (_DmtAdvStateSync)
      nil
    )
  )
)

(defun _DmtAdvRecordFromNorm (normRec / kg tonStr capStr adetStr aciklama boyVal boyStr handleVal dwgFileVal textVal rec)
  (setq kg (cdr (assoc 'AGIRLIK_KG normRec)))
  (if (and kg (> kg 0.0))
    (setq tonStr (_FormatNumCsv (/ kg 1000.0)))
    (setq tonStr "")
  )
  (if (> (cdr (assoc 'CAP_MM normRec)) 0.0)
    (setq capStr (_FormatNumCsv (cdr (assoc 'CAP_MM normRec))))
    (setq capStr "")
  )
  (setq boyVal (cdr (assoc 'BOY_M normRec)))
  (cond
    ((numberp boyVal)
     (setq boyStr (_FormatNumCsv boyVal)))
    ((/= (_s boyVal) "")
     (setq boyStr (_s boyVal)))
    ((numberp (cdr (assoc 'BOY_CM_NORM normRec)))
     (setq boyStr (_FormatNumCsv (/ (cdr (assoc 'BOY_CM_NORM normRec)) 100.0))))
    (T
     (setq boyStr (_s (cdr (assoc 'BOY_CM_NORM normRec)))))
  )
  (setq adetStr (_NumToStrCsv (cdr (assoc 'ADET normRec))))
  (setq handleVal (_DmtAdvNormHandle normRec))
  (setq dwgFileVal (_DmtAdvNormDwgFile normRec))
  (setq textVal (_CollapseSpaces (_s (cdr (assoc 'KIRIS_KOLON normRec)))))
  (setq aciklama (_DmtNormYer normRec))
  (if (= (_s aciklama) "")
    (setq aciklama (_s (cdr (assoc 'BLOCK_NAME normRec))))
  )
  (setq rec
    (list
      (cons 'NO 0)
      (cons 'HANDLE handleVal)
      (cons 'DWG_FILE dwgFileVal)
      (cons 'POZ (_s (cdr (assoc 'POZ normRec))))
      (cons 'ADET adetStr)
      (cons 'CAP capStr)
      (cons 'ARALIK "")
      (cons 'BOY boyStr)
      (cons 'TON tonStr)
      (cons 'KIRIS_KOLON textVal)
      (cons 'ACIKLAMA (_s aciklama))
      (cons 'STATUS "OK")
      (cons 'KAYNAK_TIPI (_s DMTADV_COLLECT_SOURCE))
      (cons 'LAYER (_s (cdr (assoc 'LAYER normRec))))
      (cons 'BLOCK_NAME (_s (cdr (assoc 'BLOCK_NAME normRec))))
      (cons 'INSERT_PT
        (list
          (cdr (assoc 'X normRec))
          (cdr (assoc 'Y normRec))
        ))))
  (_DmtAdvApplyTextZonesToRecord rec)
)

(defun _DmtAdvAppendRecordSafe (rec / handle rec2)
  (setq handle (_s (cdr (assoc 'HANDLE rec))))
  (cond
    ((= handle "")
     (if DMTADV_COLLECT_MODE
       (setq DMTADV_COLLECT_DUP (1+ DMTADV_COLLECT_DUP)))
     nil
    )
    ((_DmtAdvRecordExistsByHandle handle)
     (if DMTADV_COLLECT_MODE
       (setq DMTADV_COLLECT_DUP (1+ DMTADV_COLLECT_DUP)))
     'DUPLICATE
    )
    (T
     (setq DMTADV_RECORD_INDEX (1+ (_DmtAdvRecordCount)))
     (setq rec2 (_DmtAdvAssocPut rec 'NO DMTADV_RECORD_INDEX))
     (setq DMTADV_RECORDS (append DMTADV_RECORDS (list rec2)))
     (if DMTADV_COLLECT_MODE
       (setq DMTADV_COLLECT_ADDED (1+ DMTADV_COLLECT_ADDED)))
     'ADDED
    )
  )
)

(defun _DmtAdvCollectBegin (source)
  (if (null DMTADV_RECORDS)
    (setq DMTADV_RECORDS '()))
  (setq DMTADV_RECORD_INDEX (_DmtAdvRecordCount))
  (setq DMTADV_COLLECT_SOURCE (_s source))
  (setq DMTADV_COLLECT_ADDED 0)
  (setq DMTADV_COLLECT_DUP 0)
  (setq DMTADV_COLLECT_MODE T)
  (setq DMTADV_UI_MODE T)
  (setq DMTPRO_UI_MODE T)
  (setq DMTADV_SESSION_MODE "DMTPRO")
  (setq DMTADV_SUPPRESS_LEGACY_CSV T)
  (setq DMTADV_SUPPRESS_LEGACY_RESULT T)
  (setq DMTADV_ALLOW_MARK_DRAW T)
  T
)

(defun _DmtAdvCollectEnd ()
  (setq DMTADV_COLLECT_MODE nil)
  (setq DMTADV_UI_MODE nil)
  (setq DMTPRO_UI_MODE nil)
  (setq DMTADV_SESSION_MODE "")
  (setq DMTADV_SUPPRESS_LEGACY_CSV nil)
  (setq DMTADV_SUPPRESS_LEGACY_RESULT nil)
  (setq DMTADV_ALLOW_MARK_DRAW nil)
  (list
    (cons 'ADDED DMTADV_COLLECT_ADDED)
    (cons 'DUPLICATE DMTADV_COLLECT_DUP)
    (cons 'TOTAL (_DmtAdvRecordCount))
    (cons 'SOURCE (_s DMTADV_COLLECT_SOURCE))
  )
)

(defun _DmtAdvMapReadyP (mapData / pozTag)
  (setq pozTag (_s (_DmtMapGet mapData "POZ")))
  (and mapData (_DmtMapHasAny mapData) (/= pozTag ""))
)

(defun _DmtAdvStateSync ()
  (if (null DMTADV_RECORDS)
    (setq DMTADV_RECORDS '()))
  (if (= (_s DMTADV_LAST_STATUS) "")
    (setq DMTADV_LAST_STATUS "Hazir"))
  (if (null DMT_MAP_DATA)
    (setq DMT_MAP_DATA (_DmtMapLoad)))
  (setq DMTADV_MAP_READY (_DmtAdvMapReadyP DMT_MAP_DATA))
  (setq DMTADV_RECORD_INDEX (_DmtAdvRecordCount))
  (setq DMTADV_STATE
    (list
      (cons 'MAP_READY DMTADV_MAP_READY)
      (cons 'DWGNAME (_s (getvar "DWGNAME")))
      (cons 'RECORD_COUNT (_DmtAdvRecordCount))
      (cons 'RECORD_INDEX DMTADV_RECORD_INDEX)
      (cons 'LAST_STATUS (_s DMTADV_LAST_STATUS))))
  DMTADV_STATE
)

(defun _DmtAdvResetState ()
  (_DmtAdvClearRecords)
  (setq DMTADV_SUPPRESS_LEGACY_CSV nil)
  (setq DMTADV_SUPPRESS_LEGACY_RESULT nil)
  (setq DMTADV_ALLOW_MARK_DRAW nil)
  (setq DMTADV_LAST_STATUS "Temizlendi.")
  (_DmtAdvStateSync)
)

(defun _DmtAdvNormalizeSelectedIndex ( / n idx)
  (setq n (_DmtAdvRecordCount))
  (cond
    ((<= n 0)
     (setq DMTADV_SELECTED_INDEX nil))
    ((and (numberp DMTADV_SELECTED_INDEX)
          (>= DMTADV_SELECTED_INDEX 0)
          (< DMTADV_SELECTED_INDEX n))
     DMTADV_SELECTED_INDEX)
    (T
     (setq DMTADV_SELECTED_INDEX 0)))
  DMTADV_SELECTED_INDEX
)

(defun _DmtAdvOnListSelect (val)
  (setq DMTADV_SELECTED_INDEX (_DmtAdvSafeInt val))
  (princ)
)

(defun _DmtAdvSelectedIndex ()
  (_DmtAdvNormalizeSelectedIndex)
)

(defun _DmtAdvSelectedRecord ( / idx recs)
  (setq recs (_DmtAdvVisibleRecords))
  (setq idx (_DmtAdvSelectedIndex))
  (if (and recs idx (>= idx 0) (< idx (length recs)))
    (nth idx recs)
    nil)
)

(defun _DmtAdvRecordPoint (rec / pt h en)
  (setq pt (cdr (assoc 'INSERT_PT rec)))
  (cond
    ((and (= (type pt) 'LIST) (>= (length pt) 2))
     (list (car pt) (cadr pt) (if (and (>= (length pt) 3) (numberp (caddr pt))) (caddr pt) 0.0)))
    (T
     (setq h (_s (cdr (assoc 'HANDLE rec))))
     (if (/= h "")
       (progn
         (setq en (handent h))
         (if en (_DmtSafePoint en) nil))
       nil)))
)

(defun _DmtAdvZoomSelected ( / rec pt)
  (setq rec (_DmtAdvSelectedRecord))
  (cond
    ((null rec)
     (setq DMTADV_LAST_STATUS "Secili kayit bulunamadi."))
    (T
     (setq pt (_DmtAdvRecordPoint rec))
     (if (_DmtKntrlZoomPoint pt)
       (setq DMTADV_LAST_STATUS "Secili kayda zoom yapildi.")
       (setq DMTADV_LAST_STATUS "Secili kayit bulunamadi."))))
  (_DmtAdvStateSync)
  T
)

(defun _DmtAdvPadRight (s n / txt)
  (setq txt (_DmtAdvSafeStr s))
  (if (> (strlen txt) n)
    (setq txt (_TruncStr txt n))
  )
  (while (< (strlen txt) n)
    (setq txt (strcat txt " "))
  )
  txt
)

(defun _DmtAdvMainHeaderLine ()
  (strcat
    (_DmtAdvPadRight "NO" 4) " | "
    (_DmtAdvPadRight "POZ" 10) " | "
    (_DmtAdvPadRight "ADET" 6) " | "
    (_DmtAdvPadRight "CAP" 5) " | "
    (_DmtAdvPadRight "ARALIK" 8) " | "
    (_DmtAdvPadRight "BOY" 10) " | "
    (_DmtAdvPadRight "TON" 8) " | "
    (_DmtAdvPadRight "METIN" 24)
  )
)

(defun _DmtAdvMainRowLine (rec)
  (strcat
    (_DmtAdvPadRight (_DmtAdvRecVal rec 'NO) 4) " | "
    (_DmtAdvPadRight (_DmtAdvRecVal rec 'POZ) 10) " | "
    (_DmtAdvPadRight (_DmtAdvRecVal rec 'ADET) 6) " | "
    (_DmtAdvPadRight (_DmtAdvRecVal rec 'CAP) 5) " | "
    (_DmtAdvPadRight (_DmtAdvRecVal rec 'ARALIK) 8) " | "
    (_DmtAdvPadRight (_DmtAdvRecVal rec 'BOY) 10) " | "
    (_DmtAdvPadRight (_DmtAdvRecVal rec 'TON) 8) " | "
    (_DmtAdvPadRight (_TruncStr (_DmtAdvRecordDisplayText rec) 24) 24)
  )
)

(defun _DmtAdvRefreshMainList ( / records rec line totalTon idx)
  (if (and (boundp 'DMTADV_RECORDS) DMTADV_RECORDS)
    (setq records DMTADV_RECORDS)
    (setq records '())
  )
  (_DmtAdvNormalizeSelectedIndex)
  (_DmtAdvSetTileSafe "adv_main_header" (_DmtAdvMainHeaderLine))
  (start_list "adv_main_list")
  (foreach rec records
    (setq line (_DmtAdvSafeStr (_DmtAdvMainRowLine rec)))
    (add_list (_DmtAdvSafeStr line))
  )
  (end_list)
  (setq idx (_DmtAdvSelectedIndex))
  (if (and idx records)
    (_DmtAdvSetTileSafe "adv_main_list" (itoa idx)))
  (setq totalTon (_DmtAdvSafeStr (_FormatNumCsv (_DmtAdvTotalTon))))
  (_DmtAdvSetTileSafe "adv_main_total"
    (strcat "Toplam: " (_DmtAdvSafeStr (length records))
            " kayit | " totalTon " ton"))
)

(defun _DmtAdvRefreshMainDialog ()
  (_DmtAdvStateSync)
  (_DmtAdvSetTileSafe "adv_main_map_status"
    (strcat "Mapping: " (if DMTADV_MAP_READY "Hazir" "Eksik")))
  (_DmtAdvSetTileSafe "adv_main_dwg"
    (strcat "Cizim: " (_DmtAdvSafeStr (getvar "DWGNAME"))))
  (_DmtAdvSetTileSafe "adv_main_record_count"
    (strcat "Kayit: " (_DmtAdvSafeStr (_DmtAdvRecordCount))))
  (_DmtAdvSetTileSafe "adv_main_status"
    (strcat "Durum: " (_TruncStr (_DmtAdvSafeStr DMTADV_LAST_STATUS) 84)))
  (_DmtAdvRefreshMainList)
)

(defun _DmtAdvMainDialog ( / dclId dclPath result ok refreshRes)
  (setq dclPath (_DmtDclPath))
  (if (null dclPath)
    (progn
      (setq DMTADV_LAST_STATUS "Ana ekran acilamadi.")
      (_DmtAdvStateSync)
      0)
    (progn
      (setq dclId (load_dialog dclPath))
      (setq ok
        (if (and DMTADV_DIALOG_POS (listp DMTADV_DIALOG_POS))
          (new_dialog "dmt_adv_main" dclId "" DMTADV_DIALOG_POS)
          (new_dialog "dmt_adv_main" dclId)))
      (if (and dclId ok)
        (progn
          (setq refreshRes (vl-catch-all-apply '_DmtAdvRefreshMainDialog '()))
          (if (vl-catch-all-error-p refreshRes)
            (progn
              (unload_dialog dclId)
              (setq DMTADV_LAST_STATUS
                (strcat "Ana tablo yenilenemedi: " (_DmtAdvSafeStr (vl-catch-all-error-message refreshRes))))
              (_DmtAdvStateSync)
              0)
            (progn
              (action_tile "adv_main_list"     "(_DmtAdvOnListSelect $value)")
              (action_tile "adv_main_mapping"  "(setq DMTADV_DIALOG_POS (done_dialog 2))")
              (action_tile "adv_main_add"      "(setq DMTADV_DIALOG_POS (done_dialog 3))")
              (action_tile "adv_main_add_one"  "(setq DMTADV_DIALOG_POS (done_dialog 4))")
              (action_tile "adv_main_text"     "(setq DMTADV_DIALOG_POS (done_dialog 10))")
              (action_tile "adv_main_settings" "(setq DMTADV_DIALOG_POS (done_dialog 5))")
              (action_tile "adv_main_csv"      "(setq DMTADV_DIALOG_POS (done_dialog 6))")
              (action_tile "adv_main_table"    "(setq DMTADV_DIALOG_POS (done_dialog 7))")
              (action_tile "adv_main_clear"    "(setq DMTADV_DIALOG_POS (done_dialog 8))")
              (action_tile "adv_main_zoom"     "(setq DMTADV_DIALOG_POS (done_dialog 9))")
              (action_tile "cancel"            "(setq DMTADV_DIALOG_POS (done_dialog 0))")
              (setq result (start_dialog))
              (unload_dialog dclId)
              result)))
        (progn
          (if dclId (unload_dialog dclId))
          (setq DMTADV_LAST_STATUS "Ana ekran yuklenemedi.")
          (_DmtAdvStateSync)
          0))))
)

(defun _DmtAdvEnsureMapping ( / ok)
  (setq DMT_MAP_DATA (_DmtMapLoad))
  (setq DMTADV_MAP_READY (_DmtAdvMapReadyP DMT_MAP_DATA))
  (_DmtAdvStateSync)
  (if DMTADV_MAP_READY
    T
    (progn
      (setq DMTADV_LAST_STATUS
        "Mapping eksik. Mapping ekrani aciliyor.")
      (_DmtAdvStateSync)
      (setq ok (_DmtMapFullFlow))
      (setq DMT_MAP_DATA (_DmtMapLoad))
      (setq DMTADV_MAP_READY (_DmtAdvMapReadyP DMT_MAP_DATA))
      (if DMTADV_MAP_READY
        (progn
          (setq DMTADV_LAST_STATUS "Mapping hazir.")
          (_DmtAdvStateSync)
          T)
        (progn
          (if ok
            (setq DMTADV_LAST_STATUS "Mapping eksik. Zorunlu alanlari tamamlayin.")
            (setq DMTADV_LAST_STATUS "Mapping iptal edildi."))
          (_DmtAdvStateSync)
          nil)))))

(defun _DmtAdvRunMap ( / ok)
  (setq ok (_DmtMapFullFlow))
  (setq DMT_MAP_DATA (_DmtMapLoad))
  (setq DMTADV_MAP_READY (_DmtAdvMapReadyP DMT_MAP_DATA))
  (if DMTADV_MAP_READY
    (setq DMTADV_LAST_STATUS "Mapping guncellendi.")
    (if ok
      (setq DMTADV_LAST_STATUS "Mapping eksik. Zorunlu alanlari tamamlayin.")
      (setq DMTADV_LAST_STATUS "Mapping degismedi.")))
  (_DmtAdvStateSync)
  DMTADV_MAP_READY
)

(defun _DmtAdvBuildAddStatus (added dup total / found msg)
  (setq added (_DmtAdvSafeInt added))
  (setq dup (_DmtAdvSafeInt dup))
  (setq total (_DmtAdvSafeInt total))
  (setq found (+ added dup))
  (cond
    ((and (> added 0) (> dup 0))
      (setq msg
        (strcat
          (itoa found) " kayit bulundu. "
          (itoa added) " yeni kayit eklendi ve pozlar cizildi, "
          (itoa dup) " kayit zaten vardi."
          " Toplam kayit: " (itoa total) ".")))
    ((> added 0)
      (setq msg
        (strcat
          (itoa added) " kayit eklendi ve pozlar cizildi."
          " Toplam kayit: " (itoa total) ".")))
    ((> dup 0)
      (setq msg
        (strcat
          (itoa found) " kayit bulundu, "
          (itoa dup) " kayit zaten mevcut.")))
    (T
      (setq msg "Yeni kayit eklenmedi.")))
  msg
)

(defun _DmtAdvRunBulkAdd ( / runRes stats added dup total errMsg)
  (if DMTADV_MAP_READY
    (progn
      (_DmtAdvCollectBegin "EKLE")
      (setq runRes (vl-catch-all-apply '_DmtCmdAlan '()))
      (setq stats (_DmtAdvCollectEnd))
      (setq added (cdr (assoc 'ADDED stats)))
      (setq dup   (cdr (assoc 'DUPLICATE stats)))
      (setq total (cdr (assoc 'TOTAL stats)))
      (if (vl-catch-all-error-p runRes)
        (progn
          (setq errMsg (vl-catch-all-error-message runRes))
          (setq DMTADV_LAST_STATUS
            (strcat "Ekle islemi tamamlanamadi: " (_DmtAdvSafeStr errMsg))))
        (setq DMTADV_LAST_STATUS (_DmtAdvBuildAddStatus added dup total))
      )
    )
    (setq DMTADV_LAST_STATUS "Mapping eksik."))
  (_DmtAdvStateSync)
  T
)

(defun _DmtAdvRunSingleAdd ( / runRes stats added dup total errMsg)
  (if DMTADV_MAP_READY
    (progn
      (_DmtAdvCollectBegin "TEK EKLE")
      (setq runRes (vl-catch-all-apply '_DmtCmdTek '()))
      (setq stats (_DmtAdvCollectEnd))
      (setq added (cdr (assoc 'ADDED stats)))
      (setq dup   (cdr (assoc 'DUPLICATE stats)))
      (setq total (cdr (assoc 'TOTAL stats)))
      (if (vl-catch-all-error-p runRes)
        (progn
          (setq errMsg (vl-catch-all-error-message runRes))
          (setq DMTADV_LAST_STATUS
            (strcat "Tek ekle islemi tamamlanamadi: " (_DmtAdvSafeStr errMsg))))
        (setq DMTADV_LAST_STATUS (_DmtAdvBuildAddStatus added dup total))
      )
    )
    (setq DMTADV_LAST_STATUS "Mapping eksik."))
  (_DmtAdvStateSync)
  T
)

(defun _DmtAdvRunSettings ()
  (_DmtCmdAyar)
  (setq DMTADV_LAST_STATUS "Ayarlar kapatildi.")
  (_DmtAdvStateSync)
  T
)

(defun _DmtAdvVisibleRecords ()
  (if (and (boundp 'DMTADV_RECORDS) DMTADV_RECORDS)
    DMTADV_RECORDS
    '())
)

(defun _DmtAdvRecVal (rec key)
  (_DmtAdvSafeStr (cdr (assoc key rec)))
)

(defun _DmtAdvNumVal (v / s)
  (cond
    ((numberp v) v)
    (T
      (setq s (_Trim (_s v)))
      (if (= s "")
        0.0
        (atof (_ReplaceAll s "," ".")))))
)

(defun _DmtAdvTotalTon ( / total rec)
  (setq total 0.0)
  (foreach rec (_DmtAdvVisibleRecords)
    (setq total (+ total (_DmtAdvNumVal (cdr (assoc 'TON rec)))))
  )
  total
)

(defun _DmtAdvCsvHeaders ()
  (list "NO" "POZ" "ADET" "CAP" "ARALIK" "BOY" "TON" "HANDLE" "DWG_FILE" "ACIKLAMA" "STATUS" "KIRIS_KOLON")
)

(defun _DmtAdvCsvEsc (s)
  (setq s (_ReplaceAll (_CleanVal (_s s)) "\"" "\"\""))
  (strcat "\"" s "\"")
)

(defun _DmtAdvCsvCellOut (c)
  (if (and (= (type c) 'LIST) (= (car c) 'RAW))
    (_DmtAdvSafeStr (cdr c))
    (_DmtAdvCsvEsc (_DmtAdvSafeStr c))
  )
)

(defun _DmtAdvCsvLineCore (cells / out first)
  (setq out "" first T)
  (foreach c cells
    (if first
      (setq out (_DmtAdvCsvCellOut c))
      (setq out (strcat out ";" (_DmtAdvCsvCellOut c))))
    (setq first nil)
  )
  out
)

(defun _DmtAdvCsvLine (cells)
  (_DmtAdvCsvLineCore cells)
)

(defun _DMTADVCSVLINE (cells)
  (_DmtAdvCsvLineCore cells)
)

(defun _DmtAdvCsvHandleCell (rec / h)
  (setq h (_DmtAdvSafeStr (_DmtAdvRecVal rec 'HANDLE)))
  (if (= h "")
    ""
    (cons 'RAW (strcat "=" (chr 34) h (chr 34)))
  )
)

(defun _DmtAdvCsvRowFromRecord (rec)
  (list
    (_DmtAdvRecVal rec 'NO)
    (_DmtAdvRecVal rec 'POZ)
    (_DmtAdvRecVal rec 'ADET)
    (_DmtAdvRecVal rec 'CAP)
    (_DmtAdvRecVal rec 'ARALIK)
    (_DmtAdvRecVal rec 'BOY)
    (_DmtAdvRecVal rec 'TON)
    (_DmtAdvCsvHandleCell rec)
    (_DmtAdvRecVal rec 'DWG_FILE)
    (_DmtAdvRecVal rec 'ACIKLAMA)
    (_DmtAdvRecVal rec 'STATUS)
    (_DmtAdvRecVal rec 'KIRIS_KOLON)
  )
)

(defun _DmtAdvLegendKeyFromRecord (rec)
  (_DmtAdvSafeStr (_DmtAdvRecVal rec 'CAP))
)

(defun _DmtAdvLegendRows (records / rows rec key pair ton cap item)
  (setq rows '())
  (foreach rec records
    (setq key (_DmtAdvLegendKeyFromRecord rec))
    (setq ton (_DmtAdvNumVal (_DmtAdvRecVal rec 'TON)))
    (setq pair (assoc key rows))
    (if pair
      (setq rows
        (subst
          (cons key (_DmtAdvAssocPut (cdr pair) 'TON (+ (_DmtAdvNumVal (cdr (assoc 'TON (cdr pair)))) ton)))
          pair rows))
      (progn
        (setq cap (_DmtAdvSafeStr (_DmtAdvRecVal rec 'CAP)))
        (setq item (list (cons 'CAP cap) (cons 'TON ton)))
        (setq rows (append rows (list (cons key item)))))))
  (mapcar 'cdr rows)
)

(defun _DmtAdvLegendHeaderCells ()
  (list "LEJANT" "CAP" "TOPLAM_TON")
)

(defun _DmtAdvLegendRowCells (row)
  (list
    "DONATI"
    (_DmtAdvSafeStr (cdr (assoc 'CAP row)))
    (_FormatNumCsv (_DmtAdvNumVal (cdr (assoc 'TON row)))))
)

(defun _DmtAdvWriteLegendCsv (fh records / rows row)
  (setq rows (_DmtAdvLegendRows records))
  (if rows
    (progn
      (write-line "" fh)
      (write-line (_DmtAdvCsvLineCore (_DmtAdvLegendHeaderCells)) fh)
      (foreach row rows
        (write-line (_DmtAdvCsvLineCore (_DmtAdvLegendRowCells row)) fh))
      T)
    nil)
)

(defun _DmtAdvExportCsvPath ()
  (_DmtExportBasePath "_DMTPRO.csv")
)

(defun _DmtAdvExportRecordsCsv ( / path fh count records row)
  (setq records (_DmtAdvVisibleRecords))
  (if (null records)
    nil
    (progn
      (setq path (_DmtAdvExportCsvPath))
      (setq fh (open path "w"))
      (if fh
        (progn
          (write-line (_DmtAdvCsvLineCore (_DmtAdvCsvHeaders)) fh)
          (setq count 0)
          (foreach rec records
            (setq row (_DmtAdvCsvRowFromRecord rec))
            (if (= (_DmtAdvSafeStr (_DmtAdvRecVal rec 'HANDLE)) "")
              (_DmtLog "WARN" "csv" "HANDLE bos kayit CSV'ye yaziliyor."))
            (if (= (_DmtAdvSafeStr (_DmtAdvRecVal rec 'DWG_FILE)) "")
              (_DmtLog "WARN" "csv" "DWG_FILE bos kayit CSV'ye yaziliyor."))
            (write-line (_DmtAdvCsvLineCore row) fh)
            (setq count (1+ count))
          )
          (_DmtAdvWriteLegendCsv fh records)
          (close fh)
          (list (cons 'PATH path) (cons 'COUNT count))
        )
        nil
      )
    )
  )
)

(defun _DmtAdvTableHeaders ()
  (list "NO" "POZ" "ADET" "CAP" "ARALIK" "BOY" "TON" "ACIKLAMA")
)

(defun _DmtAdvTableRowFromRecord (rec)
  (list
    (_DmtAdvRecVal rec 'NO)
    (_DmtAdvRecVal rec 'POZ)
    (_DmtAdvRecVal rec 'ADET)
    (_DmtAdvRecVal rec 'CAP)
    (_DmtAdvRecVal rec 'ARALIK)
    (_DmtAdvRecVal rec 'BOY)
    (_DmtAdvRecVal rec 'TON)
    (_TruncStr (_DmtAdvRecVal rec 'ACIKLAMA) 64)
  )
)

(defun _DmtAdvSumList (lst / total)
  (setq total 0.0)
  (foreach x lst (setq total (+ total x)))
  total
)

(defun _DmtAdvDrawTextCell (space pt txt th / obj)
  (setq obj (vl-catch-all-apply 'vla-AddText (list space (_s txt) (vlax-3d-point pt) th)))
  (if (not (vl-catch-all-error-p obj)) obj nil)
)

(defun _DmtAdvDrawRecordsTableFallback (pt / space scale rh th widths rows totalRows totalWidth x0 y0 z0 r y x row cells w xcur textPt records)
  (setq space (_DmtCurrentSpace))
  (setq scale (getvar "DIMSCALE"))
  (if (or (not scale) (= scale 0.0)) (setq scale 1.0))
  (setq rh (* 5.0 scale))
  (setq th (* 2.2 scale))
  (setq widths (list (* 8.0 scale) (* 16.0 scale) (* 12.0 scale) (* 10.0 scale) (* 12.0 scale) (* 12.0 scale) (* 12.0 scale) (* 36.0 scale)))
  (setq records (_DmtAdvVisibleRecords))
  (setq rows
    (append
      (list (_DmtAdvTableHeaders))
      (mapcar '_DmtAdvTableRowFromRecord records)
      (list (list "" "" "" "" "" "TOPLAM TON" (_FormatNumCsv (_DmtAdvTotalTon)) ""))))
  (setq totalRows (length rows))
  (setq totalWidth (_DmtAdvSumList widths))
  (setq x0 (car pt))
  (setq y0 (cadr pt))
  (setq z0 (if (caddr pt) (caddr pt) 0.0))
  (setq r 0)
  (while (<= r totalRows)
    (setq y (- y0 (* r rh)))
    (vl-catch-all-apply 'vla-AddLine
      (list space (vlax-3d-point (list x0 y z0)) (vlax-3d-point (list (+ x0 totalWidth) y z0))))
    (setq r (1+ r))
  )
  (setq x x0)
  (vl-catch-all-apply 'vla-AddLine
    (list space (vlax-3d-point (list x y0 z0)) (vlax-3d-point (list x (- y0 (* totalRows rh)) z0))))
  (foreach w widths
    (setq x (+ x w))
    (vl-catch-all-apply 'vla-AddLine
      (list space (vlax-3d-point (list x y0 z0)) (vlax-3d-point (list x (- y0 (* totalRows rh)) z0))))
  )
  (setq r 0)
  (foreach row rows
    (setq y (- y0 (* r rh) (* rh 0.64)))
    (setq xcur x0)
    (setq cells row)
    (foreach w widths
      (setq textPt (list (+ xcur (* 0.8 scale)) y z0))
      (_DmtAdvDrawTextCell space textPt (_DmtAdvSafeStr (car cells)) th)
      (setq cells (cdr cells))
      (setq xcur (+ xcur w))
    )
    (setq r (1+ r))
  )
  (list (cons 'OK T) (cons 'ROWS (length records)) (cons 'MODE "FALLBACK"))
)

(defun _DmtAdvDrawRecordsTable ( / records pt)
  (setq records (_DmtAdvVisibleRecords))
  (if (null records)
    nil
    (progn
      (setq pt (getpoint "\nTablo yerlesim noktasini secin: "))
      (if pt
        (_DmtAdvDrawRecordsTableFallback pt)
        (list (cons 'OK nil) (cons 'CANCEL T))
      )
    )
  )
)

(defun _DmtAdvRunExport ( / recCount res path count)
  (setq recCount (_DmtAdvRecordCount))
  (if (<= recCount 0)
    (setq DMTADV_LAST_STATUS "Aktarilacak kayit yok.")
    (progn
      (setq res (_DmtAdvExportRecordsCsv))
      (if res
        (progn
          (setq path (cdr (assoc 'PATH res)))
          (setq count (cdr (assoc 'COUNT res)))
          (setq DMTADV_LAST_STATUS
            (strcat (itoa count) " kayit CSV olarak aktarildi: " (_s path))))
        (setq DMTADV_LAST_STATUS "CSV olusturulamadi."))
    )
  )
  (_DmtAdvStateSync)
  T
)

(defun _DmtAdvRunDrawTable ( / recCount res rows)
  (setq recCount (_DmtAdvRecordCount))
  (if (<= recCount 0)
    (setq DMTADV_LAST_STATUS "Tablo cizilecek kayit yok.")
    (progn
      (setq res (_DmtAdvDrawRecordsTable))
      (cond
        ((and res (cdr (assoc 'CANCEL res)))
         (setq DMTADV_LAST_STATUS "Tablo cizimi iptal edildi."))
        ((and res (cdr (assoc 'OK res)))
         (setq rows (cdr (assoc 'ROWS res)))
         (setq DMTADV_LAST_STATUS
           (strcat "Tablo cizildi. Satir sayisi: " (itoa rows) ".")))
        (T
         (setq DMTADV_LAST_STATUS "Tablo cizilemedi."))
      )
    )
  )
  (_DmtAdvStateSync)
  T
)

(defun _DmtAdvRunZoomSelected ()
  (_DmtAdvZoomSelected)
  T
)

; STAGE8_SINGLE_AUTHORITY_PATH: kullaniciya acik ana komut c:DMTPRO'dur.
; Diger DMT komutlari ic akista sakli tutulur.
(defun _DmtProMain ( / loopResult running)
  (_DmtInitSafeMode)
  (_DmtAdvClearRecords)
  (setq DMTADV_LAST_STATUS "Hazir")
  (_DmtAdvStateSync)
  (if (_DmtAdvEnsureMapping)
    (progn
      (setq running T)
      (while running
        (_DmtAdvStateSync)
        (setq loopResult
          (vl-catch-all-apply '_DmtAdvMainDialog '()))
        (if (vl-catch-all-error-p loopResult)
          (progn
            (setq DMTADV_LAST_STATUS
              (strcat "Ana ekran hatasi: " (_DmtAdvSafeStr (vl-catch-all-error-message loopResult))))
            (_DmtAdvStateSync)
            (setq running nil))
          (cond
          ((= loopResult 2)
           (_DmtAdvRunMap))
          ((= loopResult 3)
           (_DmtAdvRunBulkAdd))
          ((= loopResult 4)
           (_DmtAdvRunSingleAdd))
          ((= loopResult 5)
           (_DmtAdvRunSettings))
          ((= loopResult 6)
           (_DmtAdvRunExport))
          ((= loopResult 7)
           (_DmtAdvRunDrawTable))
          ((= loopResult 8)
           (_DmtAdvResetState))
          ((= loopResult 9)
           (_DmtAdvRunZoomSelected))
          ((= loopResult 10)
           (_DmtAdvRunTextZone))
          (T
           (setq running nil)))))
      ))
  (_DmtRestoreSafeMode)
  (princ)
)

(defun c:DMTPRO ()
  (_DmtProMain)
)

(defun _DmtCmdAdvAlias ()
  (_DmtProMain)
)

; -----------------------------------------------------------------------------
; LEGACY_DISABLED_DO_NOT_USE
; Stage7 notu:
; - Eski DMTADV_DATA tabanli mini ADV akisi (_DmtAdvRefreshUI,
;   _DmtAdvProcessSelection, _DmtAdvPozlandir, _DmtAdvGetCapIcmali,
;   _DmtAdvExportExcel, _DmtAdvExportTable, _DmtAdvShowSummary,
;   _DmtAdvDrawMark) aktif kullanici yolundan kaldirildi.
; - Kullaniciya acik tek ana komut c:DMTPRO -> dmt_adv_main olarak korunur.
; - Ic DMT komutlari kullanıcı autocomplete listesinde gorunmesin diye komut yerine ic fonksiyon olarak saklanir.
; - Gerekli olmayan ikinci ADV loop/UI temizlendi.
; -----------------------------------------------------------------------------

(princ "\nHuseyinozdenbakir tarafindan yapilmistir. Baslatmak icin DMTPRO yazin.")
(princ)
