Code Red > AutoLISP (Vanilla / Visual)

How to get plot style names from STB file?

(1/2) > >>

roy_043:
Is it possible to get the plot style names from an STB file? The only thing I can come up with is an ugly workaround using the the logfile and the -Layer command. Is there a better way?

Lee Mac:
These may help:

http://www.theswamp.org/index.php?topic=41529.0

http://www.noliturbare.com/more/faq#Q1

http://www.theswamp.org/index.php?topic=37625.0

roy_043:
Thank you Lee for those links.

Well, this is turning out to be quite a --==={challenge}===-- for me.

First I had quite some trouble finding a Zlib dll that would register with regsvr32.exe. But I was able to register this one:
http://www.dogma.net/markn/ZlibOCX2.dll
It is mentioned on http://www.zlib.net/ as "unsupported VB5 binary".
This dll reads and writes files.

Second problem: reading the binary file, removing the first 60 bytes, and then writing the result to a new binary file that the dll can then decompress. I have checked out code from Lee Mac and MP. See below.
Lee's read function produces a variant of the type 8209(?). But MP's code will only read the first portion of the stb file. So I am using Lee's (LM:ReadBinaryStream) function for reading.
As I am not able to recreate a variant of the type 8209 I am not able to use Lee's code for writing. So I am using MP's (_WriteStream). But somehow the conversion to text that his write function requires causes trouble. In my test only 290 bytes instead of 440 - 60 = 380 bytes were written.

Basically I am stuck here. Any and all insights are welcome!

My code:

