fcb4444ee1
Neue Module ssg_blocktools.lsp (SSG_BLOCK_COUNT, SSG_BLOCK_DELETE, SSG_ATTR_ERSETZEN) und ssg_texttools.lsp (SSG_TEXT_ERSETZEN, SSG_TEXT_PARALLEL, SSG_TEXT_HOEHE, SSG_TEXT_STIL) sowie der generische Eingabe-Wrapper ssg_input.lsp, dazu Menue-/Lade-Integration, zweisprachige Texte und Unit-Tests fuer die reinen Kerne. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
312 lines
10 KiB
Common Lisp
312 lines
10 KiB
Common Lisp
;; ============================================================
|
|
;; SSG_BLOCKTOOLS.LSP - Block-Werkzeuge fuer die aktuelle Zeichnung
|
|
;;
|
|
;; Ursprung: ACADSST/MENU/TOOLS.LSP (BLKANZAHL, BLKENTF), DINGEN2
|
|
;; (g-bli) und ssg.lsp (suchen-aendern) - neu geschrieben im ssg-Stil
|
|
;; (Undo-Gruppe, i18n, Ja/Nein-Rueckfrage, keine Globals).
|
|
;;
|
|
;; Befehle:
|
|
;; SSG_BLOCK_COUNT Einfuegungen zaehlen (ein Block, Namensmuster
|
|
;; oder Statistik aller Bloecke)
|
|
;; SSG_BLOCK_DELETE Alle Einfuegungen eines Blocks/Namensmusters
|
|
;; loeschen (mit Rueckfrage)
|
|
;; SSG_ATTR_ERSETZEN Attributwerte zeichnungsweit oder in einer
|
|
;; Auswahl suchen und ersetzen (mit Vorschau)
|
|
;;
|
|
;; Blocknamen werden ueber den WIRKSAMEN Namen verglichen (dynamische
|
|
;; Bloecke: EffectiveName statt "*U12"). Muster arbeiten mit wcmatch
|
|
;; (Platzhalter * ? #, ohne Beachtung der Gross-/Kleinschreibung).
|
|
;; Es wird nur der aktuelle Layout-Reiter (Modell ODER Papierbereich)
|
|
;; durchsucht.
|
|
;;
|
|
;; Setzt ssg_core.lsp, ssg_lang.lsp und ssg_input.lsp voraus.
|
|
;; ============================================================
|
|
|
|
(vl-load-com)
|
|
|
|
;; ------------------------------------------------------------
|
|
;; REINE HILFSFUNKTIONEN (in test_unit getestet)
|
|
;; ------------------------------------------------------------
|
|
|
|
;; T, wenn name auf das wcmatch-Muster passt (ohne Gross-/Kleinschreibung).
|
|
;; muster nil oder "" -> alle Namen passen.
|
|
(defun ssg-bt-name-passt-p (name muster)
|
|
(if (or (null muster) (= muster ""))
|
|
T
|
|
(if (wcmatch (strcase name) (strcase muster)) T nil)
|
|
)
|
|
)
|
|
|
|
;; Liste von Namen -> Alist ((NAME . ANZAHL) ...), alphabetisch sortiert
|
|
;; (ohne Beachtung der Gross-/Kleinschreibung).
|
|
(defun ssg-bt-zaehle-namen (namen / alist eintrag)
|
|
(foreach name namen
|
|
(setq eintrag (assoc name alist))
|
|
(if eintrag
|
|
(setq alist (subst (cons name (1+ (cdr eintrag))) eintrag alist))
|
|
(setq alist (cons (cons name 1) alist))
|
|
)
|
|
)
|
|
(vl-sort alist '(lambda (a b) (< (strcase (car a)) (strcase (car b)))))
|
|
)
|
|
|
|
;; Sonderzeichen eines Blocknamens fuer wcmatch maskieren (Backquote), damit
|
|
;; ein per Pick gewaehlter Name nur sich selbst trifft.
|
|
(defun ssg-bt-muster-escape (name / res i c)
|
|
(setq res "" i 1)
|
|
(while (<= i (strlen name))
|
|
(setq c (substr name i 1))
|
|
(if (vl-string-search c "#@.*?~[],`")
|
|
(setq res (strcat res "`"))
|
|
)
|
|
(setq res (strcat res c)
|
|
i (1+ i))
|
|
)
|
|
res
|
|
)
|
|
|
|
;; Muster ohne Maskier-Backquotes (fuer Meldungen)
|
|
(defun ssg-bt-muster-anzeige (muster)
|
|
(ssg-str-replace-all "" "`" muster)
|
|
)
|
|
|
|
;; Neuer Attributwert oder nil, wenn der Wert unveraendert bleibt.
|
|
;; teil-p = T : suche wird als Teilstring ueberall ersetzt
|
|
;; teil-p = nil: nur ersetzen, wenn der GESAMTE Wert gleich suche ist
|
|
;; Leere suche aendert nichts. Gross-/Kleinschreibung wird beachtet.
|
|
(defun ssg-bt-wert-neu (wert suche ersatz teil-p)
|
|
(cond
|
|
((or (null suche) (= suche "") (null wert)) nil)
|
|
(teil-p
|
|
(if (vl-string-search suche wert)
|
|
(ssg-str-replace-all ersatz suche wert)
|
|
nil
|
|
)
|
|
)
|
|
((= wert suche) ersatz)
|
|
(t nil)
|
|
)
|
|
)
|
|
|
|
;; ------------------------------------------------------------
|
|
;; ZEICHNUNGSZUGRIFF
|
|
;; ------------------------------------------------------------
|
|
|
|
;; Wirksamer Blockname einer Einfuegung (dynamische Bloecke beachten)
|
|
(defun ssg-bt-effname (ent / res)
|
|
(setq res (vl-catch-all-apply 'vla-get-effectivename
|
|
(list (vlax-ename->vla-object ent))))
|
|
(if (vl-catch-all-error-p res)
|
|
(cdr (assoc 2 (entget ent)))
|
|
res
|
|
)
|
|
)
|
|
|
|
;; T, wenn der Layer der Entity gesperrt ist
|
|
(defun ssg-bt-layer-gesperrt-p (ent / lay)
|
|
(setq lay (tblsearch "LAYER" (cdr (assoc 8 (entget ent)))))
|
|
(and lay (= 4 (logand 4 (cdr (assoc 70 lay)))))
|
|
)
|
|
|
|
;; Alle Einfuegungen im aktuellen Layout, optional gefiltert nach Namensmuster.
|
|
;; Rueckgabe: Liste von Entity-Namen (kann leer sein).
|
|
(defun ssg-bt-inserts (muster / ss i ent res)
|
|
(setq ss (ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar "CTAB")))))
|
|
(if ss
|
|
(progn
|
|
(setq i 0)
|
|
(while (setq ent (ssname ss i))
|
|
(if (ssg-bt-name-passt-p (ssg-bt-effname ent) muster)
|
|
(setq res (cons ent res))
|
|
)
|
|
(setq i (1+ i))
|
|
)
|
|
)
|
|
)
|
|
(reverse res)
|
|
)
|
|
|
|
;; Statistik: ((NAME . ANZAHL) ...) fuer alle Einfuegungen passend zum Muster
|
|
(defun ssg-bt-statistik (muster)
|
|
(ssg-bt-zaehle-namen (mapcar 'ssg-bt-effname (ssg-bt-inserts muster)))
|
|
)
|
|
|
|
;; Block per Pick oder Namensmuster waehlen.
|
|
;; Rueckgabe: Namensmuster (String) oder nil bei Enter ("alle").
|
|
(defun ssg-bt-muster-waehlen (text / sel ed)
|
|
(initget "Name")
|
|
(setq sel (entsel text))
|
|
(cond
|
|
((null sel) nil)
|
|
((= (type sel) 'STR)
|
|
(setq sel (getstring T (ssg-text "bt-prompt-muster")))
|
|
(if (= sel "") nil sel)
|
|
)
|
|
(t
|
|
(setq ed (entget (car sel)))
|
|
(if (= (cdr (assoc 0 ed)) "INSERT")
|
|
(ssg-bt-muster-escape (ssg-bt-effname (car sel)))
|
|
(progn (prompt (ssg-text "bt-kein-block")) nil)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; Attribute EINER Einfuegung ersetzen (oder nur zaehlen, wenn probe-p).
|
|
;; tag = wcmatch-Muster fuer den Attribut-Tag ("*" = alle).
|
|
;; Rueckgabe: Anzahl betroffener Attribute.
|
|
(defun ssg-bt-attr-ersetzen-ent (ent tag suche ersatz teil-p probe-p
|
|
/ e ed neu n)
|
|
(setq n 0
|
|
e (entnext ent))
|
|
(while (and e
|
|
(= "ATTRIB" (cdr (assoc 0 (setq ed (entget e))))))
|
|
(if (and (ssg-bt-name-passt-p (cdr (assoc 2 ed)) tag)
|
|
(setq neu (ssg-bt-wert-neu (cdr (assoc 1 ed)) suche ersatz teil-p)))
|
|
(progn
|
|
(setq n (1+ n))
|
|
(if (not probe-p)
|
|
(entmod (subst (cons 1 neu) (assoc 1 ed) ed))
|
|
)
|
|
)
|
|
)
|
|
(setq e (entnext e))
|
|
)
|
|
(if (and (> n 0) (not probe-p)) (entupd ent))
|
|
n
|
|
)
|
|
|
|
;; Attribute einer Liste von Einfuegungen ersetzen. Rueckgabe: Anzahl.
|
|
(defun ssg-bt-attr-ersetzen-liste (ents tag suche ersatz teil-p probe-p / n)
|
|
(setq n 0)
|
|
(foreach ent ents
|
|
(setq n (+ n (ssg-bt-attr-ersetzen-ent ent tag suche ersatz teil-p probe-p)))
|
|
)
|
|
n
|
|
)
|
|
|
|
;; Auswahlsatz -> Liste von Entity-Namen (nur INSERT)
|
|
(defun ssg-bt-ss-inserts (ss / i ent res)
|
|
(if ss
|
|
(progn
|
|
(setq i 0)
|
|
(while (setq ent (ssname ss i))
|
|
(if (= (cdr (assoc 0 (entget ent))) "INSERT")
|
|
(setq res (cons ent res))
|
|
)
|
|
(setq i (1+ i))
|
|
)
|
|
)
|
|
)
|
|
(reverse res)
|
|
)
|
|
|
|
;; ------------------------------------------------------------
|
|
;; BEFEHLE
|
|
;; ------------------------------------------------------------
|
|
|
|
(defun c:SSG_BLOCK_COUNT ( / muster stat summe)
|
|
(setq muster (ssg-bt-muster-waehlen (ssg-text "bt-prompt-waehlen-count")))
|
|
(setq stat (ssg-bt-statistik muster))
|
|
(cond
|
|
((null stat)
|
|
(prompt (if muster
|
|
(ssg-textf "bt-count-keine" (list (ssg-bt-muster-anzeige muster)))
|
|
(ssg-text "bt-count-keine-alle")))
|
|
)
|
|
((and muster (null (cdr stat)))
|
|
(prompt (ssg-textf "bt-count-ergebnis" (list (cdar stat) (caar stat))))
|
|
)
|
|
(t
|
|
(setq summe 0)
|
|
(foreach z stat
|
|
(prompt (ssg-textf "bt-count-zeile" (list (car z) (cdr z))))
|
|
(setq summe (+ summe (cdr z)))
|
|
)
|
|
(prompt (ssg-textf "bt-count-summe" (list summe (length stat))))
|
|
)
|
|
)
|
|
(princ)
|
|
)
|
|
|
|
(defun c:SSG_BLOCK_DELETE ( / muster ents frei gesperrt n)
|
|
(setq muster (ssg-bt-muster-waehlen (ssg-text "bt-prompt-waehlen-delete")))
|
|
(if (null muster)
|
|
(prompt (ssg-text "bt-delete-kein-muster"))
|
|
(progn
|
|
(setq ents (ssg-bt-inserts muster))
|
|
(foreach ent ents
|
|
(if (ssg-bt-layer-gesperrt-p ent)
|
|
(setq gesperrt (cons ent gesperrt))
|
|
(setq frei (cons ent frei))
|
|
)
|
|
)
|
|
(cond
|
|
((null ents)
|
|
(prompt (ssg-textf "bt-count-keine" (list (ssg-bt-muster-anzeige muster)))))
|
|
((null frei)
|
|
(prompt (ssg-textf "bt-delete-alle-gesperrt" (list (length gesperrt)))))
|
|
((ssg-in-yesno (ssg-textf "bt-delete-frage" (list (length frei) (ssg-bt-muster-anzeige muster))) nil)
|
|
(ssg-start (ssg-text "bt-delete-titel") nil)
|
|
(setq n 0)
|
|
(foreach ent frei
|
|
(if (entdel ent) (setq n (1+ n)))
|
|
)
|
|
(ssg-end)
|
|
(prompt (ssg-textf "bt-delete-ergebnis" (list n)))
|
|
(if gesperrt
|
|
(prompt (ssg-textf "bt-delete-gesperrt" (list (length gesperrt)))))
|
|
)
|
|
(t (prompt (ssg-text "bt-abgebrochen")))
|
|
)
|
|
)
|
|
)
|
|
(princ)
|
|
)
|
|
|
|
(defun c:SSG_ATTR_ERSETZEN ( / k-bereich k-modus bereich ents muster tag suche ersatz modus teil-p n)
|
|
(setq k-bereich (ssg-text "in-keys-bereich")
|
|
k-modus (ssg-text "in-keys-modus")
|
|
bereich (ssg-in-keyword (ssg-text "bt-attr-bereich") k-bereich
|
|
(ssg-in-first-word k-bereich)))
|
|
(if (= bereich (ssg-in-first-word k-bereich))
|
|
(progn
|
|
(setq muster (ssg-in-string (ssg-text "bt-attr-muster") "*"))
|
|
(setq ents (ssg-bt-inserts muster))
|
|
)
|
|
(progn
|
|
(prompt (ssg-text "bt-attr-auswahl"))
|
|
(setq ents (ssg-bt-ss-inserts (ssget '((0 . "INSERT")))))
|
|
)
|
|
)
|
|
(cond
|
|
((null ents) (prompt (ssg-text "bt-attr-keine-bloecke")))
|
|
(t
|
|
(setq tag (ssg-in-string (ssg-text "bt-attr-tag") "*")
|
|
suche (ssg-in-string (ssg-text "bt-attr-suche") nil))
|
|
(if (or (null suche) (= suche ""))
|
|
(prompt (ssg-text "bt-abgebrochen"))
|
|
(progn
|
|
(setq ersatz (ssg-in-string (ssg-text "bt-attr-ersatz") "")
|
|
modus (ssg-in-keyword (ssg-text "bt-attr-modus") k-modus
|
|
(ssg-in-first-word k-modus))
|
|
teil-p (= modus (ssg-in-first-word k-modus)))
|
|
(setq n (ssg-bt-attr-ersetzen-liste ents tag suche ersatz teil-p T))
|
|
(cond
|
|
((= n 0) (prompt (ssg-text "bt-attr-nichts")))
|
|
((ssg-in-yesno (ssg-textf "bt-attr-frage" (list n (length ents))) T)
|
|
(ssg-start (ssg-text "bt-attr-titel") nil)
|
|
(setq n (ssg-bt-attr-ersetzen-liste ents tag suche ersatz teil-p nil))
|
|
(ssg-end)
|
|
(prompt (ssg-textf "bt-attr-ergebnis" (list n))))
|
|
(t (prompt (ssg-text "bt-abgebrochen")))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(princ)
|
|
)
|
|
|
|
(princ)
|