The Function of WC_RESET% in Window Processing (TB#81) (Functions/Subroutines/Programs)

The Function of WC_RESET% in Window Processing

A 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

  • kb/kb_articles/kb0048.txt
  • Last modified: 2024/01/30 13:36
  • by 127.0.0.1