Author Topic: entmake mText  (Read 4108 times)

0 Members and 1 Guest are viewing this topic.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
entmake mText
« on: February 23, 2004, 09:11:53 AM »
I'm have a routine which reads text lines out of a text file into a list
of text strings. Example '("string 1" "string 2" "string 3")
I wanted a way to convert the list to mText. Because the lines of text from
the file are already formatted I decided to use mtext with Width set to zero.
This way all you have to do is add the \P at the end of each line.
The difficult part for me was dealing with the case where the text could
exceed 250 characters. I think I've solved that.

Questions:
Are there other ways to convert the list to mtext?

Are there any improvements to be had for this routine?

CAB

Code: [Select]
;;;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
;;;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
;;;                    Txt_List->Mtext.lsp                            
;;;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
;;;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
;;;
;;;  convert a list of strings to a mtext entity
;;;  make the entity using current layer & text
;;;  style and with insert point of (0,0)
;;;  mtext is NoWrap with \P paragraph code at
;;;  the end of each line
;;;
;;;   ARGUMENTS : list of strings one for each line
;;;   ("first line" "second line" third line")
;;;
;;;   RETURNS : <EntName> if successful else nil
;;;
;;   MText entity format note
;; Group Code              Description
;; 1  Text string. If the text string is less than 250 characters,
;;    all characters appear in group 1. If the text string is
;;    greater than 250 characters, the string is divided
;;    into 250 character chunks, which appear in one or more
;;    group 3 codes. If group 3 codes are used, the last group
;;    is a group 1 and has fewer than 250 characters.
;;
;; 3  Additional text (always in 250 character chunks) (optional)

(defun txt_list->mtext (txtlist / mtxtlist tmptxt entList tmpstr ptr itm)
  (setq mtxtlist '()
        tmptxt   ""
        entlist  (list
                   '(0 . "MTEXT")
                   '(100 . "AcDbEntity")
                   '(100 . "AcDbMText")
                   (cons 10 (list 0 0 0)) ; insert point
                   (cons 7 (getvar "TextStyle")) ; Current Style
                   (cons 40 (getvar "TextSize")) ; Current height
                   (cons 41 0) ; 0 Width = no wrap
                 )
  ); end setq
  ;;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  ;;  Create a list of the text formatted for mtext entity
  (foreach itm txtlist
    (if (> (strlen (strcat tmptxt itm)) 248)
      ;;  use 248 because we are adding \P
      (progn ; break text into 250 char groups
        ;;  pointer to number of chrs needed to make 250
        (setq ptr (- 250 (strlen tmptxt)))
        ;;  characters to be added to group
        (setq tmpstr (strcat tmptxt (substr itm 1 ptr)))
        ;;  add the group to the list of groups w/ code 3
        (setq mtxtlist (cons (cons 3 tmpstr) mtxtlist))
        ;;  characters that did not make it into the group
        (setq tmptxt (strcat (substr itm (1+ ptr)) "\\P"))
      ) ; end progn
      ;;  New line, add paragraph code, txt 2 small for group
      (setq tmptxt (strcat tmptxt itm "\\P"))
    ) ; endif
  ) ; end foreach  Done
  ;;  Add the remaining text to the list of groups w/ code 1
  (setq mtxtlist (reverse (cons (cons 1 tmptxt) mtxtlist)))
  ;;  Combine entity list with text list
  (setq entlist (append entlist mtxtlist))
  ;; make mtext & return name if ok, else return nil
  (if (entmake entlist) (entlast))
) ; end defun
;;;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
;;;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=


(defun c:test (/ str)
  (setq str (list
              "Line 1 123456789012345678901234567890123456789 L01"
              "Line 2 123456789012345678901234567890123456789 L02"
              "Line 3 123456789012345678901234567890123456789 L03"
              "Line 4 123456789012345678901234567890123456789 L04"
              "Line 5 123456789012345678901234567890123456789 L05"
              "Line 6 123456789012345678901234567890123456789 L06"
              "Line 7 123456789012345678901234567890123456789 L07"
              "Line 8 123456789012345678901234567890123456789 L08")
  )
  (txt_list->mtext str)
  (princ)
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

SMadsen

  • Guest
entmake mText
« Reply #1 on: February 23, 2004, 12:11:30 PM »
Hi CAB, nice work!

Here's a thought. Why not string all strings together and then cut them up in 250 chunk pieces? If a piece is 250 characters long then put into a code 3, otherwise into a code 1.
In the sample below, a \\P is glued to the end of each string item, then stringed together (or strung?), then cut up, then passed back to TXT_LIST->MTEXT:

Code: [Select]
(defun txt_list->mtext (txtlist / entList)
  (setq entlist (list
                  '(0 . "MTEXT")
                  '(100 . "AcDbEntity")
                  '(100 . "AcDbMText")
                  (cons 10 (list 0 0 0)) ; insert point
                  (cons 7 (getvar "TextStyle")) ; Current Style
                  (cons 40 (getvar "TextSize")) ; Current height
                  (cons 41 0)           ; 0 Width = no wrap
                )
  )                                     ; end setq  
  (cond ((setq entlist (append entlist (doString txtlist)))
         ;; make mtext & return name if ok, else return nil
         (if (entmake entlist) (entlast))
        )
  )
)

(defun doString (strings / code i lStr n strlst)
  (setq i    1
        ;; end each string with newline and string them together
        strings  (apply 'strcat (mapcar '(lambda (n) (strcat n "\\P")) strings))
  )
  (while (/= "" (setq lStr (substr strings i 250)))
    (setq code   (if (< (strlen lStr) 250) 1 3)
          strlst (cons (cons code lStr) strlst)
          i      (+ i 250)
    )
  )
  (reverse strlst)
)

SMadsen

  • Guest
entmake mText
« Reply #2 on: February 23, 2004, 12:23:16 PM »
PS: If you're worried what STRCAT can do then try multiply the string list. E.g. this test will give a string with 40,000 characters. It's no match for STRCAT.

Code: [Select]
(defun c:test (/ str mstr)
  (setq str (list "Line 1 123456789012345678901234567890123456789 L01"
                  "Line 2 123456789012345678901234567890123456789 L02"
                  "Line 3 123456789012345678901234567890123456789 L03"
                  "Line 4 123456789012345678901234567890123456789 L04"
                  "Line 5 123456789012345678901234567890123456789 L05"
                  "Line 6 123456789012345678901234567890123456789 L06"
                  "Line 7 123456789012345678901234567890123456789 L07"
                  "Line 8 123456789012345678901234567890123456789 L08")
  )
  (repeat 100 (setq mstr (append str mstr)))
  (txt_list->mtext mstr)
  (princ)
)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
entmake mText
« Reply #3 on: February 23, 2004, 01:11:19 PM »
Thanks for the eye opener. I new there were other ways but couldn't see it.
I don't "own" the mapcar and lambda commands yet. :D

I didn't realize there were no limits on strings. Somehow I had 256 as
a max in my mind. Must have been remembering limits from another language.

That opens doors...

CAB
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
entmake mText
« Reply #4 on: February 23, 2004, 02:52:17 PM »
OK, here is my version of the "combine all" strings method.

This is just an exersize :)

