Author Topic: DCL2LSP  (Read 12867 times)

0 Members and 1 Guest are viewing this topic.

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
DCL2LSP
« on: January 10, 2012, 06:20:32 AM »
Here is my simple code, but vary powerful if you want to implement dcl content into lsp file... Of course, you have to edit main lsp with these lines :
Code: [Select]
  (setq fname (vl-filename-mktemp nil nil ".dcl"))
  (setq fn (open fname "w"))

After that comes the part from successful conversion of dcl content to lsp in form :
Code: [Select]
  (write-line "... ... \" ... ... \" ... ..." fn)
  (write-line "... ..." fn)
  ...

Then comes these final lines :
Code: [Select]
  (close fn)
  (vl-file-delete fname)

So, here is my conversion dcl2lsp.lsp :
Code: [Select]
(defun c:dcl2lsp ( / fname1 fn1 fname2 fn2 k fn1l fn2l )
  (setq fname1 (getfiled "Select DCL file" "" "dcl" 16))
  (setq fn1 (open fname1 "r"))
  (setq fname2 (getfiled "File to save" "" "lsp" 1))
  (setq fn2 (open fname2 "w"))
  (while (setq fn1l (read-line fn1))
    (setq fn2l fn1l)
    (setq k 0)
    (while (setq k (vl-string-search "\"" fn2l k))
      (setq fn2l (vl-string-subst "\\\"" "\"" fn2l k))
      (setq k (+ k 2))
    )
    (setq fn2l (strcat "(write-line \"" fn2l "\" fn)"))
    (write-line fn2l fn2)
  )
  (close fn1)
  (close fn2)
  (princ)
)

I hope, that you'll find this useful... Someone, like me want to have everything in *.lsp, for if separate main lsp code from dcl, you have to put both files in CAD support search path, and load *.lsp from there... This way, if you have all in single *.lsp, you can load it from anywhere and not worry if dialog box will show up or not (it must show up)...

M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: DCL2LSP
« Reply #1 on: January 10, 2012, 07:26:06 AM »
I had a similar idea a while back: http://caddons.svn.sourceforge.net/viewvc/caddons/Libraries/Dialogs.LSP?revision=56&view=markup

Basically it converts the DCL file into a LSP file with a defun to copy into your LSP. Then instead of the (load_dialog "Filename.DCL") call you'd just call that function.

It's a bit old, you'll note, as I'm using a convoluted method of escaping " and \. I could have combined both into a vl-prin1-to-string call.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: DCL2LSP
« Reply #2 on: January 10, 2012, 07:42:53 AM »
Actually I've just added a new revision incorporating the simplified escaping, but also adding a run-dialog function which greatly simplifies using your dialog. See the test function at the end.
http://caddons.svn.sourceforge.net/viewvc/caddons/Libraries/Dialogs.LSP?revision=57&view=markup
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: DCL2LSP
« Reply #3 on: January 10, 2012, 08:03:53 AM »
Sorry  :ugly: I should've tested it more thoroughly. Reverted back to the old escaping methods. Instead of prefixing double quotes with a backslash it changed them to double-double-quotes ... which cuases havoc with lisp code:
http://caddons.svn.sourceforge.net/viewvc/caddons/Libraries/Dialogs.LSP?revision=58&view=markup
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: DCL2LSP
« Reply #4 on: January 10, 2012, 08:51:44 AM »
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.

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: DCL2LSP
« Reply #5 on: January 10, 2012, 09:30:22 AM »
Here is my reversed lsp that is to be applied to obtain dcl...
It is based on my firstly posted dcl2lsp.lsp and it should be applied on *.lsp made by it :

Code: [Select]
(defun c:lsp2dcl ( / fname1 fn1 fname2 fn2 k fn1l fn2l )
  (setq fname1 (getfiled "Select LSP file" "" "lsp" 16))
  (setq fn1 (open fname1 "r"))
  (setq fname2 (getfiled "File to save" "" "dcl" 1))
  (setq fn2 (open fname2 "w"))
  (while (setq fn1l (read-line fn1))
    (setq fn2l fn1l)
    (setq fn2l (substr fn2l (+ (vl-string-search "\"" fn2l) 2) (- (vl-string-position (ascii "\"") fn2l nil T) (+ (vl-string-search "\"" fn2l) 1))))
    (setq k 0)
    (while (setq k (vl-string-search "\\\"" fn2l k))
      (setq fn2l (vl-string-subst "\"" "\\\"" fn2l k))
      (setq k (+ k 1))
    )
    (write-line fn2l fn2)
  )
  (close fn1)
  (close fn2)
  (princ)
)

