how to convert odcl.lsp files to embedded for des compile

Started by jmaeding, August 07, 2013, 02:17:17 PM

Previous topic - Next topic

jmaeding

This is not a new topic, but I went through it and thought to document the process.
I started out with a folder of odcl.lsp files my programs use. That folder is in the support paths, so is used first while in the development process. After development is over, and vlx/des is deployed, the odcl.lsp files are not available and the embedded ones get used.

The key to this is understanding that odcl has a funtion to load a dialog project from a list contiaining a string of the dialog definition. Process of conversion:

1) open a dialog file in vlide that is of type odcl.lsp. You will see its just a list of strings - gibbereish. That list is exactly what you feed to (dcl_project_import thelist ...) to load the dialogs.
2) make a copy of the odcl.lsp files, and place in same folder as the lisps being compiled to vlx/des.
3) rename each to replace the . before odcl.lsp to a dash. This is because the vlide does not like .'s in the lsp names in your prv files. Also, we want the filenames different to control what gets loaded during development. Its ambiguous what was found if the names are the same.
4) add a line of code to the top of each file, it should be (SETQ <Projectname>-odcl  also add a closing paren at the end of the file.
5) modify your prv files to add the new files with -odcl.lsp, as :lsp items. So they move from the resource files part, and up to lsp files. Replace the :txt with :lsp for each.
6) use a routine to load things, that takes the name of a project as string, and tries to load the various possibilities in this order:
Load an outside "old" .odcl file if found
Load an outside odcl.lsp file if found
Load the embedded list from odcl list variable named <projectname>-odcl
Load the embedded list from odcl.lsp files as resource files

Now when you compile to vlx or des, the dialogs will be included.
The trick here that I use so I can make a generic load routine, is to name the old .odcl.lsp files to -odcl.lsp, and also set a variable of the sma ename to the list inside with the setq at top.
Then my load function knows to add the -odcl to the project name when looking to see if that variable exists.

Here is my load function for acad and bricscad versions:
Code (autolisp) Select

(DEFUN LOAD-ODCL-PROJ (NAME-STR GLOBAL-VAR / ITEM ODCLFILE TMP BCAD NOGO)
  ;TEST FOR BRICSCAD
  (IF (AND (WCMATCH (STRCASE (VLAX-PRODUCT-KEY)) "*BRICSCAD*")
           (SETQ BCAD 1)
      )
    (COND
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\V13*")
       (IF (Acad64Bit-version)
         (SETQ ODCLFILE "opendcl.X64.13.brx")
         (SETQ ODCLFILE "opendcl.13.brx")
       )
      )
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\V12*")
       (IF (Acad64Bit-version)
         (SETQ ODCLFILE "opendcl.X64.12.brx")
         (SETQ ODCLFILE "opendcl.12.brx")
       )
      )
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\R11*")(SETQ ODCLFILE "opendcl.11.brx"))
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\R10*")(SETQ ODCLFILE "opendcl.10.brx"))
    )
    ;ELSE ACAD
    (COND
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\R19*")
       (IF (Acad64Bit-version)
         (SETQ ODCLFILE "opendcl.X64.19.arx")
         (SETQ ODCLFILE "opendcl.19.arx")
       )
      )
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\R18*")
       (IF (Acad64Bit-version)
         (SETQ ODCLFILE "opendcl.X64.18.arx")
         (SETQ ODCLFILE "opendcl.18.arx")
       )
      )
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\R17*")(SETQ ODCLFILE "opendcl.17.arx"))
      ((WCMATCH (VLAX-PRODUCT-KEY) "*\\R16*")(SETQ ODCLFILE "opendcl.16.arx"))
    )
  )
  ;LOAD IT
  (IF (AND (not (IsLoadedArx ODCLFILE))(FINDFILE ODCLFILE))(arxload ODCLFILE))
  ;LOAD PROJECT
  (IF (NOT (IsLoadedArx ODCLFILE)) ;(IsLoadedArx "opendcl.12.brx")
    (ALERT (STRCAT "This tool will not work without the file " ODCLFILE " in AutoCad's search path."))
    (PROGN
      (IF (NOT (EVAL (READ GLOBAL-VAR))) ;(EVAL (READ "CT-CIVIL:LOADED"))
        (PROGN
          (IF (NOT BCAD)
            (vl-arx-import ODCLFILE)
          )
          (FOREACH ITEM (STR-TOKENS NAME-STR (LIST ","))
            (OR
              ;OUTSIDE ODCL.LSP FILE
              (IF (SETQ TMP (FINDFILE (STRCAT ITEM ".odcl.lsp")))(DCL_Project_Load TMP))
              ;REGULAR ODCL FILE
              (IF (SETQ TMP (FINDFILE (STRCAT ITEM ".odcl")))(DCL_Project_Load TMP))
              ;EMBEDDED RESOURCE AS GLOBAL VARIABLE (dcl_project_import (EVAL (READ "CheckXrefs-odcl")) nil nil) CheckXrefs-odcl
              (IF (EVAL (READ (STRCAT ITEM "-odcl"))) (dcl_project_import (EVAL (READ (STRCAT ITEM "-odcl"))) nil nil))
              ;EMBEDDED RESOURCE AS ODCL.LSP FILE
              (IF (SETQ TMP (FINDFILE (STRCAT ITEM ".odcl")))(dcl_project_import (VL-GET-RESOURCE (STRCAT ITEM ".odcl")) NIL NIL))
            )
          )
        )
      )
      (IF GLOBAL-VAR (SET (READ GLOBAL-VAR) 1))
    )
  )
  (EVAL (READ GLOBAL-VAR))
)


