PDA

View Full Version : SaveVars & ResetVars & *ErrorExample* function


Terry Cadd
2006-07-01, 02:01 AM
Here are two useful functions for saving and resetting your system variables. (SaveVars) saves the current settings you specify, and (ResetVars) resets the settings per the last call to (SaveVars). Ideally you would put (SaveVars) near the top of your program before you change anything, and put (ResetVars) near the end. If you have an *error* function put (ResetVars) near the end also. This is so that if any program uses (SaveVars) and (ResetVars) it will reset the system variables. Notice I did not name *ErrorExample* as *error*, because I wouldn't want to write over an existing one. Just paste in what you need to include. i.e. (ResetVars)
Regards,
Terry Cadd

;-----------------------------
(defun c:Test123 (/ P1 P2)
;Save system variables you will be changing
(SaveVars (list "CLAYER" "OSMODE" "ORTHOMODE"))
;Change system variables in program as desired
(setvar "CLAYER" "0");Might want to check status first?
(setvar "OSMODE" 512);Nearest only
(setvar "ORTHOMODE" 0);Ortho off
(princ "\nDraw a line")
;Even if you cancel here the *error* function runs (Resetvars)
(setq P1 (getpoint "\nSpecify start point: " ))
(if P1
(setq P2 (getpoint "\nSpecify end point: " P1))
);if
(if (and P1 P2)
(command "LINE" P1 P2 "")
);if
(Resetvars);Resets system variables
(princ)
);defun c:Test123

;-----------------------------
; SaveVars - Saves the current state of a specified list of system variables.
; Arguments: 1
; VarList = List of system variables to save
; Syntax: (SaveVars (list "clayer" "osmode" ["snapmode"...] ))
; Returns: Creates the global variable *SysVars* that contains an association
; list of the specified system variables and their current settings to save.
;-----------------------------
(defun SaveVars (VarList)
(foreach item VarList
(setq *SysVars* (append *SysVars* (list (cons item (getvar item)))))
);foreach
);defun SaveVars
;-----------------------------
; ResetVars - Resets system variables to the settings saved by (SaveVars).
; Syntax: (ResetVars)
;-----------------------------
(defun ResetVars ()
(if *SysVars*
(foreach item *SysVars*
(setvar (car item)(cdr item))
);foreach
);if
(setq *SysVars* nil)
);defun ResetVars
;-----------------------------
; *ErrorExample* - Example *error* function for reference (ONLY).
; Notice the call to (ResetVars) to reset system variables if an error occurs.
; I did not want to name this function *error* if you already have one,
; but you can paste the line (ResetVars) into your own *error* function.
;-----------------------------
(defun *ErrorExample* (ErrMsg$)
(if (not (member ErrMsg$ (list "console break" "Function cancelled" "quit / exit abort")))
(princ (strcat "\n" ErrMsg$ "\n"))
);if
(ResetVars)
(princ)
);defun *ErrorExample*
;-----------------------------

[ Moderator Action = ON ] How do I use [ CODE ] tags? (http://forums.augi.com/misc.php?do=bbcode#code) [ Moderator Action = OFF ]

kennet.sjoberg
2006-07-03, 12:37 PM
Do not be surprised if -or when you get this errormessage :

; error: An error has occurred inside the *error*

: ) Happy Computing !

kennet

.T.
2006-07-03, 07:57 PM
Hi Kennet,

Can you elaborate? Where would the problem be? I'm just not seeing it, and I don't want to run into the same problem with my code.

TIA

kennet.sjoberg
2006-07-03, 09:38 PM
Hi Kennet,

Can you elaborate? Where would the problem be? I'm just not seeing it, and I don't want to run into the same problem with my code.

TIA


hmm. . actually I was thinking at next
<snip>
(if P1
(setq P2 (getpoint "\nSpecify end point: " Pt1))
);if
<snip>
but that will cause an other error message, sorry if I misslead you.

: ) Happy Computing !

kennet

BTW
the correct syntax is
(if P1
(setq P2 (getpoint P1 "\nSpecify end point: " ))
);if

.T.
2006-07-03, 09:44 PM
Thanks, Kennet.I wasn't sure if I missed something.

:beer: :beer:

Terry Cadd
2006-07-05, 04:43 PM
The variable Pt1 should have been P1. Sorry!
I found the following two examples in our code here at work, and both seem to work the same.
The first one is referred to in the example in AutoCAD 2006 help, but the second example is found more often in our AutoLISP code. I'm wondering if previous versions used the second example in AutoCAD help.
(if P1 (setq P2 (getpoint P1 "\nSpecify end point: ")))
(if P1 (setq P2 (getpoint "\nSpecify end point: " P1)))