M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: DCL2LSP
« Reply #6 on: January 11, 2012, 08:12:32 AM »
I don't know if there is program for this, but this little routine might work on every *.dcl file that has standard dialog description as first word in line for defining dialog box name...

Code: [Select]
(defun c:viewdcl ( / dclid return# filen fn lin )
  (setq dclid (load_dialog (setq filen (getfiled "" "" "dcl" 16))))
  (setq fn (open filen "r"))
  (while (or (eq (substr (setq lin (read-line fn)) 1 2) "//") (eq (substr lin 1 (vl-string-search " " lin)) "") (not (eq (substr lin (+ (vl-string-search " " lin) 1) 9) " : dialog"))))
  (new_dialog (substr lin 1 (vl-string-search " " lin)) dclid)
  (action_tile "accept" "(done_dialog 1)")
  (action_tile "cancel" "(done_dialog 0)")
  (setq return# (start_dialog))
  (princ return#)
  (unload_dialog dclid)
  (princ)
)

For those that want to quickly review what have been written as *.dcl, this might be of some help...
M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Gu_xl

  • Mosquito
  • Posts: 6
Re: DCL2LSP
« Reply #7 on: January 11, 2012, 08:32:30 AM »
This code can be more simple
Code - Lisp: [Select]
  1. (defun c:dcl2lsp ( / fname1 fn1 fname2 fn2 k fn1l fn2l )
  2.   (setq fname1 (getfiled "Select DCL file" "" "dcl" 16))
  3.   (setq fn1 (open fname1 "r"))
  4.   (setq fname2 (getfiled "File to save" "" "lsp" 1))
  5.   (setq fn2 (open fname2 "w"))
  6.   (while (setq fn1l (read-line fn1))
  7.     (setq fn2l (strcat "(write-line " (VL-PRIN1-TO-STRING fn1l ) " fn)"))
  8.     (write-line fn2l fn2)
  9.   )
  10.   (close fn1)
  11.   (close fn2)
  12.   (princ)
  13. )
  14.  
« Last Edit: January 11, 2012, 08:38:40 AM by Gu_xl »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: DCL2LSP
« Reply #8 on: January 11, 2012, 10:22:54 AM »
Welcome to the Swamp. 8-)
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.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: DCL2LSP
« Reply #9 on: January 11, 2012, 10:51:51 AM »
Just a query: What happens with double-quotes on your side with that vl-prin1-to-string function? For me they turn into 2x double-quotes instead of the needed backslash escape prefix.  :realmad: Otherwise my code would have been a lot simpler as well!

BTW, I think ribarm's method is the most straigt-forward method of escaping backslashes and double quotes. I'll have another go at making mine a bit less convoluted.  :lmao:
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: DCL2LSP
« Reply #10 on: January 11, 2012, 11:20:00 AM »
Ok, this one seems to work now: http://caddons.svn.sourceforge.net/viewvc/caddons/Libraries/Dialogs.LSP?annotate=59

Basically I'm using a string substitution function (at the start of my code) which I got with some help from Lee Mac. Then I'm applying it twice: first for the \ --> \\, then for " --> \" ... see line 48 in my code.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: DCL2LSP
« Reply #11 on: January 12, 2012, 03:57:54 AM »
Although I don't know where you can find char \ in dcl file, here are my versions that include them in conversions... This is now the same as (vl-prin1-to-string) variant...

Code: [Select]
(defun c:dcl2lsp ( / fname1 fn1 fname2 fn2 k fn1l fn2l )
  (setq fname1 (getfiled "Select DCL file" "" "dcl" 16))
  (setq fn1 (open fname1 "r"))
  (setq fname2 (getfiled "File to save" "" "lsp" 1))
  (setq fn2 (open fname2 "w"))
  (while (setq fn1l (read-line fn1))
    (setq fn2l fn1l)
    (setq k 0)
    (while (setq k (vl-string-search "\\" fn2l k))
      (setq fn2l (vl-string-subst "\\\\" "\\" fn2l k))
      (setq k (+ k 2))
    )
    (setq k 0)
    (while (setq k (vl-string-search "\"" fn2l k))
      (setq fn2l (vl-string-subst "\\\"" "\"" fn2l k))
      (setq k (+ k 2))
    )
    (setq fn2l (strcat "(write-line \"" fn2l "\" fn)"))
    (write-line fn2l fn2)
  )
  (close fn1)
  (close fn2)
  (princ)
)

Code: [Select]
(defun c:lsp2dcl ( / fname1 fn1 fname2 fn2 k fn1l fn2l )
  (setq fname1 (getfiled "Select LSP file" "" "lsp" 16))
  (setq fn1 (open fname1 "r"))
  (setq fname2 (getfiled "File to save" "" "dcl" 1))
  (setq fn2 (open fname2 "w"))
  (while (setq fn1l (read-line fn1))
    (setq fn2l fn1l)
    (setq fn2l (substr fn2l (+ (vl-string-search "\"" fn2l) 2) (- (vl-string-position (ascii "\"") fn2l nil T) (+ (vl-string-search "\"" fn2l) 1))))
    (setq k 0)
    (while (setq k (vl-string-search "\\\"" fn2l k))
      (setq fn2l (vl-string-subst "\"" "\\\"" fn2l k))
      (setq k (+ k 1))
    )
    (setq k 0)
    (while (setq k (vl-string-search "\\\\" fn2l k))
      (setq fn2l (vl-string-subst "\\" "\\\\" fn2l k))
      (setq k (+ k 1))
    )
    (write-line fn2l fn2)
  )
  (close fn1)
  (close fn2)
  (princ)
)

M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: DCL2LSP
« Reply #12 on: January 12, 2012, 06:53:19 AM »
The \ can be placed inside label/value/list parameters to indicate tabs / new lines. Though they're very rare. Also it might be that a backslash is intended in the label, but due to a double-backslash becoming a single on if you princ/write-line to the file - this would make problems in the LSP - therefore you need to double each \ found in the DCL - before you add another backslash to the "

Now why did mine give hassles previously? I've just tried this on the command line:
Code: [Select]
Command: (setq str (getstring t)) Test backslash \ and double quotes "
"Test backslash \\ and double quotes \""

Command: (progn (princ str) (princ))
Test backslash \ and double quotes "

Command: (progn (princ (vl-princ-to-string str)) (princ))
Test backslash \ and double quotes "

Command: (progn (princ (vl-prin1-to-string str)) (princ))
"Test backslash \\ and double quotes \""
So the vl-prin1-to-string "should" work perfectly. Though last time I incorporated it into my DCL2LSP it would simply double the quotes thus:
Code: [Select]
(progn (princ (vl-prin1-to-string str)) (princ))
 "Test backslash \\ and double quotes """
Actually why use the vl-prin1-to-string at all? Why not simply use the prin1 to print directly to the file?
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: DCL2LSP
« Reply #13 on: January 12, 2012, 07:14:57 AM »
OK, this seems to now work perfectly. Instead of my previuous:
Code: [Select]
;|
    ;; prefix all quotes and backslashes with backslashes
    (setq str (strsubst "\\\"" "\"" (strsubst "\\\\" "\\" str)))

    ;; Write to file
    (write-line (strcat "  (write-line \"" str "\" f)")lsp)
    |;

This works just as well:
Code: [Select]
    (princ "  (write-line " lsp)
    (prin1 str lsp)
    (princ " f)\n" lsp)

Updated my code as it makes it a lot simpler: http://caddons.svn.sourceforge.net/viewvc/caddons/Libraries/Dialogs.LSP?annotate=61

BTW, why would you need a LSP2DCL? Wouldn't you simply want to call the LSP generated to save the DCL? E.g. here's a sample DCL with most of the strange stuff inside:
Code: [Select]
TestDialog : dialog {
  label = "Testing \\ DCL2LSP";
  : edit_box {
    key = "ser";
    label = "Edit box";
    width = 50;
  }
  : list_box {
    key = "key";
    label = "List Box";
    tabs = "20 35";
    multiple_select = true;
    list = "One\t1\nTwo\t2\nThree\t3";
    value = "1 2";
  }
  : text {
    key = "txt";
    height = 3;
    value = "My long line of text\nhas a second line";
  }
  ok_cancel;
}
Now running mu DCL2LSP on that file (I saved it as test.DCL) I get a file named load_dialog_test.lsp:
Code: [Select]
;;; Function to load test dialog
(defun load_dialog_test (/ fn f)
  (setq fn (strcat (getvar "TEMPPREFIX") "test.DCL"))
  (setq f (open fn "w"))
  (write-line "TestDialog : dialog {" f)
  (write-line "  label = \"Testing \\\\ DCL2LSP\";" f)
  (write-line "  : edit_box {" f)
  (write-line "    key = \"ser\";" f)
  (write-line "    label = \"Edit box\";" f)
  (write-line "    width = 50;" f)
  (write-line "  }" f)
  (write-line "  : list_box {" f)
  (write-line "    key = \"key\";" f)
  (write-line "    label = \"List Box\";" f)
  (write-line "    tabs = \"20 35\";" f)
  (write-line "    multiple_select = true;" f)
  (write-line "    list = \"One\\t1\\nTwo\\t2\\nThree\\t3\";" f)
  (write-line "    value = \"1 2\";" f)
  (write-line "  }" f)
  (write-line "  : text {" f)
  (write-line "    key = \"txt\";" f)
  (write-line "    height = 3;" f)
  (write-line "    value = \"My long line of text\\nhas a second line\";" f)
  (write-line "  }" f)
  (write-line "  ok_cancel;" f)
  (write-line "}" f)
  (close f)
  (load_dialog fn)
) ;_ end of defun

;;; Function to run the TestDialog dialog
(defun run_dialog_test_TestDialog (key_list extra / dcl return)
  (if (and (setq dcl (load_dialog_test)) (new_dialog dcl))
    (progn
      (foreach key key_list
        (if (cadr key)
          (set_tile (car key) (cadr key))
        )
        (if (caddr key)
          (action_tile (car key) (caddr key))
        )
        (if (cadddr key)
          (progn
            (start_list (car key))
            (mapcar 'add_list (cdddr key))
            (end_list)
          )
        )
      )
      (if extra (eval extra))
      (setq return (start_dialog))
      (unload_dialog dcl)
    )
  )
  return
) ;_ end of defun

So in my case all I need to do is run the generated load_dialog_test defun and then the test.DCL file will be available in the temp folder.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: DCL2LSP
« Reply #14 on: January 12, 2012, 08:35:01 AM »
Here is your TestDialog.dcl example implemented into my version of TestDialog.lsp... Above and below lines are always the same and lines (write-line "..." fn) are obtained from my dcl2lsp.lsp... I've tested my TestDialog.lsp and it works (shows your *.dcl)...

Code: [Select]
(defun c:TestDialog ( / fname fn dclid lin return# )
  (setq fname (vl-filename-mktemp nil nil ".dcl"))
  (setq fn (open fname "w"))

(write-line "TestDialog : dialog {" fn)
(write-line "  label = \"Testing \\\\ DCL2LSP\";" fn)
(write-line "  : edit_box {" fn)
(write-line "    key = \"ser\";" fn)
(write-line "    label = \"Edit box\";" fn)
(write-line "    width = 50;" fn)
(write-line "  }" fn)
(write-line "  : list_box {" fn)
(write-line "    key = \"key\";" fn)
(write-line "    label = \"List Box\";" fn)
(write-line "    tabs = \"20 35\";" fn)
(write-line "    multiple_select = true;" fn)
(write-line "    list = \"One\\t1\\nTwo\\t2\\nThree\\t3\";" fn)
(write-line "    value = \"1 2\";" fn)
(write-line "  }" fn)
(write-line "  : text {" fn)
(write-line "    key = \"txt\";" fn)
(write-line "    height = 3;" fn)
(write-line "    value = \"My long line of text\\nhas a second line\";" fn)
(write-line "  }" fn)
(write-line "  ok_cancel;" fn)
(write-line "}" fn)
 
  (close fn)
  (setq fn (open fname "r"))
  (setq dclid (load_dialog fname))
  (while (or (eq (substr (setq lin (vl-string-right-trim "\" fn)" (vl-string-left-trim "(write-line \"" (read-line fn)))) 1 2) "//") (eq (substr lin 1 (vl-string-search " " lin)) "") (not (eq (substr lin (+ (vl-string-search " " lin) 1) 9) " : dialog"))))
  (new_dialog (substr lin 1 (vl-string-search " " lin)) dclid)
  (action_tile "accept" "(done_dialog 1)")
  (action_tile "cancel" "(done_dialog 0)")
  (setq return# (start_dialog))
  (princ return#)
  (unload_dialog dclid)
  (close fn)
  (vl-file-delete fname)
  (princ)
)

M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube