1 | ;+ |
---|
2 | ; NAME: |
---|
3 | ; ERROR_MESSAGE |
---|
4 | ; |
---|
5 | ; PURPOSE: |
---|
6 | ; |
---|
7 | ; The purpose of this function is to have a device-independent |
---|
8 | ; error messaging function. The error message is reported |
---|
9 | ; to the user by using DIALOG_MESSAGE if widgets are |
---|
10 | ; supported and MESSAGE otherwise. |
---|
11 | ; |
---|
12 | ; In general, the ERROR_MESSAGE function is not called directly. |
---|
13 | ; Rather, it is used in a CATCH error handler. Errors are thrown |
---|
14 | ; to ERROR_MESSAGE with the MESSAGE command. A typical CATCH error |
---|
15 | ; handler is shown below. |
---|
16 | ; |
---|
17 | ; Catch, theError |
---|
18 | ; IF theError NE 0 THEN BEGIN |
---|
19 | ; Catch, /Cancel |
---|
20 | ; ok = Error_Message() |
---|
21 | ; RETURN |
---|
22 | ; ENDIF |
---|
23 | ; |
---|
24 | ; Error messages would get into the ERROR_MESSAGE function by |
---|
25 | ; throwing an error with the MESSAGE command, like this: |
---|
26 | ; |
---|
27 | ; IF test NE 1 THEN Message, 'The test failed.' |
---|
28 | ; |
---|
29 | ; AUTHOR: |
---|
30 | ; |
---|
31 | ; FANNING SOFTWARE CONSULTING |
---|
32 | ; David Fanning, Ph.D. |
---|
33 | ; 1645 Sheely Drive |
---|
34 | ; Fort Collins, CO 80526 USA |
---|
35 | ; Phone: 970-221-0438 |
---|
36 | ; E-mail: davidf@dfanning.com |
---|
37 | ; Coyote's Guide to IDL Programming: http://www.dfanning.com/ |
---|
38 | ; |
---|
39 | ; CATEGORY: |
---|
40 | ; |
---|
41 | ; Utility. |
---|
42 | ; |
---|
43 | ; CALLING SEQUENCE: |
---|
44 | ; |
---|
45 | ; ok = Error_Message(the_Error_Message) |
---|
46 | ; |
---|
47 | ; INPUTS: |
---|
48 | ; |
---|
49 | ; the_Error_Message: This is a string argument containing the error |
---|
50 | ; message you want reported. If undefined, this variable is set |
---|
51 | ; to the string in the !Error_State.Msg system variable. |
---|
52 | ; |
---|
53 | ; KEYWORDS: |
---|
54 | ; |
---|
55 | ; ERROR: Set this keyword to cause Dialog_Message to use the ERROR |
---|
56 | ; reporting dialog. Note that a bug in IDL causes the ERROR dialog |
---|
57 | ; to be used whether this keyword is set to 0 or 1! |
---|
58 | ; |
---|
59 | ; INFORMATIONAL: Set this keyword to cause Dialog_Message to use the |
---|
60 | ; INFORMATION dialog instead of the WARNING dialog. Note that a bug |
---|
61 | ; in IDL causes the ERROR dialog to be used if this keyword is set to 0! |
---|
62 | ; |
---|
63 | ; TITLE: Set this keyword to the title of the DIALOG_MESSAGE window. By |
---|
64 | ; default the keyword is set to 'System Error' unless !ERROR_STATE.NAME |
---|
65 | ; equals "IDL_M_USER_ERR", in which case it is set to "Trapped Error'. |
---|
66 | ; |
---|
67 | ; TRACEBACK: Setting this keyword results in an error traceback |
---|
68 | ; being printed to standard output with the PRINT command. Set to |
---|
69 | ; 1 (ON) by default. Use TRACEBACK=0 to turn this functionality off. |
---|
70 | ; |
---|
71 | ; OUTPUTS: |
---|
72 | ; |
---|
73 | ; Currently the only output from the function is the string "OK". |
---|
74 | ; |
---|
75 | ; RESTRICTIONS: |
---|
76 | ; |
---|
77 | ; The WARNING Dialog_Message dialog is used by default. |
---|
78 | ; |
---|
79 | ; EXAMPLE: |
---|
80 | ; |
---|
81 | ; To handle an undefined variable error: |
---|
82 | ; |
---|
83 | ; IF N_Elements(variable) EQ 0 THEN $ |
---|
84 | ; ok = Error_Message('Variable is undefined') |
---|
85 | ; |
---|
86 | ; MODIFICATION HISTORY: |
---|
87 | ; |
---|
88 | ; Written by: David W. Fanning, 27 April 1999. |
---|
89 | ; Added the calling routine's name in the message and NoName keyword. 31 Jan 2000. DWF. |
---|
90 | ; Added _Extra keyword. 10 February 2000. DWF. |
---|
91 | ; Forgot to add _Extra everywhere. Fixed for MAIN errors. 8 AUG 2000. DWF. |
---|
92 | ; Adding call routine's name to Traceback Report. 8 AUG 2000. DWF. |
---|
93 | ; Added ERROR, INFORMATIONAL, and TITLE keywords. 19 SEP 2002. DWF. |
---|
94 | ; Removed the requirement that you use the NONAME keyword with the MESSAGE |
---|
95 | ; command when generating user-trapped errors. 19 SEP 2002. DWF. |
---|
96 | ; Added distinctions between trapped errors (errors generated with the |
---|
97 | ; MESSAGE command) and IDL system errors. Note that if you call ERROR_MESSAGE |
---|
98 | ; directly, then the state of the !ERROR_STATE.NAME variable is set |
---|
99 | ; to the *last* error generated. It is better to access ERROR_MESSAGE |
---|
100 | ; indirectly in a Catch error handler from the MESSAGE command. 19 SEP 2002. DWF. |
---|
101 | ; Change on 19 SEP 2002 to eliminate NONAME requirement did not apply to object methods. |
---|
102 | ; Fixed program to also handle messages from object methods. 30 JULY 2003. DWF. |
---|
103 | ; Removed obsolete STR_SEP and replaced with STRSPLIT. 27 Oct 2004. DWF. |
---|
104 | ; Made a traceback the default case without setting TRACEBACK keyword. 19 Nov 2004. DWF. |
---|
105 | ; Added check for window connection specifically for CRON jobs. 6 May 2008. DWF. |
---|
106 | ;- |
---|
107 | ;########################################################################### |
---|
108 | ; |
---|
109 | ; LICENSE |
---|
110 | ; |
---|
111 | ; This software is OSI Certified Open Source Software. |
---|
112 | ; OSI Certified is a certification mark of the Open Source Initiative. |
---|
113 | ; |
---|
114 | ; Copyright 1999-2008 Fanning Software Consulting |
---|
115 | ; |
---|
116 | ; This software is provided "as-is", without any express or |
---|
117 | ; implied warranty. In no event will the authors be held liable |
---|
118 | ; for any damages arising from the use of this software. |
---|
119 | ; |
---|
120 | ; Permission is granted to anyone to use this software for any |
---|
121 | ; purpose, including commercial applications, and to alter it and |
---|
122 | ; redistribute it freely, subject to the following restrictions: |
---|
123 | ; |
---|
124 | ; 1. The origin of this software must not be misrepresented; you must |
---|
125 | ; not claim you wrote the original software. If you use this software |
---|
126 | ; in a product, an acknowledgment in the product documentation |
---|
127 | ; would be appreciated, but is not required. |
---|
128 | ; |
---|
129 | ; 2. Altered source versions must be plainly marked as such, and must |
---|
130 | ; not be misrepresented as being the original software. |
---|
131 | ; |
---|
132 | ; 3. This notice may not be removed or altered from any source distribution. |
---|
133 | ; |
---|
134 | ; For more information on Open Source Software, visit the Open Source |
---|
135 | ; web site: http://www.opensource.org. |
---|
136 | ; |
---|
137 | ;########################################################################### |
---|
138 | |
---|
139 | |
---|
140 | FUNCTION ERROR_MESSAGE, theMessage, Error=error, Informational=information, $ |
---|
141 | Traceback=traceback, NoName=noname, Title=title, _Extra=extra |
---|
142 | |
---|
143 | On_Error, 2 |
---|
144 | |
---|
145 | ; Check for presence and type of message. |
---|
146 | |
---|
147 | IF N_Elements(theMessage) EQ 0 THEN theMessage = !Error_State.Msg |
---|
148 | s = Size(theMessage) |
---|
149 | messageType = s[s[0]+1] |
---|
150 | IF messageType NE 7 THEN BEGIN |
---|
151 | Message, "The message parameter must be a string.", _Extra=extra |
---|
152 | ENDIF |
---|
153 | IF N_Elements(traceback) EQ 0 THEN traceback = 1 |
---|
154 | |
---|
155 | ; Get the call stack and the calling routine's name. |
---|
156 | Help, Calls=callStack |
---|
157 | callingRoutine = (StrSplit(StrCompress(callStack[1])," ", /Extract))[0] |
---|
158 | |
---|
159 | |
---|
160 | |
---|
161 | |
---|
162 | ; Are widgets supported? |
---|
163 | widgetsSupported = ((!D.Flags AND 65536L) NE 0) |
---|
164 | |
---|
165 | ; It is not enough to know if widgets are supported. In CRON jobs, widgets are |
---|
166 | ; supported, but there is no X connection and pop-up dialogs are not allowed. |
---|
167 | ; Here is a quick test to see if we can connect to a windowing system. If not, |
---|
168 | ; then we are going to assume widgets are not supported. |
---|
169 | Catch, theError |
---|
170 | IF theError NE 0 THEN BEGIN |
---|
171 | Catch, /CANCEL |
---|
172 | widgetsSupported = 0 |
---|
173 | GOTO, testWidgetSupport |
---|
174 | ENDIF |
---|
175 | theWindow = !D.Window |
---|
176 | Window, /FREE, XSIZE=5, YSIZE=5, /PIXMAP |
---|
177 | Catch, /CANCEL |
---|
178 | |
---|
179 | testWidgetSupport: ; Come here if you choke on creating a window. |
---|
180 | IF !D.Window NE theWindow THEN BEGIN |
---|
181 | WDelete, !D.Window |
---|
182 | IF theWindow GE 0 THEN WSet, theWindow |
---|
183 | ENDIF |
---|
184 | |
---|
185 | IF widgetsSupported THEN BEGIN |
---|
186 | |
---|
187 | ; If this is an error produced with the MESSAGE command, it is a trapped |
---|
188 | ; error and will have the name "IDL_M_USER_ERR". |
---|
189 | IF !ERROR_STATE.NAME EQ "IDL_M_USER_ERR" THEN BEGIN |
---|
190 | |
---|
191 | IF N_Elements(title) EQ 0 THEN title = 'Trapped Error' |
---|
192 | |
---|
193 | ; If the message has the name of the calling routine in it, |
---|
194 | ; it should be stripped out. Can you find a colon in the string? |
---|
195 | |
---|
196 | ; Is the calling routine an object method? If so, special processing |
---|
197 | ; is required. Object methods will have two colons together. |
---|
198 | doublecolon = StrPos(theMessage, "::") |
---|
199 | IF doublecolon NE -1 THEN BEGIN |
---|
200 | |
---|
201 | prefix = StrMid(theMessage, 0, doublecolon+2) |
---|
202 | submessage = StrMid(theMessage, doublecolon+2) |
---|
203 | colon = StrPos(submessage, ":") |
---|
204 | IF colon NE -1 THEN BEGIN |
---|
205 | |
---|
206 | ; Extract the text up to the colon. Is this the same as |
---|
207 | ; the callingRoutine? If so, strip it. |
---|
208 | IF StrMid(theMessage, 0, colon+StrLen(prefix)) EQ callingRoutine THEN $ |
---|
209 | theMessage = StrMid(theMessage, colon+1+StrLen(prefix)) |
---|
210 | ENDIF |
---|
211 | ENDIF ELSE BEGIN |
---|
212 | |
---|
213 | colon = StrPos(theMessage, ":") |
---|
214 | IF colon NE -1 THEN BEGIN |
---|
215 | |
---|
216 | ; Extract the text up to the colon. Is this the same as |
---|
217 | ; the callingRoutine? If so, strip it. |
---|
218 | IF StrMid(theMessage, 0, colon) EQ callingRoutine THEN $ |
---|
219 | theMessage = StrMid(theMessage, colon+1) |
---|
220 | ENDIF |
---|
221 | |
---|
222 | ENDELSE |
---|
223 | |
---|
224 | |
---|
225 | ; Add the calling routine's name, unless NONAME is set. |
---|
226 | IF Keyword_Set(noname) THEN BEGIN |
---|
227 | answer = Dialog_Message(theMessage, Title=title, _Extra=extra, $ |
---|
228 | Error=error, Information=information) |
---|
229 | ENDIF ELSE BEGIN |
---|
230 | answer = Dialog_Message(StrUpCase(callingRoutine) + ": " + $ |
---|
231 | theMessage, Title=title, _Extra=extra, $ |
---|
232 | Error=error, Information=information) |
---|
233 | ENDELSE |
---|
234 | |
---|
235 | ENDIF ELSE BEGIN |
---|
236 | |
---|
237 | ; Otherwise, this is an IDL system error. |
---|
238 | IF N_Elements(title) EQ 0 THEN title = 'System Error' |
---|
239 | |
---|
240 | IF StrUpCase(callingRoutine) EQ "$MAIN$" THEN $ |
---|
241 | answer = Dialog_Message(theMessage, _Extra=extra, Title=title, $ |
---|
242 | Error=error, Information=information) ELSE $ |
---|
243 | IF Keyword_Set(noname) THEN BEGIN |
---|
244 | answer = Dialog_Message(theMessage, _Extra=extra, Title=title, $ |
---|
245 | Error=error, Information=information) |
---|
246 | ENDIF ELSE BEGIN |
---|
247 | answer = Dialog_Message(StrUpCase(callingRoutine) + "--> " + $ |
---|
248 | theMessage, _Extra=extra, Title=title, $ |
---|
249 | Error=error, Information=information) |
---|
250 | ENDELSE |
---|
251 | ENDELSE |
---|
252 | ENDIF ELSE BEGIN |
---|
253 | Message, theMessage, /Continue, /NoPrint, /NoName, /NoPrefix, _Extra=extra |
---|
254 | Print, '%' + callingRoutine + ': ' + theMessage |
---|
255 | answer = 'OK' |
---|
256 | ENDELSE |
---|
257 | |
---|
258 | ; Provide traceback information if requested and this is NOT an informational message. |
---|
259 | IF Keyword_Set(traceback) AND ~Keyword_Set(informational)THEN BEGIN |
---|
260 | Help, /Last_Message, Output=traceback |
---|
261 | Print,'' |
---|
262 | Print, 'Traceback Report from ' + StrUpCase(callingRoutine) + ':' |
---|
263 | Print, '' |
---|
264 | FOR j=0,N_Elements(traceback)-1 DO Print, " " + traceback[j] |
---|
265 | ENDIF |
---|
266 | |
---|
267 | RETURN, answer |
---|
268 | END ; ---------------------------------------------------------------------------- |
---|
269 | |
---|