On another note, I friend suggested that I mention that the variables to save in SaveVars should not include (read only) variables, in the case that someone might want to try it. Also we came across an exception with DIMBLK that requires a revision to ResetVars as follows:

;-----------------------------
; ResetVars - Resets system variables to the settings saved by (SaveVars).
; Syntax: (ResetVars)
;-----------------------------
(defun ResetVars ()
(if *SysVars*
(foreach Item *SysVars*
(if (and (= (strcase (car Item)) "DIMBLK")(= (cdr Item) ""))
(setvar "DIMBLK" ".")
(setvar (car Item)(cdr Item))
);if
);foreach
);if
(setq *SysVars* nil)
);defun ResetVars
; Revised per exception with DIMBLK variable. 7-5-06

CAB2k
2006-07-05, 10:28 PM
How about this as an alternative to your code.
;-----------------------------
; SaveVars - Saves the current state of a specified list of system variables.
; Argument: VarList = List of system variables to save
; Syntax: (SaveVars (list "clayer" "osmode" ["snapmode"...] ))
; Returns: Creates the global variable *SysVars* that contains an association
; list of the specified system variables and their current settings to save.
; (("clayer" . "FJ2_Floor Joist") ("osmode" . 175) ("snapmode" . 0))
;-----------------------------
(defun savevars (varlist / err)
(setq *sysvars*
(mapcar
'(lambda (item)
(if (vl-catch-all-error-p
(setq err (vl-catch-all-apply 'getvar (list item)))
)
(print (vl-catch-all-error-message err))

)
(cons item err)
)
varlist
)
)
) ;defun SaveVars

;-----------------------------
; ResetVars - Resets system variables to the settings saved by (SaveVars).
; Syntax: (ResetVars)
;-----------------------------
(defun resetvars ()
(and
(setq *sysvars* (mapcar '(lambda (x) (cons (strcase (car x)) (cdr x))) *sysvars*))
(setq *sysvars* (subst '("DIMBLK" . ".") '("DIMBLK" . "") *sysvars*))
(mapcar '(lambda (item)
(if (vl-catch-all-error-p
(setq err (vl-catch-all-apply 'setvar (list (car item) (cdr item)))))
(print (vl-catch-all-error-message err))
))
*sysvars*
)
(setq *sysvars* nil)
)
) ;defun ResetVars

Terry Cadd
2006-07-06, 12:23 AM
Great version of the code, CAB2k.
In both versions I tested all setvar variables that were initially blank. Without setting anything after saving then in SaveVars, I ran (ResetVars). There were only three variables that I came across that can't be reset back to blank in either version of the code: PROJECTNAME, PUCSBASE, and UCSBASE. I'm wondering if I should also include an exception for these, or for the routine to ignore these, with an error message stating that they were skipped over because of this reason.
Terry Cadd

pnorman
2006-07-06, 04:40 PM
How about these ideas....

When storing the system vars using (SaveVars (list "CLAYER" "OSMODE" "ORTHOMODE")) why not set the values you want at the same time like this

(ppn_sysvar (list (cons "clayer" (getvar "clayer"))'("osmode" . 0)))
or
(ppn_sysvar '(("texteval" . 1)("cmdecho" . 0)))

and how about just having one function rather than two to store or reset the sysvars and then use cond to control what the function does.

here is an example of my sysvar function:

;| function to store and reset system variables
has three conditions
1. if the given argument is list then store the current value
of each system variable in the list and then set the new
value to the value given by the second item in each pair
eg.
(ppn_sysvar '(("texteval" . 1)("cmdecho" . 0)))
(ppn_sysvar (list (cons "clayer" (getvar "clayer"))))
(ppn_sysvar (list (cons "clayer" (getvar "clayer"))'("osmode" . 0)))
2. if the given argument is an integer then reset that number of system
variables from the list of variables in *SYSVAR_LIST*
eg.
(ppn_sysvar 2)
3. if the given argument is nil then reset all sysvars
in the list of variables in *SYSVAR_LIST*
|;
(defun ppn_sysvar (SYSVARLST / SYSVAR)
(cond
((= (type SYSVARLST) 'LIST)
(foreach SYSVAR SYSVARLST
(setq *SYSVAR_LIST* (cons (cons (car SYSVAR) (getvar (car SYSVAR))) *SYSVAR_LIST*))
(vla-setvariable (active-document) (car SYSVAR) (cdr SYSVAR))
)
)
((= (type SYSVARLST) 'INT)
(if *SYSVAR_LIST*
(repeat SYSVARLST
(setq SYSVAR (car *SYSVAR_LIST*))
(setq *SYSVAR_LIST* (cdr *SYSVAR_LIST*))
(vla-setvariable (active-document) (car SYSVAR) (cdr SYSVAR))
)
)
)
((= SYSVARLST nil)
(repeat (length *SYSVAR_LIST*)
(setq SYSVAR (car *SYSVAR_LIST*))
(setq *SYSVAR_LIST* (cdr *SYSVAR_LIST*))
(vla-setvariable (active-document) (car SYSVAR) (cdr SYSVAR))
)
)
)
(princ)
)


And another thing to consider might be the use of global and local error handlers together.
Also I included undo control into my error handler.

see the attached file for the full example.

Cheers
Phill

PS great post Terry

Terry Cadd
2006-07-06, 09:19 PM
Phill,
I downloaded your ErrorTools.lsp file and tried some of the examples. They worked fine. I like your style of remarks and instructions. It makes it so much easier for someone to use and understand your code.
Terry Cadd

Isn’t sharing great!

pnorman
2006-07-06, 10:07 PM
Isn’t sharing great!
You're welcome Terry.
I have learnt a lot from people sharing.
Hopefully what goes around comes around.

Cheers
Phill

whdjr
2006-07-07, 06:21 PM
This is what I use.

;;;
;;;(setq var_names '("OSMODE" "ORTHOMODE" "CMDECHO" "BLIPMODE")
;;; var_vars '(osm otm cmd bpm)
;;; var_vals '(0 1 0 0)
;;;)
;;;Usage: (store_old_vals var_vars var_names)
;;; (set_new_vals var_names var_vals)
;;; (restore_old_vals var_names var_vars)
;;; Restore also goes in the error handler.
(defun *store_old_vals* (vars names)
(mapcar 'set vars (mapcar 'getvar names))
)

(defun *set_new_vals* (names vals)
(mapcar 'setvar names vals)
)

(defun *restore_old_vals* (names vars)
(mapcar 'setvar names (mapcar 'eval vars))
)
;;;

kennet.sjoberg
2006-07-07, 07:15 PM
There is more than 70 write protected ( RO ) SYSTEM variables that you accidently may include in your LIST
Here is one way to awoid "; error: An error has occurred inside the *error*" in your global error handler, that trap the real error.

(defun ChangeSysVar ( Name Value / *error* ) ;; <-- function *error* declared as Local... ! ! IMPORTANT ! !
;; If the function *error* is not declared as local, it REPLACE the default AutoCAD errorhandler ! !
;; To name the local function *error* as *MYerror* does not work ( for me ), this is a kind of strange. . . or ?
;; OK, Local error function that treat the error, and do not replace the default AutoCAD errorhandler when declared as local.
(defun *error* (msg)
(if (= (getvar "ERRNO" ) 20 ) (princ (strcat Name " is a write protected SYSTEM variable" )) (princ "Untreated Error" ) )
(setvar "ERRNO" 0 )
)
(setvar "ERRNO" 0 ) ;; Reset the ERRNO SYSTEM variable
(setvar Name Value ) ;; Statement that may cause the error, and that you can replace with mapcar/foreach/lambda/list things...
(princ)
)


-----------------------------------------------------------------------------------------------------------
Just a test :

Command: (/ 1 0 )
Error: divide by zero <- Default AutoCAD errorhandler

Load ChangeSysVar
CHANGESYSVAR <- Function ChangeSysVar is loaded

Command: (/ 1 0 )
Error: divide by zero <- Default AutoCAD errorhandler

Command: (setvar "OSMODE" 111 )
111 <- OK, normal prompt

Command: (setvar "AREA" 111 )
Error: AutoCAD variable setting rejected: "AREA" 111 <- Default AutoCAD errorhandler

Command: (ChangeSysVar "OSMODE" 111 )
Command: <- OK, function changed not ( RO ) System variable

Command: (ChangeSysVar "AREA" 111 )
Write protected SYSTEM variable <- Local errorhandler in the ChangeSysVar function trapped the error

Command: (/ 1 0 )
Error: divide by zero <- STILL Default AutoCAD errorhandler

: ) Happy Computing !

kennet