Implementing applications using text windows

Text windows are implemented using unix curses or using NT_info console windows. All 'subwindows' are implemented on top of this basic interface. That is, no system sub-windowing is done. An application is responsible for its own subwindows -- but significant tools are provided to support this.

Unlike other unix curses applications, you'll find this one to be relatively easy to get the function keys working. This tools sets up its own TERMINFO directory and force the terminfo source file. Only XTERM's are supported. This means that portability is likely -- unless the user does something goofy with xrdb or the XTerm resoruces file. The first text windowing application you execute will create (on unix) the $HOME/.tools_dir directory. It will contain the terminfo source file which will be compiled by /usr/bin/tic.

Specifically, $HOME/.tools_home/MACHINE/

If you are having trouble with key bindings it will because of your xrdb settings or your $HOME/XTerm resource file. If you changed them from their defaults, you may need to fix the $HOME/.tools_dir/ file to account for those same changes or you can try removing your overrides. As I said, unless you mess with these X configurations, you should get the correct settings. If you have messed with the settings and don't know how to fix the problem, see fixing_function_key_bindings .

The program tests/test_curses.c will allow you to get keycodes with the minimum amount of filtering. The editor instantiates a viewer, named KeyViewer, which is almost but not quite as flexibile. You can use ^X ^N from the editor and then select KeyViewer as a quick way to look at keycodes. However, the keyviewer intercepts the paging and arrow keys -- so you can't really use ti to diagnose trouble with your keybindings.

Note that on RedHat 9, there is a strange bug envolving the ^Z key. Normally, ^Z is bound to the SUSP interrupt. The cursor text windowing package redirects this builting behaviour and returns 0x1a. However, on RedHat 9, there is a strange bug that works like this If and only if you run a cursor text windowing program from a script:

The text windowing tools are provided in a series of layers. You should choose the highest layer that will actually work for you because it will place the least burden on you. It is possible to jump in at any layers, however -- if you want to do something not 'built in'.

Layers of text windowing classes

Here are the layers of text windowing classes/headers/functions:

Overview of window creation

The simplest way to create a text windowing application is do the following:

A trivial example

For an example of such an application,

See also:
test_viewer.c. Note that while this example is trivial and seems easy to implement, the ListViewer class is actually easier to use for any moderately complex application interface. Consider DirectoryViewer as an example of a medium complexity interface and how it is implemented as a ListViewer. Try maximizing, minimizing, and resizing the window to see what happens.

The ExampleViewer application will have 1 window. It will contain the text your viewer class chooses to paint. When the user closes the window, your class will be deleted and the application will exit. In order to provide more than one window and more than one kind of viewer, you should use the ViewerManager::add_app function. This lets you provide the viewer manager a way to know how to create new windows -- and with that, the user can split the screen (ie the curses window) either horizontally or vertically.

A realistic ListViewer example

A ListViewer example can be found in tests/test_dirviewer.c. This program begins with a directory display in a single window. However, it properly defines the DirectoryViewer as a ViewerManager application and thus you can split the screen horizontally and vertically -- placing a new directory viewer in each split. To see the key bindings that allow these splits and mergers, press F1 when you bring up the help displayer. It will describe the key bindings. It will tell you that ^X 2 splits the screen vertically, ^X 3 splits it horizontally, and ^X 1 merges the splits into 1 viewport. There is other help information of interest. Press any key to kill the help viewer display.

Drawing in text windows

As you can see from the above example, you draw in text windows by writing text to them. Every character you draw has an associated text attribute. If draw in a CursorWindow, you will be using the screen (ie curses or NT) native drawing origin. This is not recommended. In general, you should be implementing a Viewer or a worst a CursorWindow::viewport. The drawing functions for viewports and cursor windows is the same however. You can either 'write' a character or a string or you can use operator << to write to the viewport or cursor window. The operator<< lets you create simplistically formatted outputs.

Drawing occurs in the context of the current cursor position (which gets incremented by the write operation) and the current text attributes -- which stay the same until changed. Text attributes are as follows:

Note that this allows a lot of flexibility in application choices. If you wish to avoid having to think for yourself about what attributes ought to be used where, you can use either of the following sets of global variables which define a consistent group of attributes:

If you do not wish to use the ViewerManager, you the CursorWindow class has a set of variables with the same names that define the same consistent set of attributes.

When drawing in a viewport, you should follow the following layout guideline: always check the physical screen origin of the viewport and if the origin column is not 0, reserve the left most column of the viewport for a column of vertical bars -- which you should draw in the normal_att. Also, make sure the bottom line of your viewport is underlined or drawn in reverse video. While these two rules seem a bit burdensome, they don't turn out to be much of an annoyance in practice -- and these rules reduce the amount of wasted screen space while also providing clear demarcation of the borders between viewports.

Generated on Wed Feb 29 22:51:48 2012 for CXXUtilities by  doxygen 1.6.3