IF (NOT TWA-SWAP-LOWLEVEL)   do the attach logic .     3.  *== Cancel the current Dialog programatically if required   IF (TWA-SWAP-DIALOG-A)   MOVE A TO TWA-SWAP-ID   ELSE   MOVE X TO TWA-SWAP-ID     4.  *== This must be done in %PREINIT    *== Check for attach and utilize data passed in SERRMSG   IF (TWA-MSK-ATT-REQ)   IF (TWA-SCOMPL-ATTDET = 'ATT' ) AND   (TWA-SCOMPL-FUNCT is a valid function )   MOVE SERRMSG TO your-SERRMSG-work-area   continue as appropiate for attach   ELSE   take action for invalid attach .     5. *== This must be done in %PREINIT   *== Check for detach and utilize data passed in SERRMSG   IF (TWA-MSK-DET-REQ)   IF ( TWA-SCOMPL-ATTDET = 'DET' ) AND   ( TWA-SCOMPL-FUNCT is a valid function )   MOVE SERRMSG TO your-SERRMSG-work-area   move various SERRMSG data to screen fields   GO TO AA800-SEND-SCREEN   ELSE   take action for invalid detach .   The above examples show the various things that can be done by interrogating the current status of the session. The (cont.) third example shows how a program can push itself to the top of the attach list. Note that this also occurs (cont.) automatically any time the terminal user causes the MAGEC clear screen to be invoked, or when a MAGEC menu function is (cont.) used. The application users can escape a dialog at any time they desire. Logging on (via the SYSLOG function) also (cont.) results in the session being established at the "top" of the attach dialog (clearing the stack). Additionally, if the (cont.) application does not make the check to see if it has been attached, and then subsequently issues an invalid Detach (cont.) request, an error code is displayed. Attempting to attach another function when you are already at the lowest level (cont.) results in a pop-up window offering the operator four options for handling the situation. 1) push the oldest screen off (cont.) the stack, 2) clear the stack, 3) transfer the screen without adding the current screen to the stack (using a (cont.) FTH-FUNCT, instead of an Attach), 4) return to the original screen. # Appendix S -- Multi-Screen Applications ## Screen Sequences A common (false) impression that many developers get when first introduced to MAGEC is that it does a great job of (cont.) developing single-screen transactions; but doesn't seem to handle applications which involve multiple screens. An (cont.) example of such a multi-screen application would occur when the data to be added/updated is more than can be placed on (cont.) one screen. In this example it is necessary to create multiple screens to capture or present all the data before any (cont.) I/O request to update the file(s) or table(s) is issued. Actually, multi-screen processing is quite simple with MAGEC. In fact, the entire application development process which (cont.) was used throughout these turorials is merely a collection of MAGEC-generated applications which link to one another. (cont.) We might recall the initial phases of the development process (refer to the "Application Developer" chapter of this (cont.) *Tutorial* manual) wherein we were automatically transferred from one panel to the next in order to capture the complex (cont.) set of specifications needed to create our screen and application. The entire process consists of MAGEC-generated, (cont.) Cobol applications programs, not much different from ones any programmer using MAGEC might have produced. They use the (cont.) same standard facilities which are available to all MAGEC-generated programs. For the purposes of our discussion, let us assume that we need to develop an application which accomplishes the (cont.) standard functions to maintain a file which has records which contain more data than will fit on one screen. For (cont.) simplicity, we will assume that two screens will suffice; though there is really no limit on the number of screens (cont.) possible. ## Two Approaches There are basically two philosophies which can be applied to solve this problem. First, we could build a multi-screen (cont.) application which captures all the needed data, edits it all, then adds/updates it to the database. Second, we could (cont.) build an application which contains a "first" screen which captures some of the data, edits it, and adds/updates the (cont.) database with what it has, then links to a "second" screen which captures the remainder of the data, edits it, and (cont.) updates the database with that data. The advantage of the first approach is that no incomplete data ever reaches the database. All fields are fully edited (cont.) and validated, both individually and in context with one another, before any of the data is accepted and (cont.) recorded. The advantage of the second approach is that, in the event of an interruption, the sequence can be resumed at the point (cont.) where it was left off. Examples of interruptions would be: power failure, operator error which exits the sequence, (cont.) software abend, etc. With the first half of the data safely recorded to the database, it is a relatively simple matter (cont.) to restart from that point forward. The only data which will be lost is that which was typed onto the screen but not (cont.) yet updated to the database. The disadvantage of this second approach is that it adds the responsibility of writing an audit program which searches (cont.) for and reports any incomplete data on the database. This disadvantage is not nearly as great as it might sound, (cont.) however, since any thorough design for an online system which manages important data will include a database audit (cont.) program, anyhow. It should be recognized that no amount of diligence in any online system can prevent every possible (cont.) database integrity error condition from occurring. Physical disk errors, human errors while using offline utility (cont.) programs (backups, restores, reorganizations, etc.), software bugs (perhaps in system software), and many other types (cont.) of problems can, and do, still occur. It might be helpful to know the error codes you may encounter. Refer to the (cont.) ["Abend Codes"](/DOC/magref_main.htm#MAGREF009002) reference table for a full list of abend code issued from (cont.) MAGEC. ## First Approach To implement the first approach is not very complicated at all. First we would create two applications, one to process (cont.) the first half of the data, one to process the second half. Each would have its own screen Mask and its own MMP. Each (cont.) would also have its own full set of function codes. The function codes must be unique, therefore we would specify a (cont.) different function code prefix on the Screen Header for each of these two applications, even though both would have the (cont.) same primary Data Class. If we assume that the file we are accessing/maintaining is a customer file with a Data Class ID of CUS, we might (cont.) specify the function code prefix of CUS for the first application and a function code prefix of CS2 for the second. (cont.) Both would specify CUS as their primary Data Class. They would also both have the same list of Elements from that Data (cont.) Class, even though each might only need a portion of the complete set of customer data. In the first MMP we would wish to customize the logic so that it: 1. does not update the database 2. fetches to the second MMP, passing all the data captured and edited 3. lets the second MMP know that we are coming from the first MMP, with data passed To do this is quite simple. There are insertion points provided to allow developers to override the default database (cont.) update, or add processing. What we wish to do is to override them with a fetch to the second MMP, with the appropriate (cont.) function code set. For example, if we were adding customer data in the first screen (function code CUSADD), we would (cont.) want to fetch to the second MMP with a function code of CS2ADD. If we were updating in the first MMP (function code (cont.) CUSCHG), we would want to fetch to the second with a function code of CS2CHG, and so forth. The two insertion points involved are: %ADDIT add a record %UPDAT update a record The code you could provide into each of these insertion points to accomplish all of the above objectives might be: MOVE 'CS2' TO TEST-FUNCT-KEY.   MOVE TEST-FUNCT TO SFUNCT.   MOVE FTH-FUNCT TO TWA-NONTP-REQUEST.   GO TO AA900-GOBACK.   TEST-FUNCT-KEY is the first three bytes of TEST-FUNCT, which contains the same value as SFUNCT. By setting the first (cont.) three characters to CS2, leaving the last three characters alone, we have built the appropriate function code to fetch (cont.) to. The remainder of the above code is the standard FTH-FUNCT logic (refer to "Appendix B in this (cont.) chapter). Notice that is was not necessary to do anything at all to pass data to the fetched MMP. MAGEC automatically passes the (cont.) entire TWA. All the data which was captured from the first screen has already been moved into the appropriate record (cont.) fields in the Element copybook(s) in the TWA. Upon entry of the second MMP, the entire TWA will contain all the data (cont.) placed in it by the first MMP. *Since the programs have the same list of primary Elements, their TWA-DB-DATA areas are (cont.) defined the same.* It should be noted that the standard logic on an ADD function includes initializing the Element copybook areas to (cont.) spaces before moving data from the screen to the Element copybook fields. This means that any unreferenced fields will (cont.) have a predictable value, spaces. If another value is desired, the developer should provide customization for the (cont.) insertion point %ADDINIT. The second MMP will need to know that it is being entered from the first. It is not unusual in these situations for the (cont.) developer to specify that it is illegal to access the second MMP without having come from the first. To ensure this, (cont.) the developer could add customization into the %PREINIT insertion point, as follows. MOVE SFUNCT TO TEST-FUNCT   MOVE SKEY TO TEST-KEY     IF (TWA-LAST-KEY NOT = TEST-KEY)   OR (TEST-FUNCT-KEY NOT = 'CUS' AND 'CS2')   MOVE 'CUS' TO TEST-FUNCT-KEY   MOVE TEST-FUNCT TO SFUNCT   MOVE FTH-FUNCT TO TWA-NONTP-REQUEST   GO TO AA900-GOBACK.   The above code will ensure that we have come from the first screen, and for the same key value. If not, it will fetch (cont.) back to the first screen to try to initiate the sequence at the beginning, on the assumption that that is what the (cont.) operator should have done (meant to do) anyhow. The second MMP will also need to refrain from re-reading (or trying to read) the record being processed. This is (cont.) because the first MMP has already read it and the entire record (or, at least, all the Elements we are interested in) (cont.) are already in TWA-DB-DATA; reading on top of them is both unnecessary and destructive. To suppress those reads we (cont.) might simply comment out the perform of the I/O call in the insertion points: %REDKY and %RDUKY, as: ****PERFORM AA840-CALL-MAGECIO THRU AA899-EXIT   We also must prevent the default %ADDINIT logic in the second MMP from trying to initialize the Element copybook (cont.) fields. To do this we would simply add customization into the %ADDINIT insertion point commenting out the MOVE (cont.) SPACES... code. The second MMP will follow its natural flow and, if all edits are passed, add or update the database record with all the data from the first and second screens. ## Second Approach In the second approach we allow the standard logic of the first MMP to do its normal update or add, then we have it (cont.) fetch to the second MMP. Since, on an ADD function, the record will be added in the first MMP, we will transfer to the (cont.) second using a CHG function whether we were doing an ADD or a CHG in the first MMP. Because we will be adding an incomplete set of data to the database in the first MMP, we should be careful to set (cont.) appropriate default values into all the fields of the Element copybook(s) being updated. That means that we might need (cont.) to put some customization code into the %ADDINIT insertion point. The customization would move default values to those (cont.) fields not updated/added from the first MMP. Some developers will choose to set default values which identify this (cont.) record as "incomplete" in order to facilitate auditing the database and/or restarting the multi-screen transaction from (cont.) the point it was aborted. The first MMP should fetch to the second from the %GOODADD and %GOODCHG insertion points. These insertion points occur (cont.) after a successful add or update, respectively. The coding to fetch to the second MMP would be: MOVE 'CS2CHG' TO SFUNCT.   Next: https://magec.com/DOC/markdown/cstm18.md.txt