;;; ---------------------------------------------------------------------
;;;  TXTFR-bgol.lsp
;;;  Command:  TFRM
;;;
;;;  PURPOSE
;;;  Draws a rectangular frame tightly fitted around each selected TEXT
;;;  entity, sized to that text's own bounding box (plus a small margin),
;;;  so labels of different lengths each get a correctly-sized box.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   TFRM   at the command line and press Enter.
;;;    3. Select one or more TEXT/MTEXT entities to frame.
;;;    4. Press Enter to finish selection.
;;;    5. A rectangle (LWPOLYLINE) is drawn around each selected text,
;;;       sized to its actual extents, on layer "BGOL-TXTFRAME".
;;;
;;;  NOTES
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of "fit a box around text"
;;;      utilities common in CAD drafting workflows, but the code,
;;;      command name and file name here are new and are NOT copied
;;;      from, nor identical to, any specific third-party product.
;;;
;;;  ---------------------------------------------------------------------
;;;  Developed and shared for the CAD community by:  BGol Community
;;;  Community website:                              https://bgol.in/
;;;  License:  Open-source & free to use, modify, and share for all.
;;;            Provided "as is", without warranty of any kind.
;;;  ---------------------------------------------------------------------

(vl-load-com)

(defun BGOL:TXTFR-EnsureLayer (lname / )
  (if (not (tblsearch "LAYER" lname))
    (entmake (list '(0 . "LAYER")
                   '(100 . "AcDbSymbolTableRecord")
                   '(100 . "AcDbLayerTableRecord")
                   (cons 2 lname)
                   '(70 . 0)
                   '(62 . 5)          ; blue
                   '(6 . "Continuous")))
  )
)

;; Draw a rectangular LWPOLYLINE from two opposite corners, on given layer
(defun BGOL:TXTFR-DrawBox (minpt maxpt lname / p1 p2 p3 p4)
  (setq p1 (list (car minpt) (cadr minpt)))
  (setq p2 (list (car maxpt) (cadr minpt)))
  (setq p3 (list (car maxpt) (cadr maxpt)))
  (setq p4 (list (car minpt) (cadr maxpt)))
  (entmake (list '(0 . "LWPOLYLINE")
                  '(100 . "AcDbEntity")
                  (cons 8 lname)
                  '(100 . "AcDbPolyline")
                  (cons 90 4)
                  (cons 70 1)          ; closed
                  (cons 10 p1)
                  (cons 10 p2)
                  (cons 10 p3)
                  (cons 10 p4)
            )
  )
)

(defun C:TFRM ( / ss n ent obj minpt maxpt margin ip1 ip2)
  (BGOL:TXTFR-EnsureLayer "BGOL-TXTFRAME")
  (setq margin 1.0)   ; default clearance around each text, in drawing units
  (setq ss (ssget '((0 . "TEXT,MTEXT"))))
  (if ss
    (progn
      (setq n 0)
      (repeat (sslength ss)
        (setq ent (ssname ss n))
        (setq obj (vlax-ename->vla-object ent))
        (vl-catch-all-apply
          '(lambda ()
             (vla-getboundingbox obj 'minpt 'maxpt)
             (setq ip1 (vlax-safearray->list minpt))
             (setq ip2 (vlax-safearray->list maxpt))
             (setq ip1 (list (- (car ip1) margin) (- (cadr ip1) margin) 0.0))
             (setq ip2 (list (+ (car ip2) margin) (+ (cadr ip2) margin) 0.0))
             (BGOL:TXTFR-DrawBox ip1 ip2 "BGOL-TXTFRAME")
           )
        )
        (setq n (1+ n))
      )
      (princ (strcat "\n" (itoa n) " text frame(s) drawn by TFRM."))
    )
    (princ "\nNo TEXT/MTEXT entities selected.")
  )
  (princ)
)

(princ "\nTXTFR-bgol.lsp loaded. Type TFRM to draw a fitted frame around text.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
