Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

User hits ESC button while using an AutoLisp program.

13 REPLIES 13
Reply
Message 1 of 14
brianhiroshi
1075 Views, 13 Replies

User hits ESC button while using an AutoLisp program.

Hi,
My Lisp function gets the variables like osmode for example and makes them 0. Then, at the end of the function it sets the variables back to what they were. The problem is when the user presses the ESC button in the middle of the function. Is there any way to restore the variables back to what they were when this happens?
Thanks
13 REPLIES 13
Message 2 of 14
EC-CAD
in reply to: brianhiroshi

Put something like this, in your acaddoc.lsp file.
IF that file doesn't exist in your \support folder,
just make one with Notepad, and saveas 'acaddoc.lsp'

;;
;; Error Function
;;
(defun myerror (sxx)
(if (= sxx nil)
(setq sxx "console break")
); end if
(if (not (member sxx '("console break" "Function cancelled")))
(princ (strcat "\nError: " sxx))
); end if
(if (= (member sxx '("console break" "Function cancelled")))
(progn
(prompt "\nError: Break...")
(setvar "MENUECHO" 0)
(setvar "HIGHLIGHT" 1)
(setvar "SORTENTS" 1)
(setvar "ATTDIA" 0); No Attribute Dialog Boxes, please
(setvar "ATTREQ" 1); Attributes Required
(if OSM (setvar "OSMODE" OSM)); Reset OSMode
); end progn
); end if
(setvar "CMDECHO" 0)
(setq sxx nil)
(princ)
); end function err
(setq olderr *error* *error* myerror)

.. Then, in your Lisp.. do:
(setq OSM (getvar "OSMODE")); OSM is Global
Bob
Message 3 of 14
Anonymous
in reply to: brianhiroshi


What you are looking for is an error handler, an
error routine which temporarely replaces AutoCAD's native error routine and
takes care to do every instruction you code in to it, before
restoring AutoCAD's native error routine. Here is a simple exemple that you
could adapt to suit your needs:

 


size=2>;;;=========================================

(defun MyFunction ( / old_cmdecho old_osmode
old_error)

 

  ;;; define the error function
 
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  (defun MyFunctionErrorHandler
(msg)
    (alert msg)
   

    ;;; if it's not one of the below
   
;;; errors, print a custom message
   
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
   
(if
     
(not
       
(member
         
msg
         
(list
           
"Function
cancelled"
           
"console
break"
           
"quit / exit abort"
         
)
       
)
      )
     
(prompt
       
(strcat
          "\nMyFunction
failed. Error: "
         
msg
          ". The variables
have been restored.\n"
       
)
      )
    )

 

    ;;; restoring the original value
for the
    ;;; system variables by the error
routine
   
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    (setvar 'cmdecho
old_cmdecho)
    (setvar 'osmode old_osmode)

 

    ;;; set the LISP variables to
nil
    ;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
   
(setq old_cmdecho nil old_osmode nil)

 

    ;;; restoring the
 AutoCAD's native error routine
   
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    (setq
*error* old_error old_error nil)

 

    ;;; exit
quietly
    ;;; ¯¯¯¯¯¯¯¯¯
   
(princ)
  )
 
  ;;; grab the original values for the
variables
 
;;; ­­­­­­­­­­­­­­­­­­­­­¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 
(setq old_cmdecho (getvar 'cmdecho))
  (setq old_osmode (getvar
'osmode))
  (setq old_error *error*)

 

  ;;; alter the variables
 
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  (setvar 'cmdecho 0)
  (setvar 'osmode
0)
 
  ;;; substitute AutoCAD's native error
  ;;;
routine with our custom error routine
 
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  (setq *error*
MyFunctionErrorHandler)

 

  ;;; do your stuff here
 
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  (alert "Here goes the code")

 

  ;;; restoring the original value for
the system
  ;;; variables  if everything went
smoothly

  ;;;
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

  (setvar 'cmdecho old_cmdecho)
 
(setvar 'osmode old_osmode)

 

  ;;; restoring the  AutoCAD's native
error
  ;;; routine if everything went smoothly

 
;;; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  (setq *error*
old_error)

 

  ;;; exit quietly
 
;;; ¯¯¯¯¯¯¯¯¯
  (princ)
)



size=2>;;;=========================================

 

HTH

 


style="PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
Hi,
My Lisp function gets the variables like osmode for example and makes them 0.
Then, at the end of the function it sets the variables back to what they were.
The problem is when the user presses the ESC button in the middle of the
function. Is there any way to restore the variables back to what they were
when this happens? Thanks
Message 4 of 14
Anonymous
in reply to: brianhiroshi

I learned from Tom Smith on another thread here, in April '08, that there was a change in localized
variable handling at some point, and you can not only put (setq) type variables in the localized
list, but also (defun) functions. That means that you can make *error* a LOCALIZED variable, and
define it within the routine, and it will therefore take over from AutoCAD's only during the
routine, but will be abandoned when it's over like any localized variable, and AutoCAD's will go
back into effect. For example:

{code}
(defun C:Routine (/ *error* bob carol ted alice);<--- note first localized variable
(defun *error* (msg)
(if (/= msg "Function cancelled") (prompt (strcat "\nError: " msg)))
.... or other more elaborate version ....
(setvar 'cmdecho old_cmdecho)
(setvar 'osmode old_osmode)
..... and whatever else you would want to do ....
); end defun - *error*
.... go on with the rest of the routine ....
.... including the same resets, for when *error* is not invoked ....
); end defun - Routine
{code}

Doing it that way means that you DON'T need:
1) a variable name like MyFunctionErrorHandler;
2) to save AutoCAD's with something like (setq old_error *error*);
3) to restore AutoCAD's with something like (setq *error* old_error);
[in fact, you don't need the old_error variable at all].

I have found that a nice little streamlining option.

--
Kent Cooper


"Some Buddy" wrote...
What you are looking for is an error handler, an error routine which temporarely replaces AutoCAD's
native error routine and takes care to do every instruction you code in to it, before restoring
AutoCAD's native error routine. ....
Message 5 of 14
scot-65
in reply to: brianhiroshi

My 2 cents worth...
Try restructuring your programs to allow for user input first, then test the input
before executing the program. Various methods are possible with the key item
being never pause in the middle of a command for user input. Problems such as
what your inquiry is about will be the result when one does not follow this hierarchy.

Take for instance:
Draw an arc using start, end, and radius.
(setq pt1 (getpoint))
(setq pt2 (getpoint pt1))
(if (and pt1 pt2 (setq r1 (getreal)) )
(progn
-----do your thing here without additional input from user-----
);progn
);if

Good Luck!

Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.


Message 6 of 14
Anonymous
in reply to: brianhiroshi

Thanks, for the hint. My error routine is localized in the host routine, but
I didn't know about the other changes. I will remember them.


"Kent Cooper" a écrit dans le message de
news: 6127409@discussion.autodesk.com...
I learned from Tom Smith on another thread here, in April '08, that there
was a change in localized
variable handling at some point, and you can not only put (setq) type
variables in the localized
list, but also (defun) functions. That means that you can make *error* a
LOCALIZED variable, and
define it within the routine, and it will therefore take over from AutoCAD's
only during the
routine, but will be abandoned when it's over like any localized variable,
and AutoCAD's will go
back into effect. For example:

{code}
(defun C:Routine (/ *error* bob carol ted alice);<--- note first localized
variable
(defun *error* (msg)
(if (/= msg "Function cancelled") (prompt (strcat "\nError: " msg)))
.... or other more elaborate version ....
(setvar 'cmdecho old_cmdecho)
(setvar 'osmode old_osmode)
..... and whatever else you would want to do ....
); end defun - *error*
.... go on with the rest of the routine ....
.... including the same resets, for when *error* is not invoked ....
); end defun - Routine
{code}

Doing it that way means that you DON'T need:
1) a variable name like MyFunctionErrorHandler;
2) to save AutoCAD's with something like (setq old_error *error*);
3) to restore AutoCAD's with something like (setq *error* old_error);
[in fact, you don't need the old_error variable at all].

I have found that a nice little streamlining option.

--
Kent Cooper


"Some Buddy" wrote...
What you are looking for is an error handler, an error routine which
temporarely replaces AutoCAD's
native error routine and takes care to do every instruction you code in to
it, before restoring
AutoCAD's native error routine. ....
Message 7 of 14
Anonymous
in reply to: brianhiroshi

For more on the subject, here's the thread where I picked up on it:
http://discussion.autodesk.com/forums/thread.jspa?messageID=5896997ﬥ
--
Kent Cooper


"Some Buddy" wrote...
Thanks, for the hint. My error routine is localized in the host routine, but
I didn't know about the other changes. I will remember them.

"Kent Cooper" ...
I learned from Tom Smith on another thread here, in April '08, .....
Message 8 of 14
Anonymous
in reply to: brianhiroshi

Maybe it's worth mentioning that nesting issue, pointed out by Aaron Lance.
It seems that the proper way to use this new localized *errror* routine
technique with nested functions, is to declare only one *error* routine in
the most outer function, so any failure within that function, be it in its
own code or in a nested function and regardless of the nesting level, will
trigger the local *error* routine, which will hand it back to AutoCAD in the
end. Hope I am not wrong with these assumptions.


"Kent Cooper" a écrit dans le message de
news: 6127720@discussion.autodesk.com...
For more on the subject, here's the thread where I picked up on it:
http://discussion.autodesk.com/forums/thread.jspa?messageID=5896997ﬥ
--
Kent Cooper


"Some Buddy" wrote...
Thanks, for the hint. My error routine is localized in the host routine, but
I didn't know about the other changes. I will remember them.

"Kent Cooper" ...
I learned from Tom Smith on another thread here, in April '08, .....
Message 9 of 14
brianhiroshi
in reply to: brianhiroshi

Thanks guys, the program works nice now!!!
Message 10 of 14
brianhiroshi
in reply to: brianhiroshi

Thanks KentCooper, I've used the program you've showed and now it works great! Could you just tell me what exactly the line "(if (/= msg "Function cancelled") (prompt (strcat "\nError: " msg)))" do?
Thanks
Message 11 of 14
Anonymous
in reply to: brianhiroshi

The *error* function is defined to take an argument, which is called [in this case] 'msg' [short for
"message"] -- the (msg) after the function name is the list of arguments that the function takes.
When an error occurs, there's some kind of message fed to the *error* function by AutoCAD, and that
will be used where 'msg' occurs in the code.

The reason for that line is that if the User hits Escape to cancel the routine, the message AutoCAD
returns will be "Function cancelled", but presumably the User doesn't need to be told that, since
they asked for it themselves. But if the message is *not* that [the not equal (/=) function], then
the *error* function tells the User what happened. Only if the message is something else, such as
an unknown function error, or data type error, or whatever it might be [not caused the the User
cancelling], will it put up a prompt in the Command: line, to let the User know. The message that
it puts up will be "Error: " followed by whatever message AutoCAD returned -- the (strcat) function
puts those two together into one text string.

--
Kent Cooper


brianhiroshi wrote...
Thanks KentCooper, I've used the program you've showed and now it works great! Could you just tell
me what exactly the line "(if (/= msg "Function cancelled") (prompt (strcat "\nError: " msg)))" do?
Thanks
Message 12 of 14
cadking2k5
in reply to: brianhiroshi

I have this at the top and the pt3 and the bottom and it will not rest any of them when i hit esc

(setq ab (getvar "angbase"))
  (setq ad (getvar "angdir"))
  (setq pg (getvar "polarang"))
  (setq om (getvar "CMDECHO"))
  (SETVAR "CMDECHO" 0)
  (setvar "angbase" 0)
  (setvar "angdir" 0)
  (setvar "polarang" 1)

 

 

 

((= pt3 "C")
      (command "angbase" 0 "angdir" 0)
      (command "_line" pt2 ptc "")
      (vl-exit-with-error "")
         (defun *cancel* (msg)
  (if (/= msg "Function cancelled")(prompt (strcat "\n:Cancel")))
  (SETVAR 'CMDECHO cm)
  (setvar 'angbase ab)
  (setvar 'angdir ad)
  (setvar 'polarang pa)
       )
        ); end condition C
    ((= pt3 "D")
     (initget 128 "C W")
     (setq dir (getkword "\Pick angle Direction Counter clockwise or clock Wise[C/W]"))
     (if (null dir)(setq dir "C"))

Message 13 of 14
Lee_Mac
in reply to: cadking2k5

Message 14 of 14
vladislav.babich
in reply to: Lee_Mac

You can probably use this one as well: vl-catch-all-error-p

Keep praying.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost