With the ATASCII to Internal code routines converted from my Action! library and now working, as well as the libraries wait functions, I was able to start on the windowing library routines. The only larger part of the library are the window gadgets which I’ll get to in future posts.
First I converted the WInit() function which clears all the memory for the window system, and sets all the handle information to its defaults, setups of the screen by clearing it, and setting the left margin to 0.
I then started converting WBack() which sets the background display character. It uses memset to accomplish this so it is very quick. With that working, I then did the basic WOpen() function which simply saves and clears the area of the screen the window will occupy, via memcpy and memset, and then draws the window frame. I then completed the WClose() routine which restores the contents of the screen the window covered, again via memcpy. The use of memcpy and memset makes the routines very fast, even with calling StrAI() routines to get the display to internal code first.
Once the window open and close was working, I moved to implement WPos() and WPut(). WPos() moves the window system virtual cursor to a coordinate within the given window, or it can be used to position the physical cursor to an absolute position (same as CC65 gotoxy() function). The WPut() function allows you to place a single character in a given window.
Next I completed the WPrint() routine, which is used to print text into a given window. During this conversion, I changed the call slightly from Action!’s. I did it to make it a little more flexible in regards to displaying inverse text and coding in CC65 on the Mac which doesn’t allow entry of ATASCII characters into the source code.
With WPrint() complete, I moved to WOrn() which allows the placement of ornaments onto the top and bottom window frames in either the left, right, or center positions.
Next I converted the WStatus() function which returns if a window handle is in use or not. I then built a loop into the test program to display the status of each window handle.
With all that working I converted the WClr() function from my Action! library. This function clears the contents of the window (inside the frame). I then put some wait for key pauses in the test/demo program to validate everything worked as expected.
Here is the source code for the test/demo program. As in the last post, the use of byte is present, which represents an unsigned char. unsigned char’s should be used in loops where possible with CC65 because their access is quicker, making the loops execution time faster. There is a full explanation on the CC65 website:
// ------------------------------------------------------------
// Program: testwin.c
// Desc...: A8 Library Windows Test
// Author.: Ripdubski
// Date...: 202208
// Notes..: cl65 -v [-O] -t atarixl testwin.c -o testwin.xex
// ------------------------------------------------------------
// Pull in include files
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <atari.h>
// The next 4 are part of the converted Action! library.
#include "a8defines.h"
#include "a8defwin.h"
#include "a8libstr.c"
#include "a8libwin.c"
// ------------------------------------------------------------
// Func...: void main(void)
// Desc...: Main routine
// ------------------------------------------------------------
void main(void)
{
// Variables
byte bW1, bW2, bL;
unsigned char cL[40];
// Initialize window system, and setup screen
WInit();
WBack(14);
// Open title window
bW1 = WOpen(0, 0, 40, 3, WON);
WPrint(bW1, WPCNT, 1, WOFF, "CC65 Window Test");
// Open status window, display ornaments, and divider
bW2 = WOpen(4, 6, 32, 14, WOFF);
WOrn(bW2, WPTOP, WPLFT, "TL");
WOrn(bW2, WPTOP, WPRGT, "TR");
WOrn(bW2, WPTOP, WPCNT, "Status");
WOrn(bW2, WPBOT, WPLFT, "BL");
WOrn(bW2, WPBOT, WPRGT, "BR");
WDiv(bW2, 11, WON);
WPrint(bW2, WPCNT, 12, WOFF, "Divided Window");
// Use WPOS and WPUT in both inverse and regular windows
WPos(bW1, 38, 1);
WPut(bW1, 49); // 1
WPos(bW2, 30, 1);
WPut(bW2, 50); // 2
// Get and display status of each window handle
for (bL=0; bL < 10; bL++)
{
// Get window status
// Create formatted display string in char array
if (WStat(bL) == WON)
{
sprintf(cL, "Window %d = In Use", bL);
}
else
{
sprintf(cL, "Window %d = Not Used", bL);
}
// Print the string to the window
WPrint(bW2, 1, bL+1, WOFF, cL);
}
// Wait for a keypress (just used conio function)
cgetc();
// Turn off divider
WDiv(bW2, 11, WOFF);
// Wait for a keypress
cgetc();
// Clear window
WClr(bW2);
// Wait for a keypress
while (! kbhit()) { };
// Close windows
WClose(bW2);
WClose(bW1);
// Exit
return;
}
Screenshot of all the window functions being used:

Breakdown of what is being shown:
The background is painted with a period character using WBack() function.
The title window at the top is flagged to be opened in inverse with the WOpen() call.
The text “CC65 Window Test” is printed on the 1st row of the window with the CENTER flag enabled in the call to WPrint().
The status window is opened as the second window. The WOrn() function is used to set the “Status” title ornament in the center on the top of the frame.
The “TL” ornament is displayed on the frame using the WOrn() function called with TOP and LEFT.
The “TR” ornament is displayed on the frame using the WOrn() function called with TOP and RIGHT.
The “BL” ornament is displayed on the frame using the WOrn() function called with BOTTOM and LEFT.
The “BR” ornament is displayed on the frame using the WOrn() function called with BOTTOM and RIGHT.
The lower window divider is created using the WDiv() function.
The “Divided Window” test is printed on the last row of the window with the CENTER flag enabled in the call to WPrint().
The “1” and the “2” in the upper right corners of each window are displayed using the WPut() function.
Each text line (“Window x = <status>”) is displayed using WPrint().