!pr1
Writing Messages in Windows...............Bob Sander-Cederlof

The idea for the following program came from some similar code in the Cirtech Flipster software.  Their "program manager" software displays a series of messages and menus in selected windows using a simple subroutine.

The windows are not quite as sophisticated as you may be used to if you are a Macintosh fan.  This program divides the screen up vertically, with each window running the full screen width.  Calls to the program specify which window to write a message into.  The JSR MSG.IN.WINDOW is followed by a single byte specifying which window to use, the ASCII text of the message, and a final 00 byte signifying the end of message.  MSG.IN.WINDOW first sets up the window, then clears it, then displays the message in it, and then returns to continue execution right after the 00 byte.  MSG.IN.WINDOW does not make any provision for saving the previous contents of the screen inside the window and restoring it later.  As I said, this is much simpler than Mac windows.

The Apple monitor has built-in window capability, with the current window being defined by four bytes in page zero.  $20 is called LEFT, and defines the starting column of a screen line.  This is normally 0, meaning the first column.  $21 is called WIDTH, and specifies how many characters are in each line.  This is usually 40 ($28), but may be 80 ($50) in a //c or enhanced //e in 80-column mode.  MSG.IN.WINDOW does not make any changes to LEFT or WIDTH, although you could modify it to do so.

$22 is called WNDTOP, and specifies the top line of the working window.  This is usually 0, meaning to start at the top of the screen.  It could be as large as 23 ($17), meaning the bottom line of the screen.  $23 is called WNDBOT, and specifies the bottom line of the working window.  The number in WNDBOT is actually the number of the next line below the working window, and is usually 24 ($18) to specify a window that goes all the way to the bottom of the screen.  MSG.IN.WINDOW stores new values in WNDTOP and WNDBOT, according to a table of line numbers called WINDOW.DATA.

My WINDOW.DATA table lists six different windows, but of course you could have as many as you wish.  They can even overlap.  The table I used contains the line numbers 0, 24, 0, 3, 9, 18, 20, and 24.  This corresponds to the following windows:

     Index     WNDTOP WNDBOT Window
       0          0     24    0-23  <full screen>
       1       <better not use!!!>
       2          0      3    0-2
       3          3      9    3-8
       4          9     18    9-17
       5         18     20   18-19
       6         20     24   20-23

Lines 1080-1130 in the listing below detail the calling sequence for MSG.IN.WINDOW.  The test program in lines 1500 and following shows some actual calls, with a "wait for any keystroke" between messages so you can see it happen.

Lines 1140-1180 save the caller's return address, placed on the stack by the JSR MSG.IN.WINDOW.  This address will be used to pick up the calling parameters, and then used to return to the calling program.  The subroutine in lines 1400-1460 increments the pointer and picks up the next byte from the calling sequence.

When we are finished displaying the message, the pointer will be pointing at the terminal 00 byte.  Placing the pointer address back on the stack lets us use an RTS opcode to return to the caller.  This is done in lines 1340-1390.

Lines 1200-1250 pick up the window index from the first byte following the JSR instruction.  This indexes the WINDOW.DATA table, so two entries from that table are moved into WNDTOP and WNDBOT.  The the monitor HOME subroutine can be called to clear the window and place the cursor in the top-left corner of the window.

Lines 1270-1330 display the message, if any.  If there is no message, there still must be a terminal 00 byte.  By judicious use of 8D (return) and 8A (linefeed) characters, you can display the message any way you like.  If the message is too large for the window, lines will be scrolled out the top of the window and lost.

The MSG.IN.WINDOW subroutine illustrates a commonly used technique of placing messages to be printed "in-line", like PRINT "message" statements in Applesoft.  I personally prefer to collect all my messages together, and use a message number in a register to select which one to print.  One problem with my preferred method is that my programs are then easier to disassemble ... if that is a problem.  The 6502 was not designed for easy transfer of calling parameters which follow the JSR.  (The 65816 makes this kind of code easier, with its stack-relative address mode.)