Code: [Select]
(defun txt_list->mtext (txtlist / mtxtlist entlist allstrings itm)
  (setq mtxtlist '()
allstrings ""
entlist (list
  '(0 . "MTEXT")
  '(100 . "AcDbEntity")
  '(100 . "AcDbMText")
  (cons 10 (list 0 0 0)) ; insert point
  (cons 7 (getvar "TextStyle")) ; Current Style
  (cons 40 (getvar "TextSize")) ; Current height
  (cons 41 0) ; 0 Width = no wrap
)
  ) ; end setq
  ;;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  ;;  Create a list of the text formatted for mtext entity
  ;;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  (foreach itm txtlist  ; combine all strings plus EOL code
    (setq allstrings (strcat allstrings itm "\\P"))
  ) ; end foreach
  (while (> (strlen allstrings) 250);  Break into 250 char groups
    (setq mtxtlist (cons (cons 3 (substr allstrings 1 250)) mtxtlist))
    (setq allstrings (substr allstrings 251)); remaining characters
  )
  ;;  Add the remaining text to the list of groups w/ code 1
  (setq mtxtlist (reverse (cons (cons 1 allstrings) mtxtlist)))
  ;;  Combine entity list with text list
  (setq entlist (append entlist mtxtlist))
  ;;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  ;; make mtext & return name if ok, else return nil
  ;;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  (if (entmake entlist)
    (entlast)
  )
  ;;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
) ; end defun
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.