some helpers:
Code (autolisp) Select

(defun IsLoadedArx (filename / )(IF (MEMBER (STRCASE filename T) (ARX)) T NIL))


Code (autolisp) Select

(defun Acad64Bit-version ()
  (> (strlen (vl-prin1-to-string (vlax-get-acad-object))) 40)
)


Code (autolisp) Select

(DEFUN STR-TOKENS (STR-IN DELIM-LST
                   / CHAR-POS DELIM E1 E2 INDEX LAST-POS POS POS-LIST RET-LIST STR-LEFT)
  (FOREACH DELIM DELIM-LST
    (SETQ STR-LEFT STR-IN
          CHAR-POS 0
    )
    (WHILE (SETQ POS (vl-string-search DELIM STR-LEFT))
      (SETQ POS-LIST (CONS (LIST (+ CHAR-POS POS) (STRLEN DELIM)) POS-LIST)
            STR-LEFT (SUBSTR STR-LEFT (+ POS 1 (STRLEN DELIM)))
            CHAR-POS (+ CHAR-POS (+ POS (STRLEN DELIM)))
      )
    )
  )
  (SETQ POS-LIST (vl-sort POS-LIST (function (lambda (e1 e2)(< (car e1) (car e2))))))
  ;NOW USE POS-LIST TO CREATE LIST OF STRINGS
  (SETQ INDEX 1
        LAST-POS 1
  )
  (FOREACH POS POS-LIST
    (SETQ RET-LIST (CONS (SUBSTR STR-IN LAST-POS (+ 1 (- (CAR POS) LAST-POS))) RET-LIST))
    (SETQ LAST-POS (+ 1 (CAR POS)(CADR POS))
          INDEX (+ 1 INDEX)
    )
    ;IF ON LAST ITEM, DO TIL END
    (IF (AND (> INDEX (LENGTH POS-LIST))
             (< (- LAST-POS 1) (STRLEN STR-IN))
        )
      (SETQ RET-LIST (CONS (SUBSTR STR-IN LAST-POS) RET-LIST))
    )
  )
  (IF RET-LIST
    (REVERSE RET-LIST)
    (LIST STR-IN)
  )
)


the usage of the load function is like:
Code (autolisp) Select

(IF (not (LOAD-ODCL-PROJ "CT-Civil10,CT-Civil10-B,CT-Civil10-C" "CT-CIVIL:LOADED"))
    (VL-EXIT-WITH-VALUE (PRINC))
  )


the first string is a comma delim list of projects to load, the next string is a global var to remember if the project was already loaded. I know "CT-CIVIL:LOADED" is a string, not a variable, but we use (eval (read "name")) to get the value of the variable if it exists.

In the end, this system allows you to have a folder of <projectname>.odcl.lsp files that get used during development, and a set of <projectname>-odcl.lsp files that get used for the vlx/des compile. The  LOAD-ODCL-PROJ function takes care of loading things in developement or depolyment situations.
It could be modified for passwords, I do not use them.
You could automate the updating of the -odcl.lsp files, I have seen it done. Just know you must update them somehow if you update the .odcl.lsp files.

thx

owenwengerd

Thanks for posting your process, James. Just for the record, I recommend to load OpenDCL via (command "_OPENDCL") instead of trying to manually locate and load a specific OpenDCL Runtime .arx module.

roy_043

A discussion that touches on similar concepts:
http://www.opendcl.com/forum/index.php?topic=1830

I am surprised by this:
Code (autolisp) Select
(VL-GET-RESOURCE (STRCAT ITEM ".odcl"))
According to the documentation (vl-get-resource) only works with .txt files.

@ jmaeding:
You should consider automating the whole process and not relying on a number 'manual' steps. Because manual steps are easily forgotten when you 'recompile' for the umpteenth time.

jmaeding

The vla-get-resource does allow .lsp files, my old prv file looked like this for resources:

(:require-file-list
   (:txt "CT-Civil10-B.odcl.lsp")
   (:txt "CT-Civil10-C.odcl.lsp")
   (:txt "CT-Civil10.odcl.lsp")

The descoder does not currently allow lsp as a resource, but Torsten said he intended to fix this.
He just might be my second favorite CAD programmer, Owen still holds top place for the moment ;)
Hmm, seems the names of my favorites all end in "n". Owen, Torsten, Kean, Clayton...dang, my name ends in s.
The advantage of using the odcl.lsp files as resources is you need not duplicate any info.
The same file opendcl studio reads is the one compiled in your vlx/des.
So that fix would get rid of a lot of discussion.

On Owen's comment about using the _opendcl command, that must assume opendcl was installed which puts the arx/brx in the prog files\common...folder.
At my office, that install is a pain because only I and IT have admin rights. We could make it a standard install at machine build time, but then any updates are tricky. We all know that word tricky is bad in the computer world, read Hitchhikers Guide TTG and pay attention to Deep Thought's response when asked to find the answer to Life, the universe, and everything....
ok, lets just say I much prefer xcopy style tool deployment, and I keep the tools in a place the user has rights to, which is not in Program Files. If they ever have an admin rights parade, I will boycott it. I prefer all users to have full rights so updates could run right with user logged in.