The Design and Implementation of VIOWIN - Part 1

The Fullscreen PM Subset
Written by Larry Salomon Jr.

Introduction
For my job, I once had to write an application that ran only when OS/2 booted from the floppy diskettes. Because I had no access to the functionality PM provides, I resorted to a line-oriented interface, where messages were displayed on the screen and scrolled up when necessary. It was a good interface, I thought; it was fully NLS enabled and had intelligent defaults so the user basically only had to type in the name of the application. Unfortunately, the Quality Assurance team didn't concur with my opinion. "We want a nice interface!" one exclaimed. "Yeah, one with different windows and such!" another shouted.

I was backed into a corner that I could only get out of one way.

This series will describe the design and implementation of VIOWIN, a library that implements a subset of the Win APIs provided by PM for full-screen sessions. The reasoning behind writing this series is that it provided me and will hopefully provide you with some unique insights into how a windowing system is developed; and since it is based on PM, your familiarity with the already defined interface will increase your capability to fully understand what is being described.

Obviously, this series assumes you have PM application development experience, but it isn't required.

Forethought
Before I could begin coding, I had to decide where to draw the line. I couldn't reasonably expect to implement the entire API set, but I didn't want to limit the capabilities of the library unnecessarily. I must apologize because I did not take any notes when developing this, so the "list" of limitations is probably incomplete. Most of the limitations were chosen to save time coding the library; after all, I did have an application to write using this library and only two weeks total to complete all of it!

The design points are listed below. First are the "have not's": ...followed by the "have's": For the window classes, not all styles were implemented (e.g. text fields and group boxes were written, but not rectangles or bitmaps), nor were all messages in each class implemented.
 * 1) No multiprocess or multithread application support.
 * 2) No overlapping window support.
 * 3) No movable window support.
 * 4) No mouse support.
 * 5) No profile support.
 * 6) No class styles.
 * 1) At least 3 implemented window classes - buttons, entry fields, and statics.
 * 2) Input focus support.
 * 3) Timer support.
 * 4) Cursor support.
 * 5) Limited resource support.
 * 6) Window styles.

Cursor support is limited, due to the nature of the system. Since we are running in a character-mode full screen session, we cannot have dotted boxes around the text of a button, for example.

The only resource support that made it into the current version is for the STRINGTABLE. I would have liked to have added ACCELTABLE and DIALOGTEMPLATE support, but didn't have the time to do it.

Additionally, I wanted to have as much similarity to the Win APIs as I could possibly design and code. Thus, there is an anchor block and message queue (although they are hidden), message loops, window procedures, etc. The advantages here are that
 * 1) I didn't have to spend additional time designing the paradigm on which my design would be based and
 * 2) users of the library would already be familiar with the ideas, providing they had PM application development experience.

There are also some things not mentioned above that were included. I avoided the issue of output completely by choosing to leave out the Gpi APIs (for obvious reasons), but the static control, for example, had to be able to write its text out. Thus, the vwDrawText function was added. Also, for the limited clipping provided in functions such as vwDrawText, rectangle support was added. Also, certain system values were added, as well as the vwQuerySysValue and vwSetSysValue functions, and vwAlarm was needed for audible feedback.

The base library consists of the files listed below, followed by a list of the files comprising the window classes, which were kept separate to encourage good programming. It should be noted here that exploitation of the Common/2 library was used whenever possible (especially for the linked-list routines). If you are not familiar with this library, it is recommended that you get the latest version (currently 1.6.0) from ftp.cdrom.com.

Throughout this series, I will describe each module in depth along with any notes that pop into my head. I realize that this will detract from the readability of the articles, but - again - I did not originally intend for this series to even exist or for the library to grow to what it has become.

Data Structures
This month, we will only look at the four predominant data structures involved. Additional data structures will be discussed as the code involving them is described. Next month, we will delve into the code proper, and the code will be provided with the next article so that you can do your own "armchair detecting." (This also gives me more time to insure that the code is well-commented, etc.)


 * Note!:You will notice that vw is the prevailing prefix used throughout the code. This applies to function names, data types, constants, etc. A side effect of this is that, since there is HVWWND instead of HWND (et al.), many structures had to be redefined to specify the new data type instead of the original version. This is tedious at best, and is avoided whenever possible.

The Anchor Block Structure
typedef struct _VWAB { ULONG ulSzStruct; ULONG ulStatus; HCMMEM hcmWork; HCLLIST hclClasses; HCLLIST hclWindows; HCLLIST hclTimers; HMODULE hmClasses; BOOL bIsSendMsg; struct _VWWND *hwndFocus; struct _VWCURSORINFO *pciCursor; USHORT usCursorState; LONG alSysValues[VWSV_CSYSVALUES]; } VWAB, *HVWAB; The anchor block data structure, shown above, is used to maintain general housekeeping data on the state of the process as a whole (vs per thread in PM). The fields are described below:

The Class Information Structure
typedef struct _VWCLASSINFO { CHAR achName[256]; PFNVWWP pfnWndProc; } VWCLASSINFO, *PVWCLASSINFO; achName is the name of the class as registered and pfnWndProc is a pointer to the associated window procedure.

The Window Structure
typedef struct _VWWND { ULONG ulSzStruct; struct _VWCLASSINFO *pciClass; USHORT usId; ULONG ulStyle; VWSWP swpSwp; LONG lForeClr; LONG lBackClr; PCHAR pchText; PVOID pvData[2]; } VWWND, *HVWWND;


 * Note!:The colors are a necessary deviation from PM since there is no Gpi support. Instead of having each window class allocate and manage window words, I decided to do it instead, since it would be a frequently used piece of information.

Message Queue Structure
typedef struct _VWMQ { ULONG ulSzStruct; VWQMSG aqmMsgs[VW_SIZEQUEUE]; ULONG ulHead; ULONG ulTail; } VWMQ, *HVWMQ;


 * Note!:This is a circular queue.

Next Month
That's it for this month. I hope I have whet your appetite with this instalment. Next month, we will begin looking at the primary modules in the library, which will be followed in subsequent month's by the other, not-as-important modules, and finally by the window classes.

Any comments are most definitely welcome to my email address. See you next month!