--- Code: ---(setq data (vlax-safearray->list (vlax-variant-value (LM:ReadBinaryStream "default.stb" 0)))) ; List of integers. Length 440 (equals 440 bytes).
(setq txt (substr (vl-list->string data) 61))                                                 ; Chop off first 60.
(_WriteStream (strcat (getvar 'dwgprefix) "default_Minus_60_Bytes.stb") txt "w")              ; Write as text. Only 290 bytes are written?

(setq zlibIF (vlax-create-object "zlibIF.zlibIF.1"))
(vlax-put zlibIF 'inputfilename (strcat (getvar 'dwgprefix) "MANUAL_default_Minus_60_Bytes.stb"))
(vlax-put zlibIF 'outputfilename (strcat (getvar 'dwgprefix) "MANUAL_default_Minus_60_Bytes.txt"))
(vlax-invoke zlibIF 'decompress)
(if zlibIF (vlax-release-object zlibIF))

--- End code ---

Lee Mac's code:
http://www.cadtutor.net/forum/archive/index.php/t-57294.html?s=5868f10b6c04f0c55def20c8e85e764e

--- Code: ---;;-----------------=={ Read Binary Stream }==-----------------;;
;; ;;
;; Uses the ADO Stream Object to read a supplied file and ;;
;; returns a variant of bytes. ;;
;;------------------------------------------------------------;;
;; Author: Lee Mac, Copyright © 2011 - www.lee-mac.com ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; filename - filename of file to read. ;;
;; len - number of bytes to read ;;
;; (if non-numerical, less than 1, or greater than the size ;;
;; of the file, everything is returned). ;;
;;------------------------------------------------------------;;
;; Returns: ;;
;; Variant of Binary data which may be converted to a list ;;
;; bytes using the relevant VL Variant functions or used ;;
;; with LM:WriteBinaryStream. ;;
;;------------------------------------------------------------;;
(defun LM:ReadBinaryStream ( filename len / ADOStream result )
  (vl-load-com)
  (setq result
    (vl-catch-all-apply
      (function
        (lambda ( / size )
          (setq ADOStream (vlax-create-object "ADODB.Stream"))
          (vlax-invoke ADOStream 'Open)
          (vlax-put-property ADOStream 'type 1)
          (vlax-invoke-method ADOStream 'loadfromfile filename)
          (vlax-put-property ADOStream 'position 0)
          (setq size (vlax-get ADOStream 'size))
          (vlax-invoke-method ADOStream 'read (if (and (numberp len) (< 0 len size)) (fix len) -1))
        )
      )
    )
  )
  (if ADOStream (vlax-release-object ADOStream))
  (if (not (vl-catch-all-error-p result))
    result
  )
)

;;-----------------=={ Write Binary Stream }==----------------;;
;; ;;
;; Uses the ADO Stream Object to write a variant of bytes to ;;
;; a specified file. File is created if non-existent or ;;
;; overwritten if found. ;;
;;------------------------------------------------------------;;
;; Author: Lee Mac, Copyright © 2011 - www.lee-mac.com ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; filename - filename of file to read. ;;
;; data - variant of binary data to write to the file. ;;
;; (as returned by LM:ReadBinaryStream) ;;
;;------------------------------------------------------------;;
;; Returns: Filename of specified file, else nil. ;;
;;------------------------------------------------------------;;
(defun LM:WriteBinaryStream ( filename data / ADOStream result )
  (vl-load-com)
  (setq result
    (vl-catch-all-apply
      (function
        (lambda ( )
          (setq ADOStream (vlax-create-object "ADODB.Stream"))
          (vlax-put-property ADOStream 'type 1)
          (vlax-invoke ADOStream 'open)
          (vlax-invoke-method ADOStream 'write data)
          (vlax-invoke ADOStream 'savetofile filename 2)
        )
      )
    )
  )
  (if ADOStream (vlax-release-object ADOStream))
  (if (not (vl-catch-all-error-p result))
    file
  )
)

--- End code ---

MP's code:
http://www.theswamp.org/index.php?topic=17465.0

--- Code: ---(defun _ReadStream ( path len / fso file stream result )

    ;;  If the file is successful read the data is returned as
    ;;  a string. Won't be tripped up by nulls, control chars
    ;;  including ctrl z (eof marker). Pretty fast (feel free
    ;;  to bench mark / compare to alternates).
    ;;
    ;;  If the caller wants the result as a list of byte values
    ;;  simply use vl-string->list on the result:
    ;;
    ;;      (setq bytes
    ;;          (if (setq stream (_ReadStream path len))
    ;;              (vl-string->list stream)
    ;;          )
    ;;      )           
    ;;
    ;;  Arguments:
    ;;
    ;;      path  <duh>
    ;;      len   Number of bytes to read. If non numeric, less
    ;;            than 1 or greater than the number of bytes in
    ;;            the file everything is returned.
   
    (vl-catch-all-apply
       '(lambda ( / iomode format size )
            (setq
                iomode   1 ;; 1 = read, 2 = write, 8 = append
                format   0 ;; 0 = ascii, -1 = unicode, -2 = system default
                fso      (vlax-create-object "Scripting.FileSystemObject")
                file     (vlax-invoke fso 'GetFile path)
                stream   (vlax-invoke fso 'OpenTextFile path iomode format)
                size     (vlax-get file 'Size)
                len      (if (and (numberp len) (< 0 len size)) (fix len) size)
                result   (vlax-invoke stream 'read len)
            )
            (vlax-invoke stream 'Close)
        )
    )
   
    (if stream (vlax-release-object stream))
    (if file (vlax-release-object file))
    (if fso (vlax-release-object fso))
   
    result

)

(defun _WriteStream ( path text mode / fso stream file result )

    ;;  Return the file size if the file is successfully written
    ;;  to, otherwise nil. Will write all ascii chars to file
    ;;  including nulls. If the caller wants to pass a list of
    ;;  byte values to the function just call it like so:
    ;;
    ;;      (_WriteStream
    ;;          path
    ;;          (vl-list->string '(87 111 111 116 33))
    ;;          mode
    ;;      )
    ;;
    ;;  Arguments:
    ;;
    ;;      path  <duh>
    ;;      text  <duh>
    ;;      mode  "a" to create/append,
    ;;            "w" to create/overwrite (default)
   
    (setq mode (if (member mode '("a" "A")) "a" "w"))
   
    (vl-catch-all-apply
       '(lambda ( / format )
            (setq fso (vlax-create-object "Scripting.FileSystemObject"))
            (cond
                (   (or (null (findfile path)) (eq "w" mode))
                    (setq stream
                        (vlax-invoke
                            fso
                           'CreateTextFile
                            path
                           -1 ;; 0 (false) = don't overwrite , -1 (true) = overwrite
                            0 ;; 0 (false) = ascii, -1 (true) = unicode
                        )
                    )
                    (setq file (vlax-invoke fso 'GetFile path))
                )
                (   (setq file (vlax-invoke fso 'GetFile path))
                    (setq stream
                        (vlax-invoke
                            file
                           'OpenAsTextStream
                            8 ;; 1 = read, 2 = write, 8 = append
                            0 ;; 0 = ascii, -1 = unicode, -2 system default
                        )
                    )       
                )
            )
            (vlax-invoke stream 'Write text)
            (vlax-invoke stream 'Close)
            (setq result (vlax-get file 'Size))
        )
    )

    (if file (vlax-release-object file))
    (if stream (vlax-release-object stream))
    (if fso (vlax-release-object fso))
   
    result
   
)

--- End code ---

The attached zip contains 5 files:
default.stb (STB that comes with Bricscad 440 bytes)
default_Minus_60_Bytes.stb (STB created by my code: only 290 bytes)
default_Minus_60_Bytes.txt (default_Minus_60_Bytes.stb after decompression)
MANUAL_default_Minus_60_Bytes.stb (STB created "manually" with correct file size)
MANUAL_default_Minus_60_Bytes.txt (MANUAL_default_Minus_60_Bytes.stb after decompression)

roy_043:
I have to correct my previous post. MP's read function does read the complete stb file. But the string value it returns does not completely display in the command history window. I am assuming this is caused by certain special characters.

The test function returns T.


--- Code: ---(defun Read_Test ( / list_LM list_MP)
  (setq list_LM (vlax-safearray->list (vlax-variant-value (LM:ReadBinaryStream "default.stb" 0))))
  (setq list_MP (vl-string->list (_ReadStream "default.stb" 0)))
  (and
    (= (length list_LM) 440)
    (= (length list_MP) 440)
    (vl-every
      '=
      list_LM
      list_MP
    )
  )
)

--- End code ---

roy_043:
OK, the code below works.

As mentioned in a previous post the code requires this dll:
http://www.dogma.net/markn/ZlibOCX2.dll
It is mentioned on http://www.zlib.net/ as "unsupported VB5 binary".
This dll reads and writes files.
The dll must be registered using regsvr32.exe.


--- Code: ---; (PlotStyleTable_To_TextFile "default.ctb" (strcat (getvar 'dwgprefix) "default_ctb.txt"))
; (PlotStyleTable_To_TextFile "default.stb" (strcat (getvar 'dwgprefix) "default_stb.txt"))
(defun PlotStyleTable_To_TextFile (PlotStyleTableFileName txtFileName / N_ChopFirst60Bytes N_Decompress)

  (defun N_ChopFirst60Bytes (inputFilename outputFilename / adoStream content)
    (setq adoStream (vlax-create-object "ADODB.Stream"))
    (vlax-put-property adoStream 'type 1)
    (vlax-invoke adoStream 'open)
    (vlax-invoke adoStream 'loadfromfile inputFilename)
    (vlax-put-property adoStream 'position 60)
    (setq content (vlax-invoke-method adoStream 'read -1))
    (vlax-invoke adoStream 'close)
    (vlax-invoke adoStream 'open)
    (vlax-invoke adoStream 'write content)
    (vlax-invoke adoStream 'savetofile outputFilename 2)
    (vlax-release-object adoStream)
  )
 
  (defun N_Decompress (inputFilename outputFilename / zlibif)
    (setq zlibif (vlax-create-object "zlibIF.zlibIF.1"))
    (vlax-put zlibif 'inputfilename inputFilename)
    (vlax-put zlibif 'outputfilename outputFilename)
    (vlax-invoke zlibif 'decompress)
    (vlax-release-object zlibif)
  )
 
  (not
    (vl-catch-all-error-p
      (vl-catch-all-apply
        '(lambda ( / tmpFileName)
          (setq tmpFileName (vl-filename-mktemp nil nil ".zl"))
          (N_ChopFirst60Bytes PlotStyleTableFileName tmpFileName)
          (N_Decompress tmpFileName txtFileName)
          (vl-file-delete tmpFileName)
        )
      )
    )
  )
)

--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version