source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/VSANS/V_Transmission.ipf @ 1246

Last change on this file since 1246 was 1246, checked in by srkline, 2 years ago

A large number of changes to the size of panels to enable "Laptop Mode" where all of the panels and controls are scaled down so that they fit on screen and are still in correct proportion. For the laptop I'm using for testing, the resolution is 1920x1080. For this, a scaling of 0.7 seems to work. The on/off of the "laptop Mode" is controlled by a checkbox in the preference panel (under the General tab).

There are still more panels to update in the next commit.

File size: 18.1 KB
Line 
1#pragma TextEncoding = "MacRoman"
2#pragma rtGlobals=3             // Use modern global access method and strict wave access.
3#pragma IgorVersion = 7.00
4
5
6
7// TODO
8// x- initialization
9// x- link to main panel
10//
11// ?? redesign the panel based on the CATALOG?
12// -- refresh the catalog, then work with those waves?
13//
14// -- this still seems to be very awkward to use. Come up with something better
15//
16// -- need more checks - be sure that the files match
17// -- SDD, wavelength, beam on proper panel, etc.
18//
19// -- need popups (transmission, open) to respond to popup changes and
20//   update their fields, since they may be auto-located incorrectly.
21//
22// to patch the box coordinates
23// err = V_writeBoxCoordinates(fname,V_List2NumWave(str,";","inW"))
24
25
26
27//
28Function V_InitTransmissionPanel()
29       
30        DoWindow/F V_TransmissionPanel
31        if(V_Flag == 0)
32                V_InitTransPanelGlobals()
33                Execute "V_TransmissionPanel()"
34        endif
35End
36
37Function V_InitTransPanelGlobals()
38
39// root:Packages:NIST:VSANS:Globals:Transmission
40        NewDataFolder/O/S root:Packages:NIST:VSANS:Globals:Transmission
41        Variable/G gSamGrpID,gTrnGrpID,gTrans,gTransErr
42        String/G gSamLabel="file label",gTransLabel="file label",gEmptyLabel="file label"
43        String/G gEmptyBoxCoord="1;2;3;4;",gEmptyPanel="ENTER PANEL"
44        String/G gSamMatchList = "_none_"
45        String/G gTransMatchList = "_none_"
46
47
48        SetDataFolder root:
49        return(0)
50End
51
52Window V_TransmissionPanel() : Panel
53
54        Variable sc = 1
55                       
56        if(root:Packages:NIST:VSANS:Globals:gLaptopMode == 1)
57                sc = 0.7
58        endif
59       
60        PauseUpdate; Silent 1           // building window...
61        NewPanel /W=(1496*sc,366*sc,1950*sc,940*sc) /K=1
62        ModifyPanel cbRGB=(32896,16448,0,19621)
63        DoWindow/C V_TransmissionPanel
64
65//      ShowTools/A
66        PopupMenu popup_0,pos={sc*16.00,359.00*sc},size={sc*104.00,23.00*sc},fstyle=1,fsize=12*sc,proc=V_TSamFilePopMenuProc,title="Sample"
67        PopupMenu popup_0,mode=1,popvalue="_none_",value= #"root:Packages:NIST:VSANS:Globals:Transmission:gSamMatchList"
68        PopupMenu popup_1,pos={sc*12.00,229.00*sc},size={sc*195.00,23.00*sc},fstyle=1,fsize=12*sc,proc=V_TTransmFilePopMenuProc,title="Transmission"
69        PopupMenu popup_1,mode=1,popvalue="_none_",value = #"root:Packages:NIST:VSANS:Globals:Transmission:gTransMatchList"//value= V_getFilePurposeList("TRANSMISSION",0)
70        PopupMenu popup_2,pos={sc*17.00,79.00*sc},size={sc*188.00,23.00*sc},fstyle=1,fsize=12*sc,proc=V_TEmpBeamPopMenuProc,title="Open Beam"
71        PopupMenu popup_2,mode=1,popvalue="sans1.nxs.ngv",value= V_getFileIntentList("OPEN BEAM",0)
72        Button button_0,pos={sc*34.00,499.00*sc},size={sc*100.00,20.00*sc},proc=V_CalcTransmButtonProc,title="Calculate"
73        Button button_2,pos={sc*340.00,13.00*sc},size={sc*30.00,20.00*sc},proc=V_HelpTransmButtonProc,title="?"
74        Button button_3,pos={sc*380.00,13.00*sc},size={sc*50.00,20.00*sc},proc=V_DoneTransmButtonProc,title="Done"
75        Button button_4,pos={sc*164.00,500.00*sc},size={sc*150.00,20.00*sc},proc=V_CalcTransmListButtonProc,title="Calculate All In Popup"
76        SetVariable setvar_0,pos={sc*18.00,390.00*sc},size={sc*300.00,14.00*sc},title="Label:"
77        SetVariable setvar_0,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gSamLabel
78        SetVariable setvar_1,pos={sc*18.00,417.00*sc},size={sc*300.00,14.00*sc},title="Group ID:"
79        SetVariable setvar_1,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gSamGrpID
80        SetVariable setvar_2,pos={sc*15.00,257.00*sc},size={sc*300.00,14.00*sc},title="Label:"
81        SetVariable setvar_2,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gTransLabel
82        SetVariable setvar_3,pos={sc*14.00,283.00*sc},size={sc*300.00,14.00*sc},title="Group ID:"
83        SetVariable setvar_3,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gTrnGrpID
84        SetVariable setvar_4,pos={sc*18.00,108.00*sc},size={sc*300.00,14.00*sc},title="Label:"
85        SetVariable setvar_4,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gEmptyLabel
86        SetVariable setvar_5,pos={sc*18.00,132.00*sc},size={sc*300.00,14.00*sc},title="XY Box:"
87        SetVariable setvar_5,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gEmptyBoxCoord
88        SetVariable setvar_6,pos={sc*18.00,157.00*sc},size={sc*300.00,14.00*sc},title="Panel:"          //,fstyle=1,fsize=12*sc
89        SetVariable setvar_6,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gEmptyPanel
90        SetVariable setvar_7,pos={sc*18.00,442.00*sc},size={sc*300.00,14.00*sc},title="Transmission:"
91        SetVariable setvar_7,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gTrans
92        SetVariable setvar_8,pos={sc*18.00,467.00*sc},size={sc*300.00,14.00*sc},title="Error:"
93        SetVariable setvar_8,limits={-inf,inf,0},value= root:Packages:NIST:VSANS:Globals:Transmission:gTransErr
94EndMacro
95
96
97
98
99// TODO
100// -- fill in the details
101// -- currently, I pick these from the Catalog, for speed
102// -- ? is the catalog current?
103// -- T error is not part of the Catalog - is that OK?
104//
105// when the SAM file menu is popped:
106//  fill in the fields:
107// x- label
108// x- group id
109// x- transmission
110// -- T error
111//
112Function V_TSamFilePopMenuProc(pa) : PopupMenuControl
113        STRUCT WMPopupAction &pa
114
115
116// **** TODO
117// short-circuit the switch, and simply report the values
118// -- the TransFile popup now drives the panel
119                SVAR gSamLabel = root:Packages:NIST:VSANS:Globals:Transmission:gSamLabel
120                gSamLabel = V_getSampleDescription(pa.popStr)
121                NVAR gSamGrpID = root:Packages:NIST:VSANS:Globals:Transmission:gSamGrpID
122                gSamGrpID = V_getSample_GroupID(pa.popStr)
123                NVAR gTrans = root:Packages:NIST:VSANS:Globals:Transmission:gTrans
124                gTrans = V_getSampleTransmission(pa.popStr)
125                NVAR gTransErr = root:Packages:NIST:VSANS:Globals:Transmission:gTransErr
126                gTransErr = V_getSampleTransError(pa.popStr)
127
128        return(0)       
129       
130End
131
132// TODO
133//
134// Given the group ID of the sample, try to locate a (the) matching transmission file
135// by locating a matching ID in the list of transmission (intent) files
136//
137// then pop the menu
138//
139//
140Function V_TTransmFilePopMenuProc(pa) : PopupMenuControl
141        STRUCT WMPopupAction &pa
142
143        switch( pa.eventCode )
144                case 2: // mouse up
145                        Variable popNum = pa.popNum
146                        String popStr = pa.popStr
147                       
148                        SVAR gTransLabel = root:Packages:NIST:VSANS:Globals:Transmission:gTransLabel
149                        gTransLabel = V_getSampleDescription(popStr)
150                        NVAR gTrnGrpID = root:Packages:NIST:VSANS:Globals:Transmission:gTrnGrpID
151                        gTrnGrpID = V_getSample_GroupID(popStr)                 
152                       
153//                      SVAR gSamMatchList = root:Packages:NIST:VSANS:Globals:Transmission:gSamMatchList
154//                      String quote = "\""
155//                      gSamMatchList = quote + V_getFileIntentPurposeIDList("SAMPLE","SCATTERING",gTrnGrpID,0) + quote
156                        // this resets a global string, since I can't pass a parameter (only constants) in value=fn()           
157//                      PopupMenu popup_0,mode=1,value=#gSamMatchList
158                        PopupMenu popup_0,mode=1,win=V_TransmissionPanel,value=V_getSamListForPopup()
159
160
161// then pop the sample list with the top file to see that it is a match for the transmission file
162                        STRUCT WMPopupAction samPopAct
163                        ControlInfo/W=V_TransmissionPanel popup_0
164                        samPopAct.popStr = S_Value              // the top file
165                        V_TSamFilePopMenuProc(samPopAct)
166                       
167                        break
168                case -1: // control being killed
169                        break
170        endswitch
171
172        return 0
173End
174
175Function/S V_getSamListForPopup()
176
177//      String quote = "\""
178        NVAR gTrnGrpID = root:Packages:NIST:VSANS:Globals:Transmission:gTrnGrpID
179
180        String retStr = V_getFileIntentPurposeIDList("SAMPLE","SCATTERING",gTrnGrpID,0)
181
182// and be sure to add in the empty cell, since it's not a "sample"
183        retStr += V_getFileIntentPurposeIDList("EMPTY CELL","SCATTERING",gTrnGrpID,0)
184
185        // now filter through the string to refine the list to only scattering files that match
186        // the transmission file conditions
187        String newList="",item
188        Variable num,ii
189       
190        String transStr
191        ControlInfo/W=V_TransmissionPanel popup_1                       //the transmission file popup
192        transStr = S_Value
193       
194        num=ItemsInList(retStr)
195        for(ii=0;ii<num;ii+=1)
196                item = StringFromList(ii, retStr,";")
197                if(V_Scatter_Match_Trans(transStr,item))
198                        newList += item + ";"
199                endif
200        endfor
201
202        SVAR newSamList = root:Packages:NIST:VSANS:Globals:Transmission:gSamMatchList
203        newSamList = newList
204       
205        return(newList)
206End
207
208
209Function/S V_getTransListForPopup()
210
211        String retStr =""
212       
213//      retStr = V_getFilePurposeList("TRANSMISSION",0)
214       
215        retStr = V_getFileIntentPurposeList("Sample","TRANSMISSION",0)
216        retStr += V_getFileIntentPurposeList("Empty Cell","TRANSMISSION",0)
217       
218        // now filter through the string to refine the list to only transmission files that match
219        // the open beam file conditions
220        String newList="",item
221        Variable num,ii
222       
223        String openStr
224        ControlInfo/W=V_TransmissionPanel popup_2               //the open beam popup
225        openStr = S_Value
226       
227        num=ItemsInList(retStr)
228        for(ii=0;ii<num;ii+=1)
229                item = StringFromList(ii, retStr,";")
230                if(V_Trans_Match_Open(openStr,item))
231                        newList += item + ";"
232                endif
233        endfor
234
235        SVAR newTransList = root:Packages:NIST:VSANS:Globals:Transmission:gTransMatchList
236        newTransList = newList
237       
238        return(newList)
239       
240End
241
242Function V_TEmpBeamPopMenuProc(pa) : PopupMenuControl
243        STRUCT WMPopupAction &pa
244
245        switch( pa.eventCode )
246                case 2: // mouse up
247                        Variable popNum = pa.popNum
248                        String popStr = pa.popStr
249                       
250                        Print "empty beam match at ",popStr
251                        SetVariable setvar_4,value=_STR:V_getSampleDescription(popStr)
252                       
253
254                        WAVE boxCoord = V_getBoxCoordinates(popStr)
255                        Print boxCoord
256                        SetVariable setvar_5,value=_STR:V_NumWave2List(boxCoord,";")
257                       
258                        String detStr = V_getReduction_BoxPanel(popStr)
259                        SetVariable setvar_6,value =_STR:detStr
260                       
261                        PopupMenu popup_1,mode=1,value=V_getTransListForPopup()
262                       
263                        SVAR newBox = root:Packages:NIST:VSANS:Globals:Transmission:gEmptyBoxCoord
264                        newBox = V_NumWave2List(boxCoord,";")
265                       
266                        break
267                case -1: // control being killed
268                        break
269        endswitch
270
271        return 0
272End
273
274
275// NOTE: DIV is not needed for the transmission calculation, since it's a ratio
276// and the DIV simply drops out. (DIV is needed for ABS scaling calculation of Kappa, since
277// that is not a ratio)
278//
279// TODO
280// -- figure out which detector corrections are necessary to do on loading
281// data for calculation. Then set/reset preferences accordingly
282// (see V_isoCorrectButtonProc() for example of how to do this)
283//
284//  -- DIV (turn off)
285// -- NonLinear (turn off ?)
286// -- solid angle (turn off ?)
287// -- dead time (keep on?)
288//
289// -- once calculated, update the Transmission panel
290// -- update the data file
291// -- update the CATALOG (and/or delete the RawVSANS to force a re-read)
292//
293Function V_CalcTransmButtonProc(ba) : ButtonControl
294        STRUCT WMButtonAction &ba
295
296        switch( ba.eventCode )
297                case 2: // mouse up
298                        // click code here
299
300                        String SamFile,TransFile,EmptyFile
301
302                        ControlInfo/W=V_TransmissionPanel popup_0
303                        SamFile = S_Value
304
305                        ControlInfo/W=V_TransmissionPanel popup_1
306                        TransFile = S_Value             
307               
308                        ControlInfo/W=V_TransmissionPanel popup_2
309                        EmptyFile = S_Value
310               
311                        V_CalcOneTransmission(SamFile,TransFile,EmptyFile)                     
312
313                       
314                        // done
315                        break
316                case -1: // control being killed
317                        break
318        endswitch
319
320
321        return 0
322End
323
324Function V_CalcTransmListButtonProc(ba) : ButtonControl
325        STRUCT WMButtonAction &ba
326
327        switch( ba.eventCode )
328                case 2: // mouse up
329                        // click code here
330
331                        SVAR gSamMatchList = root:Packages:NIST:VSANS:Globals:Transmission:gSamMatchList
332
333                        String SamFile,TransFile,EmptyFile
334
335                        ControlInfo/W=V_TransmissionPanel popup_1
336                        TransFile = S_Value             
337               
338                        ControlInfo/W=V_TransmissionPanel popup_2
339                        EmptyFile = S_Value
340               
341                        String list
342                        list = gSamMatchList
343//                      list = list[1,strlen(list)-1]
344//                      list = list[0,strlen(list)-2]
345                       
346                        Variable num,ii
347                        num = ItemsInList(list, ";")
348                        for(ii=0;ii<num;ii+=1)
349                                SamFile = StringFromList(ii, list, ";")
350                               
351                                if(ii==0)
352                                        // calculate the transmission for the first file
353                                        V_CalcOneTransmission(SamFile,TransFile,EmptyFile)     
354                                else
355                                        // then just write in the values (globals) that V_CalcOne determined
356                                        NVAR gTrans = root:Packages:NIST:VSANS:Globals:Transmission:gTrans
357                                        NVAR gTransErr = root:Packages:NIST:VSANS:Globals:Transmission:gTransErr
358                                       
359                                        // write both out to the sample *scattering* file on disk
360                                        V_writeSampleTransmission(SamFile,gTrans)
361                                        V_writeSampleTransError(SamFile,gTransErr)     
362
363                                endif           
364                        endfor
365                       
366                        Print "Done Processing Transmission List"
367
368                        // done
369                        break
370                case -1: // control being killed
371                        break
372        endswitch
373
374
375        return 0
376End
377
378
379
380Function V_CalcOneTransmission(SamFileName,TransFileName,EmptyFileName)                 
381        String SamFileName,TransFileName,EmptyFileName
382
383                Variable trans,trans_err
384                Variable emptyCts,empty_ct_err,samCts,sam_ct_err
385                String detStr
386               
387               
388                // save preferences for file loading
389                Variable savDivPref,savSAPref
390                NVAR gDoDIVCor = root:Packages:NIST:VSANS:Globals:gDoDIVCor
391                savDivPref = gDoDIVCor
392                NVAR gDoSolidAngleCor = root:Packages:NIST:VSANS:Globals:gDoSolidAngleCor
393                savSAPref = gDoSolidAngleCor
394               
395                // set local preferences
396                gDoDIVCor = 0
397                gDoSolidAngleCor = 0
398               
399                // check for sample transmission + error
400                // if present -- exit
401               
402                trans = V_getSampleTransmission(samfileName)
403                trans_err = V_getSampleTransError(samfileName)
404//                      // TODO
405//                      // -- this criteria is rather crude. think it through better
406//                      // -- or should I simply let it overwrite? What is the harm in that?
407//                      if(trans != 0 && trans < 1 && trans_err != 0)
408//                              Printf "Sample transmission, error = %g +/- %g   already exists, nothing calculated\r",trans,trans_err
409//                              break
410//                      endif
411               
412        // for empty beam               
413                emptyCts = V_getBoxCounts(emptyFileName)
414                empty_ct_err = V_getBoxCountsError(emptyFileName)
415                WAVE xyBoxW = V_getBoxCoordinates(emptyFileName)
416                // TODO
417                // x- need to get the panel string for the sum.
418                // x- the detector string is currently hard-wired
419                detStr = V_getReduction_BoxPanel(emptyFileName)
420               
421                SVAR gEmptyPanel = root:Packages:NIST:VSANS:Globals:Transmission:gEmptyPanel
422                gEmptyPanel = detStr
423
424               
425                // check for box count + error values
426                // if present, proceed
427                // TODO
428                // -- this criteria is rather crude. think it through better
429                if(emptyCts > 1 && empty_ct_err != 0)
430                        Printf "Empty beam box counts, error = %g +/- %g   already exists, box counts not re-calculated\r",emptyCts,empty_ct_err
431                       
432                else
433                        // else the counts have not been determined
434                        // read in the data file
435                        V_LoadAndPlotRAW_wName(emptyFileName)
436                        // convert raw->SAM
437                        V_Raw_to_work("SAM")
438                        V_UpdateDisplayInformation("SAM")       
439                       
440                        // and determine box sum and error
441                        // store these locally
442                        emptyCts = V_SumCountsInBox(xyBoxW[0],xyBoxW[1],xyBoxW[2],xyBoxW[3],empty_ct_err,"SAM",detStr)
443       
444                        Print "empty counts = ",emptyCts
445                        Print "empty err/counts = ",empty_ct_err/emptyCts
446                       
447                        // TODO
448                        // write these back to the file
449                        // (write locally?)
450                       
451                endif
452
453        // for Sample Transmission File
454               
455                // check for box count + error values
456                samCts = V_getBoxCounts(TransFileName)
457                sam_ct_err = V_getBoxCountsError(TransFileName)
458                // if present, proceed
459                // TODO
460                // -- this criteria is rather crude. think it through better
461                if(samCts > 1 && sam_ct_err != 0)
462                        Printf "Sam Trans box counts, error = %g +/- %g   already exists, nothing calculated\r",samCts,sam_ct_err
463                       
464                else
465                        // else
466                        // read in the data file
467                        V_LoadAndPlotRAW_wName(TransFileName)
468                        // convert raw->SAM
469                        V_Raw_to_work("SAM")
470                        V_UpdateDisplayInformation("SAM")       
471                       
472                        // get the box coordinates
473                        // and determine box sum and error
474                       
475                        // store these locally
476                        samCts = V_SumCountsInBox(xyBoxW[0],xyBoxW[1],xyBoxW[2],xyBoxW[3],sam_ct_err,"SAM",detStr)
477       
478                        Print "sam counts = ",samCts
479                        Print "sam err/counts = ",sam_ct_err/samCts
480                       
481                        // TODO
482                        // write these back to the file
483                        // (write locally?)     
484                endif
485               
486        //then calculate the transmission
487                Variable empAttenFactor,emp_atten_err,samAttenFactor,sam_atten_err,attenRatio
488               
489                // get the attenuation factor for the empty beam
490                empAttenFactor = V_getAttenuator_transmission(emptyFileName)
491                emp_atten_err = V_getAttenuator_trans_err(emptyFileName)
492                // get the attenuation factor for the sample transmission
493                samAttenFactor = V_getAttenuator_transmission(TransFileName)
494                sam_atten_err = V_getAttenuator_trans_err(TransFileName)       
495                AttenRatio = empAttenFactor/samAttenFactor             
496                // calculate the transmission
497                // calculate the transmission error
498                trans = samCts/emptyCts * AttenRatio
499                                       
500                // squared, relative error
501                if(AttenRatio == 1)
502                        trans_err = (sam_ct_err/samCts)^2 + (empty_ct_err/emptyCts)^2           //same atten, att_err drops out
503                else
504                        trans_err = (sam_ct_err/samCts)^2 + (empty_ct_err/emptyCts)^2 + (sam_atten_err/samAttenFactor)^2 + (emp_atten_err/empAttenFactor)^2
505                endif
506                trans_err = sqrt(trans_err)
507                trans_err *= trans              // now, one std deviation
508               
509                //write out counts and transmission to history window, showing the attenuator ratio, if it is not unity
510                If(attenRatio==1)
511                        Printf "%s\t\tTrans Counts = %g\tTrans = %g +/- %g\r",SamFileName, samCts,trans,trans_err
512                else
513                        Printf "%s\t\tTrans Counts = %g\tTrans = %g +/- %g\tAttenuatorRatio = %g\r",SamFileName, samCts,trans,trans_err,attenRatio
514                endif
515               
516                // write both out to the sample *scattering* file on disk
517                V_writeSampleTransmission(SamFileName,trans)
518                V_writeSampleTransError(SamFileName,trans_err) 
519               
520                // (DONE)
521                // x- update the value displayed in the panel
522                // (NO) update the local value in the file catalog
523                // x- delete the file from RawVSANS to force a re-read?
524                NVAR gTrans = root:Packages:NIST:VSANS:Globals:Transmission:gTrans
525                gTrans = trans
526                NVAR gTransErr = root:Packages:NIST:VSANS:Globals:Transmission:gTransErr
527                gTransErr = trans_err
528
529                V_KillNamedDataFolder(V_RemoveDotExtension(samFileName))
530
531        // restore preferences on exit
532        gDoDIVCor = savDivPref
533        gDoSolidAngleCor = savSAPref
534
535        return(0)                       
536
537End
538
539
540
541
542
543
544
545Function V_WriteTransmButtonProc(ba) : ButtonControl
546        STRUCT WMButtonAction &ba
547
548        switch( ba.eventCode )
549                case 2: // mouse up
550                        // click code here
551                        break
552                case -1: // control being killed
553                        break
554        endswitch
555
556        return 0
557End
558
559Function V_HelpTransmButtonProc(ba) : ButtonControl
560        STRUCT WMButtonAction &ba
561
562        switch( ba.eventCode )
563                case 2: // mouse up
564                        // click code here
565                        DisplayHelpTopic/Z/K=1 "VSANS Data Reduction Documentation[VSANS Transmission]"
566                        if(V_flag !=0)
567                                DoAlert 0,"Transmission Help not written yet"
568                        endif
569                       
570                        break
571                case -1: // control being killed
572                        break
573        endswitch
574
575        return 0
576End
577
578Function V_DoneTransmButtonProc(ba) : ButtonControl
579        STRUCT WMButtonAction &ba
580
581        switch( ba.eventCode )
582                case 2: // mouse up
583                        // click code here
584                        DoWindow/K V_TransmissionPanel
585                        break
586                case -1: // control being killed
587                        break
588        endswitch
589
590        return 0
591End
592
Note: See TracBrowser for help on using the repository browser.