|
|
SAMPLE CODE
ATTACHTABLE_SUB( volumeName, tableList, options ) /* attaches a list of tables */ options = "A" /* Announce option */ call ATTACHTABLE_SUB(volume, tablelist, options ) declare subroutine buildindex_sub, fsmsg tablename = "PEOPLE_10000" fieldinfo<2, 1> = "ADDRESS" fieldinfo<3, 1> = "CITY" buildindex_sub(tablename, datahandle, indexhandle, fieldinfo, 0)
Figure 2. An example of a program that builds the index information array from information in the dictionary entry for the indexed column. declare subroutine msg, fsmsg /* open index */ open "DICT." : tableName to @dict else /* read entry from dictionary, then assemble necessary information for case indexType = "C"
/* fill in the rest of the index_info array using data from the indexInfo< 1 > = indexName /* name of column &*/ if dictEntry<1> = "F" then indexInfo< 7 > = Not( dictEntry< 26 > ) /* case-sensitive flag */ gosub getSortDirection if dictEntry< 4 > = "M" then /* multivalue flag */ convert @fm to @vm in indexInfo status = status() if @file.error then text = "Are you sure you want to quit? [Y/N]" declare function getconfigure The NewList row is a list of new tables and rows
to create in the new application. By default, the NEWAPPLICATIONLIST row in
SYSENV is used. Each field in the list contains the name of the table to create.
The first value in the field is the table name. Dictionaries must be explicitly
given. The second and subsequent values are rows to create in the new table. The
wildcard "*" is used to indicate that all rows from the currently
attached table of the same name should be copied. INDEX.REBUILD.SUB SUBROUTINE INDEX.REBUILD.SUB(FILE_NAME,INDEX) DECLARE SUBROUTINE DELAY $INSERT SYSINCLUDE CONFIGURE.RECORD.EQUS BTREE_FLAG = XLATE("DICT.":FILE_NAME, INDEX, 6, "X") VOLUME_NAME = XLATE("FILES", FILE_NAME, 1, "X") TOKEN = '' * place rebuild token at the end of the 0 record
REBUILDINDEX_SUB (parms)
The Function of WC_RESET% in Window Processing (TB#81) The Function of WC_RESET% in Window ProcessingA hurdle for programmers new to the Advanced Revelation window processor is trying to decide which WINDOW_COMMON% variables to use in which circumstances, particularly, the variable WC_RESET%. It can take one of 6 values and which value it takes depends on where it is used. Furthermore, other variables, for example WC_DISPLAY_ACTION%, seem to need WC_RESET% in some places and not others. This Technical Bulletin explains how the window processor uses WC_RESET% to affect window processing. To understand WC_RESET% you must first understand that the window processor is basically a loop. The window starts, then the first prompt is processed. The second prompt is processed and then the third and so on until all prompts have been processed. In fact, Window consists of loops within loops. The Basic LOOP...UNTIL R/BASIC supports several looping structures. FOR...NEXT is one, LOOP...UNTIL...REPEAT is another. LOOP...UNTIL is the structure used by Window. The syntax of LOOP...UNTIL is: LOOP UNTIL condition is met REPEAT This syntax is very flexible. Additional processing statements can be placed anywhere inside the LOOP...REPEAT block. For example: LOOP do some processing do more processing UNTIL condition is met keep on working don't stop REPEAT In this example the entire loop keeps on looping until some condition is realized. When that condition is realized control jumps straight to the REPEAT statement, skipping everything between the UNTIL and the REPEAT. Using this knowledge, a basic window loop might look like: LOOP process prompt UNTIL reset do between prompt work REPEAT Advanced LOOP...UNTIL LOOP...UNTIL permits multiple exit points. For example: LOOP do work UNTIL condition is met do more work UNTIL another condition is met do still more work REPEAT This feature helps the window loop exit more gracefully. Notice that in the basic window loop above that if the between prompt work indicates that the window should quit, one more prompt must be processed before exiting the loop. If you change the loop structure you can avoid the extra processing. LOOP process prompt UNTIL reset do between prompt work UNTIL reset REPEAT Now there are two ways out of the loop. In fact you are not limited to just two exit points. You can have as many as you want. Hypothetical Window Loop The loop for a hypothetical window processor might look like this: LOOP process prompt UNTIL reset if perpetual process do perpetual process end UNTIL reset if save flag set then do save process end UNTIL reset if delete flag set do delete process end UNTIL reset if display then do display process end REPEAT The loop quits anytime reset is true. This loop allows multiple processes the opportunity to set reset. Reset is being used as a flag to indicate that a process (the window) should stop. How can the same feature be used to stop another process? Take, for example, the save process. Resetting a Save Process The save process (in the hypothetical window loop) should allow for a presave process. If the user wants to avoid the save they should set reset. One way to implement this is like this: save process: if presave process then do presave process if reset else do save end end else do save end This is cumbersome for two reasons. First, the actual save routine is duplicated. Second, if the save is cancelled so is the window because reset is never set back to false. What you need is a way to indicate that the save process should be cancelled, but not the window. You also need a way to indicate that both the save process and the window should be cancelled. A simple approach would be to say, "1 means cancel the save, 2 means cancel the save and the window". This approach is too simple and it makes extension of the use of reset difficult. It makes all of the checks in the main loop look for a particular value. It also does not help the save process avoid duplicating code. If you change the way you use the code it gets easier. For example: save process: if presave process then do presave process end if reset then if reset <= 1 then reset = "" end else reset -= 1 end end else do save end This approach uses the same value for reset as originally outlined, but makes it easier to write clean code. The presave process is completely encapsulated inside one IF...THEN block and the save code is not duplicated. Walking through the if reset section will show that the reset values produce the required results: _ If reset is non-null (true) the then branch is taken. Otherwise the else branch is taken. It is only in the else branch that the save code is executed, so setting reset to 1 or 2 will prevent the save, which is what was intended. _ In the then branch the value of reset is checked. If it is less than or equal to 1 reset is set to null. This means that when control returns to the main loop reset is not true and the window is not cancelled. If, on the other hand, reset is greater than 1, (in this case 2) subtract 1 from reset. When control returns to the main loop reset is true and the window is cancelled. Prompt Processing Prompt processing, unlike the save process examined above, is itself a loop. In the hypothetical window it would be desirable to have the same editor used in all conditions and to have some fancy features like popups and softkeys. All of this can be done by using a loop. The simple solution is to call an editor until the editor is done and then pass control back to the main loop. For example: LOOP call editor UNTIL done REPEAT This structure is both too complex and too simple. It assumes that the editor will handle all the desired features (like popups and softkeys). If that is the case then the editor should be called for the prompt and no loop is needed for when it returns control the prompt has been processed and the main loop can continue. This is not a bad strategy if you don't mind burdening the editor with window specific functions. However, you might want to use the editor outside the window as well. A better strategy would be to define special keystrokes that the editor would recognize mean "give control back to the window processor". The window processor could then examine which key was pressed and act accordingly. With this strategy the prompt loop might look like this: LOOP editor(exitkeys, lastkey) process lastkey UNTIL reset REPEAT In this loop the process lastkey routine is like the save process above it can set reset. But this loop has the same failing as the original save process, if reset is set, the window is cancelled. There is also no preprompt processing. A better prompt processing loop looks like: process prompt: if preprompt then perform preprompt if reset then if reset <= reset_edit$ then reset = "" end else reset -= 1 end end end if reset else loop editor(exitkeys, lastkey) process lastkey until reset repeat if reset <= reset_edit$ then reset = "" end else reset -= 1 end end Notice how the same strategy is used here to deal with the reset codes as was used in the save process. Summary Refer to the original window loop, above. Note that the display action is evaluated at a specific point in the loop (the actual point is somewhat different in the real Window). In order to get the display action evaluated you must get to that point. If a prompt is being processed how do you get there? You must set reset to a value high enough to get control out of the prompt processing loop. To set reset you need to invoke a special keystroke. Maybe [F2] or a softkey; any keystroke that the editor recognizes as significant so it returns control to the window processor. If your program doesn't set reset high enough the edit loop is not exited. Note that there is no need to set reset if control is passing out of the prompt normally. Window How does this hypothetical window processor compare to Window? Figure 1 is pseudo code that shows the flow of the main window loop, emphasizing the role of WC_RESET%. Figure 2 is the pseudo code for I/O processing, while Figure 3 shows prompt processing. WC_RESET% can take the values in the following table. Use these values as you trace through the pseudo code. Value Mnemonic 1 CLEAN.UP.LINE$ 2 CLEAN.UP.EDIT$ 3 RESET.EDIT$ 4 RESET.PROMPT$ 5 RESET.RECORD$ 6 RESET.WINDOW$ Window Flow As Figure 1 shows, if WC_RESET% is still set after the prompt is processed the perpetual process is not executed. Since most windows do not have a perpetual process there is usually no practical difference between setting WC_RESET% to RESET.PROMPT$ or setting it to RESET.RECORD$ from a prompt process. Notice that after every possible "hook" the system checks for WC_RESET%. This means that setting WC_RESET% to RESET.WINDOW$ from any process will quickly cancel the window. The window processor also checks for WC_DISPLAY_ACTION% after all hooks, making it easy for you to affect window display. I/O Processing Figure 2 shows the basic flow followed by read, write, and delete processing. Note that all WC_RESET% values less than RESET.RECORD$ have the same effect on window flow. To have an impact on window flow from an I/O process you must use RESET.RECORD$ or, to leave your window, RESET.WINDOW$. Prompt Flow Figure 3 shows the flow of control through a prompt. Careful study of the pseudo code will show that from a preprompt process you must set WC_RESET% to at least RESET.PROMPT$ to force the system to leave the prompt. From the Options key or from Softkeys you must set WC_RESET% to at least RESET.EDIT$ to force the system to leave the prompt. Note that if you set WC_RESET% to CLEAN.UP.LINE$ or CLEAN.UP.EDIT$ you do not leave the prompt. CLEAN.UP.LINE$ and CLEAN.UP.EDIT$ are used by the window processor to ensure that edit checks are done. Using these values in your programs will have no effect. Edit Checks As you can see in Figure 3, one of the parameters passed to SCRIBE is the edit patterns used by the prompt (WC_SI%<VINP>). SCRIBE will, in turn, call IN.VALUE to validate your input. This processing is important in two ways. First, it explains why your custom edit checks will find the input data in @ANS. SCRIBE and IN.VALUE are independent routines. They are not window specific and cannot use the window common variables. In order to pass data to your routine, @ANS, and not WC_IS% must be used. Second, because SCRIBE can be interrupted before the edit checks have been done, there must be a way to call SCRIBE and tell it to process the data through the edit checks. This is the function of CLEAN.UP.LINE$ and CLEAN.UP.EDIT$. Depending on when processing was interrupted and whether there are edit checks, the system will use WC_RESET% to set flags in WC_SCRIBE_FLAGS%. These flags will be used by SCRIBE when it is called again to determine what action to take. Figure 1 LOOP process prompt IF WC_RESET% THEN WC_RESET% -= 1 END ELSE do perpetual process END UNTIL WC_RESET% IF WC_AMV_ACTION% THEN do amv process IF WC_JOINED_KEYS% THEN do join process IF WC_DISPLAY_ACTION% THEN do display process IF WC_SAVE_REC% THEN do save process IF WC_DISPLAY_ACTION% THEN do display process END UNTIL WC_RESET% IF WC_DELETE_REC% THEN do delete process IF WC_DISPLAY_ACTION% THEN do display process END UNTIL WC_RESET% IF WC_MV_NEXT% THEN adjust position in amv IF WC_NEW_DATAFILE% THEN do new datafile process IF WC_NEW_BROWSE% THEN do new browse list process IF WC_RING_NEXT% THEN adjust browse list pointer IF WC_NEW_ID% THEN do read process IF WC_DISPLAY_ACTION% THEN do display process END UNTIL WC_RESET% IF WC_WI_NEXT% THEN adjust prompt cursor is on IF WC_WINDOW_ACTION% THEN pan/resize/move REPEAT Figure 2 IF preprocess THEN do preprocess IF WC_RESET% <= RESET.PROMPT$ THEN WC_RESET% = "" END ELSE WC_RESET% -= RESET.PROMPT$ END END IF WC_RESET% THEN WC_RESET% -= 1 END ELSE IF replace process THEN do replace process IF WC_RESET% <= RESET.PROMPT$ THEN WC_RESET% = "" END ELSE WC_RESET -= RESET.PROMPT$ END END ELSE do i/o END IF WC_RESET% THEN WC_RESET% -= 1 END ELSE IF postprocess THEN do postprocess IF WC_RESET% <= RESET.PROMPT$ THEN WC_RESET% = "" END ELSE WC_RESET% -= RESET.PROMPT$ END END IF WC_RESET% THEN WC_RESET -= 1 END ELSE do work END END END Figure 3 prompt: IF WC_SI%<PRE.CODE> THEN do preprompt process IF WC_RESET% <= RESET.EDIT$ THEN WC_RESET% = "" END ELSE WC_RESET% -= 1 END END IF WC_RESET% ELSE LOOP WC_VALID% = TRUE$ LOOP LOOP SCRIBE(WC_IS%, WC_WEXIT_KEYS%, WC_WC%, WC_SI%<VINP>........) UNTIL WC_RESET% ;* clean.up.line$ WHILE WC_WC% IF WC_DISPLAY_ACTION% THEN do display action END check wc_wc% ;* process popups, softkeys etc UNTIL WC_RESET% ;* clean.up.line$ REPEAT IF WC_WC% THEN IF WC_RESET% THEN WC_RESET% -= 1 IF WC_RESET% > 1 THEN WC_RESET% -= 1 END ELSE adjust scribe state so edit check gets done END END END ELSE WC_RESET% = 1 END UNTIL WC_RESET% ;* clean.up.edit$ REPEAT WC_RESET% -= 1 UNTIL WC_RESET% ;* reset.prompt$ IF WC_SI%<POST.CODE> THEN do postprompt process IF WC_RESET% <= RESET.EDIT$ THEN WC_RESET% = "" END ELSE WC_RESET% -= RESET.EDIT$ END END UNTIL WC_VALID% UNTIL WC_RESET% REPEAT END IF WC_RESET% THEN WC_RESET% -= 1 WC_IS% = WC_IS_ORIG% END RETURN |
Revelation
, Advanced Revelation , AREV and Open
Insight are trademarks of Revelation
Technologies, Inc. All other products mentioned are registered
trademarks or trademarks of their respective companies.
|