.\" ********************** .if \nQ=0 \{\ .tm Run me off with "tbl | *roff -me"! .tm .tm You can shut off these annoying messages .tm by editing this file and changing the .tm ".nr Q 0" line to ".nr Q 1", or by giving .tm "-rQ1" to nroff/troff. .tm .\} .\" ********************** set the constants .nr Ls 2 \" 2 for double space; 1 to save paper .nr Ns \n(pp \" Save "normal" point size .nr Ss 9 \" small point size -- used if \n(Ls=1 (to save paper) .nr Vv 1 \" ``verbose'' -- announce progress thru troff .\" ********************** .ie \nQ=0 \{\ .tm Twiddlable things: .tm \tLine spacing = \n(Ls .if \n(Ls=1 .tm \tSmall pointsize = \n(Ss .ie \n(Vv=1 .tm \tVerbosity ON (monitoring progress) .el .tm \tVerbosity OFF .tm .\} .el .nr Vv 0 \" force non-verbose for Q(uiet) mode .\" ********************** Table of Contents stuff . \" new attempt at stuff to set up tables of contents . \" macro to put sections into table of contents . \" fails on first section if it is a .uh section .de Im .In \\$1 .ti -\\$2n .. .de In 'ba \\$1n 'in \\n($iu + \\n(pou .. .de $0 .na .(x t .Tc "\\$1" \\$2 \\$3 .)x .ad b .. .de $C .na .(x t .Tc "\\$3" \\$2 1 .)x .ad b .. .de BI .xl -\\$1n .IN \\$1n .. .de BO .xl +\\$1n .IN -\\$1n .. .\" ********************** Figure macros .de Bf \" *** begin figure macro (arg means floating fig) .ie \\n(.$ \ \{\ . (z . nr Ft 1 .\} .el \ \{\ . (b M . nr Ft 0 .\} .hl .(c .. .de Ef \" *** end figure macro .)c .sp .ce 1 Figure \\n(Fn: \\$1 .hl .ie \\n(Ft=1 .)z .el .)b .nr Fn +1 .nr Fb +1 .Fs .. .nr Fn 1 \" figure number counter .nr Fb 0 \" figure number counter (the one before) .de IN \" indent the given amount (using base indent) .ba \\$1n .in \\n($iu + \\n(pou .. .de BI \" bring both edges in .xl -\\$1n .IN \\$1n .. .de BO \" bring both edges out (usuall after a BI) .xl +\\$1n .IN -\\$1n .. .de AP \" *** appendix entry .bp .uh "Appendix \\n(An: \\$1" .nr An +1 .. .nr An 1 .\" ********************** Function macros .de ff \" Declare C function .ls 1 .sp 2.5 .ne 6 .nf .in +.5i .. .de fe \" End C function .in -.5i .sp .5 .ls \n(Ls .fi .lp .. .\" ********************** .sh section spacing .de $1 .sp 2 .. .de $2 .sp 1 .. .\" ********************** Start the ball rolling .if \n(Vv=1 .tm Starting up... .po 1.0i .ll 6.5i .tp .he '\fBThe Maryland Window Library\fR''- % -' .sp 0.5i .ce 100 .sz +4 The Maryland Window Library .sz -2 .sp 2 Chris Torek .sp 2 .sz -2 Department of Computer Science University of Maryland College Park, MD 20742 .sp 0.5i \fBABSTRACT\fR .ce 0 .BI 0.75i .pp There are many applications for windows, but the implementation of window software is not an easy task. The job can be considerably simplified by eliminating some of the capabilities of a full system, for example, requiring that windows do not overlap, but this reduces the usefulness of the result. This paper describes the University of Maryland Window Library, an implementation that supports a very complete character-based window system. .BO 0.75i .sp 2 \*(td .bp .ls \n(Ls .sh 1 "Introduction" .pp What exactly is a window? It is merely a rectangular region that can display text. In fact, it is very much like a standard terminal's display. However, since it exists as a subarea of a real display, it can be moved around, or covered by other windows. Windows can never be bigger than the real display. .pp One useful analogy for windows is glass over a room full of text. This room is called the buffer. The buffer can be bigger than the window. However, only the area that can be seen through the window is visible. .pp Two separate windows can look into the same room (\fIbuffer\fR). The same room is revealed through both windows, but not necessarily the same part of that room. These windows are called \*(lqlinked windows\*(rq although \*(lqlinked buffers\*(rq might have been a better phrase. .pp Thus there are two basic .q parts to a window: its window descriptor (its position and size); and its text buffer or \fItextbuf\fR (holding the text to be displayed within the window). It is also useful to have a portion of a window for non-textual information. This is called the \fIwinbuf\fR, or \*(lqwindow buffer\*(rq. Normally the winbuf contains only .q glass (empty space), but it can be written on. For example, an outline, or \fIframe\fR, may be written onto the glass, to show how much space is available within the window (see Figure \n(Fn). .Bf 1 .ie n \{\ +--------------+ | | | Some text | | in a window | | | +--------------+ .\} .el \{\ .TS box; c. Some text in a window .TE .\} .Ef "Framed window" .pp Figure \n(Fb shows a sixteen by six window with a frame. .ie n (The frame characters shown are those used on most displays. .el \{\ (The frame characters used on most terminals are .q + , .q \- , and .q | , for the corners, top and bottom, and left and right sides. .\} On displays that have some graphics capability, often the frames are cute little corners and sides that join together, giving the window a very solid appearance.) The text is in the text buffer, and the frame in the window buffer. This window has a descriptor indicating that the window is sixteen characters across by six characters high, and points to the window's winbuf and text buffer. The text buffer contains two blank lines, the words \*(lqSome text\*(rq on the third line, the words \*(lqin a window\*(rq on the fourth line, and two more blank lines. The winbuf contains the frame characters, with the inside of the winbuf being .q glass that displays the text buffer. .Bf 1 .ie n \{\ +-------------------+ | | | |----+ | | | +-------------------+ | | | +-----------+ .\} .el \{\ .\" ********************** Why doesn't this join smoothly, like it used to? \l'1.5i'\L'1i'\l'-1.5i'\h'-1.5i'\L'-1i'\v'1i'\h'1i'\L'.5i'\l'1i'\L'-1i'\l'-.5i'\v'-.5i' .sp 1.5i .\} .Ef "Overlapping windows" .pp Windows can overlap. In Figure \n(Fb two windows overlap. The only difference between overlapped, or \fIcovered\fR, characters and non-overlapped characters is that overlapped characters are invisible. If a window is covered, it can be brought to the .q front (where it will cover whatever used to cover it). Windows may also be hidden to make them totally invisible. Hiding a window that covers others will expose the others: hiding the upper window in Figure \n(Fb would make the lower one completely visible. Hiding a window has no effect on the operations that can be performed on it; one can't see the results, however, until the window is unhidden. .pp In addition to windows, there is a single .q box that may be turned on. It is a hollow rectangular region on the display that is made of inverse video characters. It can be used either to outline a window, or as a roving block cursor. As a window outline, the box can be used to display where a window may be created or moved. As a cursor, the box can be used with a mouse or a bitpad as a pointer for selecting windows. .sh 1 "What's in a window?" .sh 2 "Cursors" .pp Like a terminal, a window needs a cursor. The window's cursor shows where the next character will be placed within that window, though characters are actually written into the text buffer. The cursor is normally visible as a blinking block. It can be turned off if desired. .pp Since the window actually has two pieces, the winbuf and the textbuf, it also has more than one cursor. The normal cursor (\fIwindow cursor\fR) is the one just described. There are two others: the \fIaux cursor\fR and the \fIbuffer cursor\fR. The aux cursor and the buffer cursor will be discussed later; for now it is enough to say that they are never visible, and that all three cursors are mutually independent. In this document, \*(lqthe cursor\*(rq refers to the window cursor. .sh 2 "Text" .pp Characters within a window can be in any combination of four modes: bold, underscored, blinking, and reverse video. There is a \*(lqcurrent mode\*(rq associated with each window. This is the mode with which future characters will be printed. In addition, there is the \*(lqglass factor\*(rq for characters within the winbuf: are they real characters, or are they just empty slots through which the text buffer should be displayed? Frame characters are not glassy; the rest of the winbuf is normally filled with glassy blanks. The only way to put things into the winbuf is with the aux cursor or one of the special functions, e.g., frame window. .sh 2 "Text Buffers vs. Window Buffers" .pp A window buffer, as stated earlier, is normally just .q glass through which the text buffer is displayed. However, it is possible to write characters, such as those making up a frame, into the winbuf. These characters then obscure some of the characters in the text buffer. It is also possible to write modes into the winbuf. These modes can be considered \*(lqtinted glass\*(rq: they affect the display of characters being viewed, though the characters themselves are not changed. For example, if inverse video has been .q painted onto the .q glass , all the characters in the text buffer under that paint are displayed in inverse video. If the glass is wiped clean of its inverse video paint, the characters will be restored to normal. The modes on the glass are exclusive or'ed with those in the text buffer. .pp Text buffers also have cursors, namely the \*(lqbuffer cursor\*(rq. In linked windows, where two window descriptors share a text buffer, there is only one buffer cursor. In other words, the buffer cursor is shared along with the text buffer. .sh 3 "Margin Settings and the Aux Cursor" .pp Window buffers also have margin settings. These are mainly used internally to keep the window cursor from overwriting the frames (if there are any), but can be set if desired. Margins determine the amount of glass in the winbuf. Anything outside the margins is strictly off-limits; the space inside the margins is the glass. However, unwritable margins would not be particularly useful. The aux cursor is permitted to roam over the entire winbuf. It can be used to print characters directly into the winbuf. Any character in the winbuf will take precedence over the character underneath it in the text buffer. Essentially, the aux cursor writes on the glass. .pp While the aux cursor can be used to write into the winbuf, it can also be used in a sneaky way to .q un-write characters: the aux cursor is permitted to erase from the glass. Erasing a character from the winbuf re-exposes the character underneath in the text buffer. Tinted glass is created by erasing with a mode other than normal (i.e. any combination of blinking, bold, underscored, and reverse video). .pp Text buffers do not have margin settings. No part of the text buffer is protected. Quite often, however, some of the text buffer is not visible. In a typical framed window, the entire top and bottom lines of the buffer, and the left and right edges, are not visible, since they are covered by the frame characters. (Note that since the aux cursor could at any time erase part of the frames, they must remain invisible until explicitly exposed. They can't be automatically \*(lqmoved down and right\*(rq.) Figure \n(Fn should clear some of the mud. .Bf 1 .)c .ce A window .sp .(c .ie n \{\ +------------------+ |his is the second | |ne, third line, fo| |th line,... | +------------------+ .\} .el \{\ .TS box; l. \zh\h'.5'\zi\h'.5'\zs\h'.5'\z \h'.5'\zi\h'.5'\zs\h'.5'\z \h'.5'\zt\h'.5'\zh\h'.5'\ze\h'.5'\z \h'.5'\zs\h'.5'\ze\h'.5'\zc\h'.5'\zo\h'.5'\zn\h'.5'\zd \zn\h'.5'\ze\h'.5'\z,\h'.5'\z \h'.5'\zt\h'.5'\zh\h'.5'\zi\h'.5'\zr\h'.5'\zd\h'.5'\z \h'.5'\zl\h'.5'\zi\h'.5'\zn\h'.5'\ze\h'.5'\z,\h'.5'\z \h'.5'\zf\h'.5'\zo \zt\h'.5'\zh\h'.5'\z \h'.5'\zl\h'.5'\zi\h'.5'\zn\h'.5'\ze\h'.5'\z,\h'.5'\z.\h'.5'\z.\h'.5'\z. .TE .\} .)c .sp .ce and its text buffer .sp .(c .ie n \{\ IIIIIIIIIIIIIIIIIIII This is the second l ine, third line, fou rth line,... Y JJJJJJJJJJJJJJJJJJJJ .\} .el \{\ \zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI\h'.5'\zI \zT\h'.5'\zh\h'.5'\zi\h'.5'\zs\h'.5'\z \h'.5'\zi\h'.5'\zs\h'.5'\z \h'.5'\zt\h'.5'\zh\h'.5'\ze\h'.5'\z \h'.5'\zs\h'.5'\ze\h'.5'\zc\h'.5'\zo\h'.5'\zn\h'.5'\zd\h'.5'\z \h'.5'\zl \zi\h'.5'\zn\h'.5'\ze\h'.5'\z,\h'.5'\z \h'.5'\zt\h'.5'\zh\h'.5'\zi\h'.5'\zr\h'.5'\zd\h'.5'\z \h'.5'\zl\h'.5'\zi\h'.5'\zn\h'.5'\ze\h'.5'\z,\h'.5'\z \h'.5'\zf\h'.5'\zo\h'.5'\zu \zr\h'.5'\zt\h'.5'\zh\h'.5'\z \h'.5'\zl\h'.5'\zi\h'.5'\zn\h'.5'\ze\h'.5'\z,\h'.5'\z.\h'.5'\z.\h'.5'\z.\h'.5'\h'3.5'\zY \zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ\h'.5'\zJ .\} .Ef "A window and buffer" .sh 3 "Operations" .pp Since a buffer can be larger than its window, there are \*(lqbuffer operations\*(rq and \*(lqwindow operations\*(rq. In general, window operations deal with the visible portion of the text buffer, and in many cases with the glass through which said text is viewed. Buffer operations deal exclusively with the text buffer, and are not limited to the visible portions\**. .(f \**\*(lqVisible portions\*(rq can include covered or hidden portions. .q Covered is used to describe windows or characters that are obscured by other windows. .q Hidden is used to describe windows not displayed at all by specific request. The visible portion of a window's textbuf is the area that is inside the window's margins; this is irrespective of whether the window is hidden and/or covered. .)f Figure \n(Fn shows what happens when a line delete is performed as both a window operation and a buffer operation on a window that is smaller than its buffer. .Bf 1 .ie n \{\ Window Buffer Window Buffer +------+ 0123456789 +------+ 0123456789 |CDEFGH| ABCDEFGHIJ |CDEFGH| ABCDEFGHIJ |MNOPQR| KLMNOPQRST |MNOPQR| KLMNOPQRST |WXYZab| UVWXYZabcd |WXYZab| UVWXYZabcd +------+ efghijklmn +------+ efghijklmn (delete line from window) (delete line from buffer) +------+ 0123456789 +------+ 0123456789 |CDEFGH| ABCDEFGHIJ |CDEFGH| ABCDEFGHIJ |WXYZab| KLWXYZabST |WXYZab| UVWXYZabcd | | UV cd |ghijkl| efghijklmn +------+ efghijklmn +------+ .\} .el \{\ .)c .ta 1.1i 2.1i 3.5i 4.5i Window Buffer Window Buffer .\" line 1 \z0\h'.7'\z1\h'.7'\z2\h'.7'\z3\h'.7'\z4\h'.7'\z5\h'.7'\ \z6\h'.7'\z7\h'.7'\z8\h'.7'\z9\h'.7' \z0\h'.7'\z1\h'.7'\z2\h'.7'\ \z3\h'.7'\z4\h'.7'\z5\h'.7'\z6\h'.7'\z7\h'.7'\z8\h'.7'\z9 .mk 1 \" line 2 .\" register 1 holds line, 2 holds lc 1st window, 3 holds lc 2nd window \k2\ \zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7' \zA\h'.7'\ \zB\h'.7'\zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7'\zI\h'.7'\ \zJ\h'.7' \k3\ \zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7' \ \zA\h'.7'\zB\h'.7'\zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7'\ \zI\h'.7'\zJ .\" line 3 \zM\h'.7'\zN\h'.7'\zO\h'.7'\zP\h'.7'\zQ\h'.7'\zR\h'.7' \zK\h'.7'\ \zL\h'.7'\zM\h'.7'\zN\h'.7'\zO\h'.7'\zP\h'.7'\zQ\h'.7'\zR\h'.7'\zS\h'.7'\ \zT\h'.7' \zM\h'.7'\zN\h'.7'\zO\h'.7'\zP\h'.7'\zQ\h'.7'\zR\h'.7' \ \zK\h'.7'\zL\h'.7'\zM\h'.7'\zN\h'.7'\zO\h'.7'\zP\h'.7'\zQ\h'.7'\zR\h'.7'\ \zS\h'.7'\zT .\" line 4 \zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7' \zU\h'.7'\ \zV\h'.7'\zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7'\zc\h'.7'\ \zd\h'.7' \zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7' \ \zU\h'.7'\zV\h'.7'\zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7'\ \zc\h'.7'\zd .\" line 5 \ze\h'.7'\zf\h'.7'\zg\h'.7'\zh\h'.7'\zi\h'.7'\zj\h'.7'\ \zk\h'.7'\zl\h'.7'\zm\h'.7'\zn\h'.7' \ze\h'.7'\zf\h'.7'\ \zg\h'.7'\zh\h'.7'\zi\h'.7'\zj\h'.7'\zk\h'.7'\zl\h'.7'\zm\h'.7'\zn .\" draw windows .sp -1.5 \h'|\n2u-.5n'\L'|\n1u-1.5'\l'4.2+1n'\L'-|\n1u+1.5'\l'|\n2u-.5n'\ \h'|\n3u-.5n'\L'|\n1u-1.5'\l'4.2+1n'\L'-|\n1u+1.5'\l'|\n3u-.5n' .sp 1.5 .ce (delete line from window) (delete line from buffer) .sp .\" line 1 \z0\h'.7'\z1\h'.7'\z2\h'.7'\z3\h'.7'\z4\h'.7'\z5\h'.7'\ \z6\h'.7'\z7\h'.7'\z8\h'.7'\z9\h'.7' \z0\h'.7'\z1\h'.7'\ \z2\h'.7'\z3\h'.7'\z4\h'.7'\z5\h'.7'\z6\h'.7'\z7\h'.7'\z8\h'.7'\z9 .mk 4 .\" line 2 \k5\ \zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7' \zA\h'.7'\ \zB\h'.7'\zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7'\zI\h'.7'\ \zJ\h'.7' \k6\ \zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7' \ \zA\h'.7'\zB\h'.7'\zC\h'.7'\zD\h'.7'\zE\h'.7'\zF\h'.7'\zG\h'.7'\zH\h'.7'\ \zI\h'.7'\zJ .\" line 3 \zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7' \zK\h'.7'\ \zL\h'.7'\zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7'\zS\h'.7'\ \zT\h'.7' \zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7' \ \zU\h'.7'\zV\h'.7'\zW\h'.7'\zX\h'.7'\zY\h'.7'\zZ\h'.7'\za\h'.7'\zb\h'.7'\ \zc\h'.7'\zd .\" line 4 \zU\h'.7'\zV\h'.7'\z \h'.7'\z \h'.7'\z \h'.7'\z \h'.7'\ \z \h'.7'\z \h'.7'\zc\h'.7'\zd\h'.7' \zg\h'.7'\zh\h'.7'\zi\h'.7'\ \zj\h'.7'\zk\h'.7'\zl\h'.7' \ze\h'.7'\zf\h'.7'\zg\h'.7'\zh\h'.7'\ \zi\h'.7'\zj\h'.7'\zk\h'.7'\zl\h'.7'\zm\h'.7'\zn .\" line 5 \ze\h'.7'\zf\h'.7'\zg\h'.7'\zh\h'.7'\zi\h'.7'\zj\h'.7'\ \zk\h'.7'\zl\h'.7'\zm\h'.7'\zn .\" draw windows .sp -1.5 \h'|\n5u-.5n'\L'|\n4u-1.5'\l'4.2+1n'\L'-|\n4u+1.5'\l'|\n5u-.5n'\ \h'|\n6u-.5n'\L'|\n4u-1.5'\l'4.2+1n'\L'-|\n4u+1.5'\l'|\n6u-.5n' .sp 1.5 .(c .\} .Ef "Window and Buffer Operations: Line Delete" .if t .if \n(Vv=1 .tm Just set up big gory figure... .pp When the cursor position is relevant to the operation, window operations are done at the window cursor, and buffer operations at the buffer cursor. Only two operations (aux print and aux read) are done at the aux cursor position. .sh 2 "Scrolling" .pp The real reason for having separate text buffers and window buffers is to allow the storage of more text than is visible. That is, buffers can be much larger than the window through which they are viewed. This means that a window can be moved over the buffer. To go back to the room-of-text analogy, the wall is flexible, and the glass of the window can be pulled around on it. In the window library, moving the window over its text buffer is called scrolling. Thus you can scroll a window up, down, left, or right, over its buffer. There are limits, however: the amount of scrolling permitted depends on just how much more space there is in the buffer than the window. You can't pull the glass past the edge of the wall. .pp The more conventional definition of scrolling is moving the existing text upward or downward, discarding one line at the top or bottom, and making room for new text. The window library provides this by making an exception to the scrolling limits. If the window is scrolled past the end of the buffer, the buffer is .q extended one line at the bottom, and a line is .q erased from the top, making the window fit once again. (The actual algorithm is to copy the text upward, keeping the window at the bottom of the buffer.) A similar exception is made for scrolling past the beginning of the buffer. This action (moving the text upwards or downwards, losing a line off the top or bottom) is called \*(lqscrolling the buffer\*(rq, and may be done directly, without moving the window past the edge of the buffer. .pp Windows automatically scroll when necessary. When this happens, the number of lines scrolled is controlled by the window's \fIpopup\fR. Popup defaults to one, but can be set anywhere from zero to the size of the window. Scrolling by \fIn\fR lines (\fIn\fR > 1) is exactly equivalent to scrolling by one line \fIn\fR times. Scrolling by zero lines is a special case. It is not scrolling at all. Rather, the cursor is brought to the top of the window and the top line is cleared. Each time the cursor advances to the next line, that line is also cleared. When the cursor reaches the bottom of the window, the process is repeated. This is much faster on some terminals, but tends to be confusing. .sh 2 "Printing Text" .pp There are three ways to print text into a window. The first is to print at the window cursor, the second to print at the buffer cursor, and the third to print at the aux cursor. The first and second are generally more useful than the third, and have less .q drastic effects. .pp The aux cursor can be anywhere within the window buffer, and characters printed with it are required to have a mode. This mode includes (in addition to the standard four mode bits) the .q glassiness information. The character being printed is not interpreted in any way, but simply shoved onto the glass. If the character is not standard ASCII (codes 32 to 126 decimal), the results are terminal-dependent. Some terminals use special codes for the window frame characters, and look for such codes; others do not and may end up clearing the screen, repositioning the cursor, or doing other undesirable things. Therefore, the aux cursor must be used very carefully. .pp Both the window cursor and the buffer cursor check the character being printed, and take special actions for non-ASCII characters. Most of these codes are ignored. The following are not: .ip \fBBELL\fR ASCII 7, or bell, rings the terminal's bell. If desired, this may be set to flash the terminal's screen instead, providing that the terminal has this capability. Visible bells are often nicer in a crowded working environment. .ip \fBBS\fR ASCII 8, or backspace, moves the cursor backwards one character. If the cursor is at its leftmost permitted column, it does not move. .ip \fBTAB\fR ASCII 9, tab, moves the cursor forward one tab stop. Tab stops are set at every eight columns. If there are no remaining tab stops, the cursor is moved to the rightmost column. .ip \fBLF\fR ASCII 10, linefeed, moves the cursor down one line without changing its column. (If CR/LF mapping is turned on, it moves it to the leftmost column.) If the cursor is on the bottom line, the window is scrolled. If this is the buffer cursor, then one line at the top of the buffer is thrown away, and a new blank\** line is introduced (i.e. the buffer is scrolled). .(f \**The blanks introduced are in the current mode of the window; i.e. if the current mode is inverse video, a line of inverse video blanks is made. This is true for all functions that introduce blanks in the buffer. .)f If this is the window cursor, then the window is scrolled by its popup. .ip \fBCR\fR ASCII 13, carriage return, moves the cursor to the leftmost column. (If CR/LF mapping is turned on, it also performs a linefeed). .pp For the window and buffer cursors, autowrap and CR/LF mapping can be turned on and off. Autowrap means that when a character is written in the last column of the window or buffer, it is wrapped to the next line, as if a carriage return and line feed had been printed. This mode defaults on. CR/LF mapping makes both carriage return and line feed go to the first column of the next line; i.e., either code performs the actions normally done by both. This mode defaults off. The aux cursor always wraps, and, upon reaching the last column of the last line, wraps to the first column of the first line. Since it does not translate special codes, it ignores CR/LF mapping. It should not normally be used to print CRs or LFs. .sh 1 "Update Optimization" .pp The Maryland Window Library keeps track of what the terminal's screen looks like, and when asked to update (\fIrefresh\fR) the screen, attempts to do it with the greatest possible speed. If a section of lines on the current screen matches a section on the desired screen, line insert and delete operations may be done to move the old lines to their new position. If subsections of an old line match those of a new one, insert and delete character may be used. Any number of arbitrarily complex operations may be done between screen refreshes; the update is computed at refresh time. .sh 1 "Signal Handling" .pp Since window display mode turns on many special Unix\** .(f \**Unix is a trademark of Bell Laboratories. .)f tty modes, it needs to take special consideration of signals that normally cause it to stop or exit. (For more information on signals, see \fIsignal\fR(2) and \fIjobs\fR(3j) in the Unix Programmer's Manual [Joy et al 81].) The Maryland Window Library uses the job control routines provided in Berkeley 4.1 Unix. Since many Unix systems don't have job control, the actual calls to these routines are made only if permitted by the programmer. If signal handling is not enabled, it is the programmer's job to manage the Unix signals. Signal management is not always easy, so if enabled, the window library will provide default signal handlers for those signals likely to occur, namely SIGINT and SIGTSTP. SIGINT is the interrupt signal (generated with the DEL key). The default handler for this signal exits after restoring the initial terminal modes. SIGTSTP is the terminal stop signal (generated with control-Z). The default handler for this signal cleans up the terminal settings, suspends the process, and upon resumption re-initializes the terminal to windows mode.\** .(f \**I chose not to catch SIGQUIT since core dumps are handy for debugging. Besides, one can always call \fBsigset (SIGQUIT, Wexit);\fR. .)f .pp Enabling signal handling is done with the \fBWinit\fR call (described later). If at all possible, it is recommended that signal handling be enabled. If the default signal handlers are not desired, signal handling should be enabled anyway, and the handlers changed to new functions via \fBsigset\fR. .lp \fINote: under 4.2BSD, we use \fBsignal\fI as usual, since \fBsignal\fI system call in 4.2 behaves just like \fBsigset\fI did in 4.1. The jobs library is no longer used. \fR--ACT .pp If the target operating system does not have the jobs library, then there are two alternatives. One is to write a jobs library simulator (see Appendix 3); the other to not use it (the jobs library). In either case the functions \fBsigset\fR, \fBsighold\fR, \fBsigrelse\fR, and \fBsigignore\fR must be provided. If the functions are not being used, they may be empty (e.g. \fBsigset () {}\fR). .sh 1 "Window Library Functions" .pp This section describes the actual functions provided by the Maryland Window Library. All return a value. Most return zero if they succeed; exceptions are listed. To compile with the library, \fI#include\fR the file \fB\fR, and include \fI\-lwinlib \-ljobs \-ltermlib\fR when making the executable. (See Appendix 4 for sample programs.) The first four functions listed are those for initializing, suspending, and cleaning up; the remainder are in alphabetical order. Note: several functions \fIclip\fR their values. This means that if they are given out-of-range values, the nearest value that is in range is used. .pp The window library provides several types, macros, and variables. The main type is \fBWin\fR, and is the window descriptor structure. There is also a .q current window, called \fBCurWin\fR, but it is in no way special; it is provided for convenience only. It is affected only by the functions \fBWopen\fR, \fBWlink\fR, \fBWclose\fR, \fBWcloseall\fR, \fBWfind\fR, and \fBWboxfind\fR. The type, macro, and variable definitions are listed in Appendix 1. Note: \fBbold\fR text indicates exact strings. .ie t \fIItalicized\fR .el \fIUnderscored\fR text indicates arguments that are to be filled in. .br \" Force out the line, >>before<< switching sizes! .if \n(Vv=1 .tm Starting function list (about 1/4 done)! .if \n(Ls=1 \{\ .nr pp \n(Ss \" *** small text for fn listing if single spaced .sz \n(Ss .\} .ff \fBWinit (\fIsettings\fB,\fR \fInomagic\fB) struct sgttyb *\fIsettings\fB; int\fR \fInomagic\fB;\fR .fe Initializes the window system, clearing the screen and setting the tty modes. Normally, both \fIsettings\fR and \fInomagic\fR should be given as zero. To resume a suspended session, where \fBWinit\fR has already been called, \fIsettings\fR may be given as \fB(struct sgttyb *) 1\fR. If special tty mode settings are desired, \fIsettings\fR can be the address of a preset \fBstruct sgttyb\fR structure (see \fIstty\fR(2), \fIgtty\fR(2)). (Baud rate will be replaced with the actual baud rate of the terminal.) Unless signal handling is not desired (or not necessary, e.g. in raw mode) \fInomagic\fR should be given as zero. Otherwise signal handling will not be enabled. A value of zero will set \fBWsuspend\fR to catch SIGTSTP and \fBWexit\fR to handle SIGINT. .pp \fBWinit\fR returns zero if the window package can be run on the terminal. If \fBWinit\fR does not return zero, nothing has been done, and none of the other functions should be called. (\fBWinit\fR will return the same value if called again, so if it said .q Ok once it won't change its mind.) .pp The first call to \fBWinit\fR will normally set the variable \fBWSetRealCursor\fR to one, so that the terminal's real cursor will be left in the upper left hand corner of the display screen, where it is presumably out of the way. However, if any of the variables \fBWSetRealCursor\fR, \fBWRCurRow\fR, or \fBWRCurCol\fR are set, this first call will not set \fBWSetRealCursor\fR. .ff \fBWsuspend ()\fR .fe Suspends the process by calling \fBWcleanup\fR, sending SIGTSTP, and then calling \fBWinit (1, 1)\fR. This is the standard way to handle control-Z. .ff \fBWcleanup ()\fR .fe Cleans up the terminal settings to the way they were when \fBWinit\fR was called. This must be done before exiting, or before giving up control of the terminal (e.g. to a subshell). .ff \fBWexit (\fIcode\fB) int\fR \fIcode\fB;\fR .fe Calls \fBWcleanup\fR and \fBexit (\fIcode\fB)\fR. This should be used instead of \fBexit\fR unless \fBWcleanup\fR has already been called. .ff \fBDing ()\fR .fe Rings the terminal's bell. This is normally just called when control-G (BELL) is printed, but it can be called directly if desired. If the variable \fBVisibleBell\fR is nonzero, and the terminal supports it, this will flash the terminal's screen instead. .ff \fBMax (\fIa\fB,\fR \fIb\fB)\fR .fe This is a macro which expands to .sp \fB((\fIa\fB) > (\fIb\fB) ? (\fIa\fB) : (\fIb\fB))\fR .sp which is the larger of the two arguments. .ff \fBMin (\fIa\fB,\fR \fIb\fB)\fR .fe This is a macro which expands to .sp \fB((\fIa\fB) < (\fIb\fB) ? (\fIa\fB) : (\fIb\fB))\fR .sp which is the smaller of the two arguments. .ff \fBWAcursor (\fIw\fB,\fR \fIrow\fB,\fR \fIcol\fB) Win *\fIw\fB; int\fR \fIrow\fB,\fR \fIcol\fB;\fR .fe Sets the position of the window cursor. The position (0, 0) is as far left and up as the window cursor can get over the text buffer; this function may scroll the window to get to the specified position. The name of this function stands for \*(lqWindow Absolute cursor move\*(rq, meaning move the window cursor to an absolute coordinate, where .q absolute means measured from as far left and up as possible. To move only within the window (where (0, 0) is the upper left corner inside the margin settings), use \fBWWcursor\fR. \fIRow\fR and \fIcol\fR are clipped to be within the window. .ff \fBWAread (\fIw\fB,\fR \fIcharonly\fB) Win *\fIw\fB; int\fR \fIcharonly\fB;\fR .fe Reads back a character and (unless \fIcharonly\fR is set) its mode from window \fIw\fR's winbuf at the aux cursor. The aux cursor is then advanced, wrapping from the last character of the last line to the first character of the first line if necessary. See \fBWCHAROF\fR and \fBWMODEOF\fR. .ff \fBWBclear (\fIw\fB,\fR \fIhowto\fB) Win *\fIw\fB; int\fR \fIhowto\fB;\fR .fe Clears (sets to blanks) the text buffer attached to window \fIw\fR. If \fIhowto\fR is zero, the buffer is cleared from the buffer cursor to the end of the buffer, including the character under the cursor; if one, from the beginning of the buffer to the cursor, not including the character under the cursor; if two, the entire buffer is cleared. Other values are treated as zero. .ff \fBWBclearline (\fIw\fB,\fR \fIhowto\fB) Win *\fIw\fB; int\fR \fIhowto\fB;\fR .fe Clears the line the cursor is on in the text buffer attached to window \fIw\fR. If \fIhowto\fR is zero the line is cleared from the buffer cursor to the end of the line, including the character under the cursor; if one, from the beginning of the line to the buffer cursor, not including the character under the cursor; if two, the entire line is cleared. Other values are treated as zero. .ff \fBWBcursor (\fIw\fB,\fR \fIrow\fB,\fR \fIcol\fB) Win *\fIw\fB; int\fR \fIrow\fB,\fR \fIcol\fB;\fR .fe Sets the buffer cursor of the text buffer attached to window \fIw\fR to row \fIrow\fR, column \fIcol\fR. Note: there is only one buffer cursor per buffer (i.e. two linked windows have only one buffer cursor). \fIRow\fR and \fIcol\fR are clipped to be within the buffer. .ff \fBWBdelchars (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Deletes \fIn\fR characters starting at the buffer cursor from the text buffer attached to window \fIw\fR. .ff \fBWBdelcols (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Deletes \fIn\fR columns starting at the buffer cursor column from the text buffer attached to window \fIw\fR. In effect, calls \fBWBdelchars\fR on each line. .ff \fBWBdellines (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Deletes \fIn\fR lines from the text buffer attached to window \fIw\fR, starting with the line containing the buffer cursor. .ff \fBWBinschars (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Inserts \fIn\fR blanks at the buffer cursor in the text buffer attached to window \fIw\fR. .ff \fBWBinscols (\fIw\fB,\fR \fIn\fB) Win *\fIw\B; int\fR \fIn\fB;\fR .fe Inserts \fIn\fR columns in the text buffer attached to window \fIw\fR. In effect, calls \fBWBinschars\fR on each line. .ff \fBWBinslines (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Inserts \fIn\fR lines at the buffer cursor in the text buffer attached to window \fIw\fR. .ff \fBWBputc (\fIc\fB,\fR \fIw\fB)\fR\** .(f \**Note that for this and all other \fBputc\fR and \fBputs\fR functions, the window parameter comes \fIlast\fR. .)f \fBchar\fR \fIc\fB; Win *\fIw\fB;\fR .fe Prints character \fIc\fR to the buffer attached to window \fIw\fR at the buffer cursor, and advances the buffer cursor. Note that this character may well not be visible inside any or all of the windows using this buffer; care should be taken when using this function to be sure that (if necessary and desired) a window is \fBWrelscroll\fRed so that the character is visible. .ff \fBWBputs (\fIs\fB,\fR \fIw\fB) char *\fIs\fB; Win *\fIw\fB;\fR .fe Puts a C style (null terminated) string into the buffer attached to window \fIw\fR, by using \fBWBputc\fR on each character in \fIs\fR. .ff \fBWBread (\fIw\fB,\fR \fIcharonly\fB) Win *\fIw\fB; int\fR \fIcharonly\fB;\fR .fe Reads back a character and (unless \fIcharonly\fR is set) its mode from the buffer attached to window \fIw\fR at the buffer cursor. The buffer cursor is then advanced, wrapping from the last character of the last line to the first character of the first line if necessary. (Note that this ignores the autowrap setting.) See \fBWCHAROF\fR and \fBWMODEOF\fR. .ff \fBWBscroll (\fIw\fB,\fR \fIrows\fB) Win *\fIw\fB; int\fR \fIrows\fB;\fR .fe Scrolls the buffer attached to window \fIw\fR forward by \fIrows\fR lines (or backward if \fIrows\fR is negative). Text is lost at the top (bottom if \fIrows\fR is negative) and blanks are introduced at the bottom (top). The buffer cursor is moved upward \fIrows\fR lines (downward \-\fIrows\fR lines if \fIrows\fR is negative), which makes it stay over the same text. .ff \fBWBtoWcursor (\fIw\fB) Win *\fIw\fB;\fR .fe Moves the buffer cursor of the buffer attached to window \fIw\fR to be over the same character that \fIw\fR's window cursor is over. This can be used to get the buffer cursor to the window cursor so that buffer operations can be performed at the window cursor's position. .ff \fBWCHAROF (\fIc\fB) int\fR \fIc\fB;\fR .fe Returns the character element of \fIc\fR, as returned by \fBWAread\fR, \fBWBread\fR, or \fBWread\fR. This is actually a macro which expands to .sp \fB((\fIc\fB) & 0377)\fR .sp (It may be system dependent, and require changing.) .ff \fBWMODEOF (\fIc\fB) int\fR \fIc\fB;\fR .fe Returns the mode element of \fIc\fR, as returned by \fBWAread\fR, \fBWBread\fR, or \fBWread\fR. This is actually a macro which expands to .sp \fB((\fIc\fB) >> NBPB)\fR .sp (It may be system dependent, and require changing.) .ff \fBWWcursor (\fIw\fB,\fR \fIrow\fB,\fR \fIcol\fB) Win *\fIw\fB; int\fR \fIrow\fB,\fR \fIcol\fB;\fR .fe Sets the position of the window cursor of window \fIw\fR to row \fIrow\fR, column \fIcol\fR. \fIRow\fR and \fIcol\fR are clipped to be within the margins. (0, 0) is the upper left hand corner immediately inside the margin settings. .q WWcursor stands for \*(lqWindow Window-relative cursor move\*(rq, meaning move the cursor to a point relative to the current window position; this function will never move the window over its buffer. .ff \fBWWtoBcursor (\fIw\fB) Win *\fIw\fB;\fR .fe Moves the window cursor of the window \fIw\fR to be over the same character that \fIw\fR's buffer's buffer cursor is over. This is actually a macro that expands to a \fBWAcursor\fR call, with many references to \fIw\fR; watch out for side effects of things like \fBWWtoBcursor (w++)\fR. .ff \fBWaputc (\fIc\fB,\fR \fIm\fB,\fR \fIw\fB) char\fR \fIc\fB; int\fR \fIm\fB; Win *\fIw\fB;\fR .fe Puts character \fIc\fR into \fIw\fR's winbuf at the aux cursor. The character is not interpreted in any way (e.g. tab does not move to the next tab stop). The mode \fIm\fR may have any of the standard attributes (WBOLD, WBLINK, WULINE, WINVERSE), and one more, called WBUF, which means \*(lqI see through to the text buffer\*(rq (this is the \*(lqglass factor\*(rq). Modes in the window buffer are exclusive ored with modes in the text buffer if the WBUF bit is set; if not, the mode and character at that position are put on the display. Thus you can create a region of a window which is always in inverse video, no matter what happens underneath. .ff \fBWaputs (\fIs\fB,\fR \fIm\fB,\fR \fIw\fB) char *\fIs\fB; int\fR \fIm\fB; Win *\fIw\fB;\fR .fe Puts a C style (null terminated) string using \fBWaputc (*\fIs\fB,\fR \fIm\fB,\fR \fIw\fB)\fR on each character. .ff \fBWauxcursor (\fIw\fB,\fR \fIrow\fB,\fR \fIcol\fB)\fR\** .(f \**This function should have been called .q Wacursor for consistency, but I felt that that would confuse it with .q WAcursor . .)f \fBWin *\fIw\fB; int\fR \fIrow\fB,\fR \fIcol\fB;\fR .fe Sets the position of the aux cursor to row \fIrow\fR, column \fIcol\fR. (0, 0) is the upper left hand corner. \fIRow\fR and \fIcol\fR clipped to be within the window. .ff \fBWback (\fIw\fB) Win *\fIw\fB;\fR .fe Moves window \fIw\fR to the .q back of the screen (i.e. window \fIw\fR is covered by all other windows that it intersects). This is the inverse of \fBWfront\fR. .ff \fBWborder (\fIw\fB,\fR \fIulc\fB,\fR \fItop\fB,\fR \fIurc\fB,\fR \fIleft\fB,\fR \fIright\fB,\fR \fIllc\fB,\fR \fIbottom\fB,\fR \fIlrc\fB) Win *\fIw\fB; char\fR \fIulc\fB,\fR \fItop\fB,\fR \fIurc\fB,\fR \fIleft\fB,\fR \fIright\fB,\fR \fIllc\fB,\fR \fIbottom\fB,\fR \fIlrc\fB;\fR .fe Borders (frames) window \fIw\fR with the specified characters. \fIUlc\fR is the upper left corner; \fItop\fR is the top line; \fIurc\fR is the upper right corner; \fIleft\fR is the left side; \fIright\fR is the right side; \fIllc\fR is the lower left corner; and \fIlrc\fR is the lower right corner. If not already set, margins are set so that the frame characters are off-limits to window operations. When a window is framed, a subsequent label operation (see \fBWlabel\fR) will leave the left and right corners untouched, but overwrite the top or bottom frame characters. Normally \fBWframe\fR is used to frame windows; this call allows non-standard frame characters. .ff \fBWbox (\fIxorg\fB,\fR \fIyorg\fB,\fR \fIxext\fB,\fR \fIyext\fB) int\fR \fIxorg\fB,\fR \fIyorg\fB,\fR \fIxext\fB,\fR \fIyext\fB;\fR .fe Arranges for the box to be drawn on the screen at (\fIxorg\fR, \fIyorg\fR) and to be \fIxext\fR columns by \fIyext\fR rows. \fIXorg\fR and \fIyorg\fR are clipped to be on the screen; \fIxext\fR and \fIyext\fR are clipped to make the box fit. (0, 0) is the upper left hand corner of the screen. To turn off the box, set the variable \fBWBoxActive\fR to zero. .ff \fBWin *Wboxfind ()\fR .fe Finds which window the box is in. Returns zero if the box is not contained in a visible window. If the box is contained in a visible window the current window is set to this window. If the position of the box is ambiguous (i.e. it is visibly in one window, but also within covered sections of other windows), the topmost window (the one in which it is visible) is selected. For the purpose of this function, the box is considered to be a point at its upper left corner. .ff \fBWclear (\fIw\fB,\fR \fIhowto\fB) Win *\fIw\fB; int\fR \fIhowto\fB;\fR .fe Clears window \fIw\fR. The characters in window \fIw\fR's winbuf are set to .q glass ; all of the visible characters in \fIw\fR's text buffer are set to blanks. If \fIhowto\fR is two, the entire window/visible area is cleared. If \fIhowto\fR is one, the area from the beginning of the window to the window cursor is cleared, not including the character under the window cursor. Otherwise, the area from the cursor to the end of the window is cleared, including the character under the window cursor. .ff \fBWclearline (\fIw\fB,\fR \fIhowto\fB) Win *\fIw\fB; int\fR \fIhowto\fB;\fR .fe Clears the current (cursor) line of window \fIw\fR. The characters in window \fIw\fR's winbuf are set to .q glass ; the visible characters of the current line in \fIw\fR's text buffer are set to blanks. If \fIhowto\fR is two, the entire line is cleared. If \fIhowto\fR is one, the area from the beginning of the line to the cursor is cleared, not including the character under the cursor. Otherwise, the area from the cursor to the end of the window is cleared, including the character under the cursor. .ff \fBWclose (\fIw\fB) Win *\fIw\fB;\fR .fe Closes window \fIw\fR. Its buffer, if not still in use by another window, is destroyed. In any case all of the winbuf contents and the window descriptor are destroyed. Closing the current window makes the window library choose the frontmost window as the new current window. .ff \fBWcloseall ()\fR .fe Closes all open windows, using \fBWclose\fR on each one. .ff \fBWcurdown (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Moves the window cursor in window \fIw\fR down \fIn\fR lines, possibly scrolling the window upward so as to keep the cursor within the window. This is actually a macro that calls \fBWAcursor\fR; watch out for side effects. .ff \fBWcurleft (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Moves the window cursor in window \fIw\fR left \fIn\fR characters, possibly scrolling the window to the right so as to keep the cursor within the window. This is actually a macro that calls \fBWAcursor\fR; watch out for side effects. .ff \fBWcurright (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Moves the window cursor in window \fIw\fR right \fIn\fR characters, possibly scrolling the window to the left so as to keep the cursor within the window. This is actually a macro that calls \fBWAcursor\fR; watch out for side effects. .ff \fBWcurup (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Moves the window cursor in window \fIw\fR up \fIn\fR lines, possibly scrolling the window downward so as to keep the cursor within the window. This is actually a macro that calls \fBWAcursor\fR; watch out for side effects. .ff \fBWdelchars (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Deletes \fIn\fR characters at the window cursor position in the text buffer attached to window \fIw\fR. Also deletes \fIn\fR characters from \fIw\fR's winbuf, at the window cursor. .ff \fBWdelcols (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Deletes \fIn\fR columns at the window cursor column in the text buffer attached to window \fIw\fR. Also deletes \fIn\fR characters from \fIw\fR's winbuf. In effect, calls \fBWdelchars\fR on each line within the margins. .ff \fBWdellines (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Deletes \fIn\fR lines from the text buffer attached to window \fIw\fR at \fIw\fR's window cursor row. Also deletes \fIn\fR lines from \fIw\fR's winbuf, at the window cursor. .ff \fBWfiledump (\fIfile\fB) char *\fIfile\fB;\fR .fe Dumps the current virtual screen (what the screen would look like if it were \fBWrefresh\fRed) to the named file. If the file existed previously it is overwritten. See Appendix 5 for the dump file format. .ff \fBWin *Wfind (\fIid\fB) int\fR \fIid\fB;\fR .fe Searches for the window with id \fIid\fR and if found, makes is the current one. A pointer to the found window is returned, or 0 if the specified window cannot be found. If \fIid\fR is not unique, the frontmost window with that id (i.e. the window that if not hidden would cover the others) is returned. .ff \fBWframe (\fIw\fB) Win *\fIw\fB;\fR .fe Frames window w with the default frame characters. Normally these are .ie n '+', '\-', '+', '|', '|', '+', '\-', '+' .el `+', `\-', `+', `|', `|', `+', `\-', `+' but on VT100s and some other terminals you get cute little corners and lines. See \fBWborder\fR. .ff \fBWfront (\fIw\fB) Win *\fIw\fB;\fR .fe Moves window \fIw\fR to the .q front of the screen (i.e. window \fIw\fR covers all other windows that it intersects). This applies equally to hidden windows except that hidden windows never cover others. If a hidden window that has been \fBWfront\fRed is unhidden, it will cover all other windows. .ff \fBWgetframe (\fIulc\fB,\fR \fItop\fB,\fR \fIurc\fB,\fR \fIleft\fB,\fR \fIright\fB,\fR \fIllc\fB, \fIbottom\fB,\fR \fIlrc\fB) char *\fIulc\fB, *\fItop\fB, *\fIurc\fB, *\fIleft\fB, *\fIright\fB, *\fIllc\fB, *\fIbottom\fB, *\fIlrc\fB;\fR .fe Returns in the appropriate \fBchar *\fR elements the default frame characters (the ones used by \fBWframe\fR). This information can be used to border a window on two sides, for example. See \fBWborder\fR, \fBWframe\fR, \fBWsetframe\fR. .ff \fBWhide (\fIw\fB) Win *\fIw\fB;\fR .fe Hides window \fIw\fR. .ff \fBWinschars (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Inserts \fIn\fR blanks into the current (cursor) line of the text buffer attached to window \fIw\fR at the window cursor position. Also inserts \fIn\fR blanks in \fIw\fR's winbuf, at the window cursor. .ff \fBWinscols (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Inserts \fIn\fR columns of blanks at the window cursor column in the text buffer attached to window \fIw\fR. Also inserts \fIn\fR characters in \fIw\fR's winbuf. In effect, calls \fBWinschars\fR on each line within the margins. .ff \fBWinslines (\fIw\fB,\fR \fIn\fB) Win *\fIw\fB; int\fR \fIn\fB;\fR .fe Inserts \fIn\fR blank lines into the text buffer attached to window \fIw\fR at \fIw\fR's window cursor row. Also inserts \fIn\fR lines into \fIw\fR's winbuf, at the window cursor. .ff \fBWlabel (\fIw\fB,\fR \fIlabel\fB,\fR \fIbottom\fB,\fR \fIcenter\fB) Win *\fIw\fB; char *\fIlabel\fB; int\fR \fIbottom\fB,\fR \fIcenter\fB;\fR .fe Labels the window. The characters in \fIlabel\fR (or as many as will fit) are written into the uppermost line of \fIw\fR (or the lowermost line if \fIbottom\fR is nonzero), centered if \fIcenter\fR is nonzero, and dumped into the winbuf in the current mode but with reverse video inverted (in reverse video if the current mode is normal, or vice versa). If they are not already, margins are set so that the label is off-limits to window operations. If the window has been \fBWframe\fRd or \fBWborder\fRed, the label does not touch the left and right edges of the window; otherwise it spans the entire width available. .ff \fBWin *Wlink (\fIew\fB,\fR \fIid\fB,\fR \fIxorg\fB,\fR \fIyorg\fB,\fR \fIxext\fB,\fR \fIyext\fB,\fR \fIbcols\fB,\fR \fIbrows\fB) Win *\fIew\fB; int\fR \fIid\fB,\fR \fIxorg\fB,\fR \fIyorg\fB,\fR \fIxext\fB,\fR \fIyext\fB,\fR \fIbcols\fB,\fR \fIbrows\fB;\fR .fe Creates a link to the existing window \fIew\fR. In all other respects this function is like \fBWopen\fR, except that since the new window is linked to another it shares the other's buffer. See \fBWopen\fR. .ff \fBWmove (\fIw\fB,\fR \fIxorg\fB,\fR \fIyorg\fB) Win *\fIw\fB; int\fR \fIxorg\fB,\fR \fIyorg\fB;\fR .fe Moves window \fIw\fR to coordinates (\fIxorg\fR, \fIyorg\fR). (0, 0) is the upper left corner. Zero is returned if the window is successfully moved; otherwise it did not fit at the specified coordinates. Window \fIw\fR remains at the same depth it used to be; i.e. if it still overlaps another window, the one covered will remain the same, although the area covered changes. .ff \fBWnewline (\fIw\fB,\fR \fIon\fB) Win *\fIw\fB; int\fR \fIon\fB;\fR .fe Turns auto-newline mode (CR/LF mapping) on or off for window \fIw\fR. If \fIon\fR is nonzero, auto-newline is turned on (either CR or LF will perform the actions of both), otherwise it is turned off. This is a macro; beware of side effects. .ff \fBWoncursor (\fIw\fB,\fR \fIon\fB) Win *\fIw\fB; int\fR \fIon\fB;\fR .fe Turns the window cursor for window \fIw\fR on or off. If \fIon\fR is nonzero the cursor is turned on, otherwise it is turned off. When on, it is visible as a blinking block. .ff \fBWin *Wopen (\fIid\fB,\fR \fIxorg\fB,\fR \fIyorg\fB,\fR \fIxext\fB,\fR \fIyext\fB,\fR \fIbcols\fB,\fR \fIbrows\fB) int\fR \fIid\fB,\fR \fIxorg\fB,\fR \fIyorg\fB,\fR \fIxext\fB,\fR \fIyext\fB,\fR \fIbcols\fB,\fR \fIbrows\fB;\fR .fe Returns a pointer to a new window, created with id number \fIid\fR, at (\fIxorg\fR, \fIyorg\fR) on the screen, \fIxext\fR columns by \fIyext\fR rows, with a buffer at least as big as the window but possible larger, if \fIbcols\fR and/or \fIbrows\fR are larger than \fIxext\fR and \fIyext\fR. If the creation fails for any reason, 0 is returned. The new window is always on top of all other windows (i.e. if it overlaps another, it covers the other). The actual value of \fIid\fR is ignored; it's just a value for \fBWfind\fR to find, or for the programmer's use. The new window is made the current window. .ff \fBWputc (\fIc\fB,\fR \fIw\fB)\fR\** .(f \**Again, the window parameter comes \fIlast\fR. .)f \fBchar\fR \fIc\fB; Win *\fIw\fB;\fR .fe Puts a character (\fIc\fR) to the text buffer attached to window \fIw\fR at the window cursor, and advances the window cursor, as described in the section on printing characters. .ff \fBWputs (\fIs\fB,\fR \fIw\fB) char *\fIs\fB; Win *\fIw\fB;\fR .fe Puts a C style (null terminated) string into the text buffer attached to window \fIw\fR, by using \fBWputc\fR on each character in \fIs\fR. .ff \fBWread (\fIw\fB,\fR \fIcharonly\fB,\fR \fIwinonly\fB) Win *\fIw\fB; int\fR \fIcharonly\fB,\fR \fIwinonly\fB;\fR .fe Reads back a character and (unless \fIcharonly\fR is nonzero) its mode from window \fIw\fR at the \fIw\fR's window cursor position. If the character displayed would come from the winbuf (i.e. the winbuf does not contain glass at the window cursor position), the character is fetched from there. If the character displayed would come from the text buffer, the character is fetched from there unless \fIwinonly\fR is set (when it will come from the winbuf). In any case, the window cursor is subsequently advanced with wraparound from the last character of the last line to the first character of the first line. See \fBWCHAROF\fR and \fBWMODEOF\fR. .ff \fBWrefresh (\fISkipInputCheck\fB) int\fR \fISkipInputCheck\fB;\fR .fe Updates the physical screen. If \fISkipInputCheck\fR is zero, input is checked for before anything is done, and if input is pending nothing is done. (Input is defined as \*(lqthe number of characters that can be read from file descriptor 0 is nonzero.\*(rq) Normally, \fISkipInputCheck\fR should be given as zero for interactive programs, so that they don't waste time updating the display if it's about to change anyway. If \fISkipInputCheck\fR is nonzero input will not be checked for and the screen will be updated regardless of pending input.\** .(f \**I'm not sure what happens if input is already known to be pending. .)f .pp Unless the variable \fBScreenGarbaged\fR has been set, the update will be done by changing as few characters on the physical screen as possible. \fBScreenGarbaged\fR should be set if the screen has been written to by some external process. Often in an interactive program some key (e.g. control-L) will simply set \fBScreenGarbaged\fR and then call \fBWrefresh\fR. \fBScreenGarbaged\fR is automatically cleared by \fBWrefresh\fR. .ff \fBWrelscroll (\fIw\fB,\fR \fIrows\fB,\fR \fIcols\fB,\fR \fIcwin\fB) Win *\fIw\fB; int\fR \fIrows\fB,\fR \fIcols\fB,\fR \fIcwin\fB;\fR .fe Moves window \fIw\fR over its buffer. The window is moved \fIrows\fR lines forward (or backward if \fIrows\fR is negative) and \fIcols\fR columns to the right (or left if \fIcols\fR is negative) over its buffer. The window can never be moved \*(lqoff the edge\*(rq of the buffer to the left or right. If the window is moved past the top or bottom edge of the buffer, however, the buffer is scrolled (as in \fBWBscroll\fR) as necessary to keep window \fIw\fR within it. If \fIcwin\fR is set, the cursor \*(lqsticks to\*(rq the window rather than to the buffer; that is, the cursor's position relative to the window remains the same. Otherwise the cursor sticks to the buffer; that is, the cursor's position relative to the buffer remains the same\**, or in other words, the cursor stays over the same text it used to be over. .(f \**If possible. The cursor is constrained to remain within the inner margins of the window. .)f .ff \fBWretroline (\fIw\fB,\fR \fImode\fB,\fR \fIinwin\fB) Win *\fIw\fB;\fR .fe Sets all of the characters in the current (cursor) line of the window \fIw\fR to the specified \fImode\fR. \fIInwin\fR specifies whether the mode-paint is to be applied to the text buffer (if zero) or to the window buffer (if nonzero). If applied to the text buffer, all the characters in the text buffer attached to window \fIw\fR at its buffer cursor line will be painted. If applied to the winbuf, the characters in the winbuf (be they glass or normal) will be painted with mode \fImode\fR. Painting the winbuf results in \*(lqtinted glass\*(rq; that is, if the window is scrolled, the mode applies to a new line in the text buffer. Painting in the buffer results in modes that \*(lqstick to\*(rq the text; if the window is scrolled, the mode moves with the characters. This function is designed for menus, where the current line of the menu would be in reverse video, for example. .ff \fBWscreensize (\fIrows\fB,\fR \fIcols\fB) int *\fIrows\fB, *\fIcols\fB;\fR .fe Sets *\fIrows\fR to the number of rows on the physical screen and *\fIcols\fR to the number of columns. These values specify the largest legal size for windows and the box. .ff \fBWscroll (\fIw\fB) Win *\fIw\fB;\fR .fe Scrolls window \fIw\fR by its popup (normally one). If the window's popup is zero it rolls the cursor over from the bottom line to the top, and clears each line as it goes along. This is much faster on some terminals, but is at least a little confusing. This function is mainly for internal use, but may be called if desired. Normally \fBWrelscroll\fR (which does the real work for \fBWscroll\fR anyway) should be called. .ff \fBWsetbuf (\fIw\fB,\fR \fIbcols\fB,\fR \fIbrows\fB) Win *\fIw\fB; int\fR \fIbcols\fB,\fR \fIbrows\fB;\fR .fe Sets the size of the text buffer attached to window \fIw\fR. The buffer size is made \fBat least\fR \fIbrows\fR rows by \fIbcols\fR columns. Text buffers never shrink, so this is really a \*(lqgrow text buffer\*(rq call. .ff \fBWsetframe (\fIulc\fB,\fR \fItop\fB,\fR \fIurc\fB,\fR \fIleft\fB,\fR \fIright\fB,\fR \fIllc\fB,\fR \fIbottom\fB,\fR \fIlrc\fB) char\fR \fIulc\fB,\fR \fItop\fB,\fR \fIurc\fB,\fR \fIleft\fB,\fR \fIright\fB,\fR \fIllc\fB,\fR \fIbottom\fB,\fR \fIlrc\fB;\fR .fe Sets the default frame characters (the ones used by \fBWframe\fR). This function is probably not very useful, but is the only way to change the default frames. .ff \fBWsetmargins (\fIw\fB,\fR \fIinxorg\fB,\fR \fIinyorg\fB,\fR \fIinxext\fB,\fR \fIinyext\fB) Win *\fIw\fB; int\fR \fIinxorg\fB,\fR \fIinyorg\fB,\fR \fIinxext\fB,\fR \fIinyext\fB;\fR .fe Sets the margins to the specified values. \fIInxorg\fR and \fIinyorg\fR specify at what x and y values (relative to the window origin at (0, 0)) the inner area begins; \fIinxext\fR and \fIinyext\fR specify how many characters in each direction are accessible. The inner area is set to come from the text buffer, and the outer area to come from the window buffer. If the margins are set to the full size of the window, subsequent \fBWlabel\fR calls will use the leftmost and rightmost characters, unless \fBWframe\fR or \fBWborder\fR is called. (See \fBWborder\fR, \fBWlabel\fR.) .ff \fBWsetmode (\fIw\fB,\fR \fIm\fB) Win *\fIw\fB; int\fR \fIm\fB;\fR .fe Sets the mode for window \fIw\fR. \fIM\fR is any combination of the constants WBOLD, WULINE, WBLINK, and WINVERSE, which represent (respectively) bold, underscore, blink, and inverse video. The values can be added or boolean ored for combinations. This is a macro; beware of side effects. .ff \fBWsetpopup (\fIw\fB,\fR \fIp\fB) Win *\fIw\fB; int\fR \fIp\fB;\fR .fe Sets the popup for window \fIw\fR to \fIp\fR. The popup value is the number of lines to scroll upward when the cursor moves off the bottom of the window via a newline (or carriage return if CR/LF mapping is on). If the popup value is zero, the cursor moves to the top of the window and clears a line at a time, instead of scrolling. This is faster on some terminals, but can be confusing. This is a macro, beware of side effects. .ff \fBWsize (\fIw\fB,\fR \fIxext\fB,\fR \fIyext\fB) Win *\fIw\fB; int\fR \fIxext\fB,\fR \fIyext\fB;\fR .fe Sets the size of window \fIw\fR to \fIxext\fR columns by \fIyext\fR rows. The margins are set to make the entire winbuf the inside area, and the entire winbuf is set to glassy blanks. .ff \fBWunhide (\fIw\fB) Win *\fIw\fB;\fR .fe Unhides window \fIw\fR. .ff \fBWwrap (\fIw\fB,\fR \fIon\fB) Win *\fIw\fB; int\fR \fIon\fB;\fR .fe Turns autowrap on or off for window \fIw\fR. If \fIon\fR is nonzero, autowrap is turned on, otherwise it is turned off. See the section on printing characters. .ff \fBbcopy (\fIfrom\fB,\fR \fIto\fB,\fR \fIcount\fB) char *\fIfrom\fB, *\fIto\fB; int\fR \fIcount\fB;\fR .fe Block copy of \fIcount\fR bytes (0 <= \fIcount\fR <= 65535) from address \fIfrom\fR to address \fIto\fR. This is used internally and is provided only because it's a fast block copy. .\" ********************** Switch back to normal point size .nr pp \n(Ns .sz \n(Ns .\" ********************** End of main text; begin appendicies .if \n(Vv=1 .tm Done with function list (about 2/3 done)! .bp .sp 4 \fIAcknowledgements\fR .pp The original display optimization algorithm was written by James Gosling [Gosling 81]. An earlier version of the window package was written by Rich Wood [Wood 82]. The complaints of Mark Weiser and Randy Trigg inspired me to write this version. .\" ********************** References .if \\n($m=1 .bp \" start new page unless in 2 column mode .uh "REFERENCES" .in 5 .ls 1 .de ][ .if \\$1>5 .tm Bad arg to [] .sp .ti 0 .\" if !"\\*([F"" [\\*([F]\t\c this is the way it used to be .if !"\\*([F"" [\\*([F] \" these two lines are to get a line break after flag .br \.[\\$1 .. . \" ******* stuff for references .de [< .]< .. .de ]< .in 5 .ta 5 .. .de [> .]> .. .de ]> .sp .. .de [- .]- .. .de ]- .rm [A [B [C [D [E [I [N [O [P [Q [R [V [T [W .. . . .de [0 \" other .if !"\\*([Q"" \\*([Q, .if !"\\*([W"$$ignoreauthor" .if !"\\*([A"" \\*([A, .if !"\\*([T"" \\*([T\c .if !"\\*([T"" .if !"\\*([O"" ,\ .ie !"\\*([O"" \\*([O .el .if !"\\*([T"" \&. .if !"\\*([D"" \\*([D. .. .de [1 \" journal article .if !"\\*([Q"" \\*([Q, .if !"\\*([W"$$ignoreauthor" .if !"\\*([A"" \\*([A, .if !"\\*([T"" \\*([o\\*([T,\\*([c .ul .ie !"\\*([V"" \fI\\*([J \fB\\*([V\fR, .el \fI\\*([J\fR, .if !"\\*([N"" \\*([N, .if !"\\*([E"" ed. \\*([E, .if !"\\*([C"" \\*([C, .if !"\\*([P"" \{\ .ie \\n([P>0 pp.\& .el p.\& \\*([P,\} .if !"\\*([I"" .if "\\*([R"" \\*([I, \\*([D. .if !"\\*([O"" \\*([O .. .de [2 \" book .if !"\\*([Q"" \\*([Q, .if !"\\*([W"$$ignoreauthor" .if !"\\*([A"" \\*([A, .if !"\\*([E"" \\*([E, (ed.) .ul \\*([T, \\*([I, .if !"\\*([C"" \\*([C, \\*([D. .if !"\\*([O"" \\*([O .. .de [3 \" article in book .if !"\\*([Q"" \\*([Q, .if !"\\*([W"$$ignoreauthor" .if !"\\*([A"" \\*([A, \\*([o\\*([T,\\*([c .if !"\\*([P"" pp. \\*([P in .ul \\*([B, .if !"\\*([E"" ed. \\*([E, .if !"\\*([I"" \\*([I, .if !"\\*([C"" \\*([C, \\*([D. .if !"\\*([O"" \\*([O .. .de [4 \" report .if !"\\*([Q"" \\*([Q, .if !"\\*([W"$$ignoreauthor" .if !"\\*([A"" \\*([A, \\*([o\\*([T,\\*([c \\*([R\c .if !"\\*([G"" \& (\\*([G)\c \&, .if !"\\*([I"" \\*([I, .if !"\\*([C"" \\*([C, \\*([D. .if !"\\*([O"" \\*([O .. .de [5 \" tm style .if !"\\*([Q"" \\*([Q, .if !"\\*([W"$$ignoreauthor" .if !"\\*([A"" \\*([A, \\*([T, .ie \\n(TN \\*([M. .el Bell Laboratories internal memorandum (\\*([D). .. .\" I think I can leave this out for now. 6/12/81 .\" .[ .\" $LIST$ .\" .] .]< .\"Gosling.J.-1981-12-1 .ds [F Gosling 81 .]- .ds [A Gosling, J. .ds [T UNIX EMACS .ds [R Dept. of Computer Science, Carnegie-Mellon Univ. TR .ds [D Dec. 1981 .ds [L Gosling 81 .nr [T 0 .nr [A 1 .nr [O 0 .][ 4 tech-report .\"Joy.W.N.-1981-06-2 .ds [F Joy et al 81 .]- .ds [A Joy, W.N. .as [A ", Farby, R.S. .as [A ", and Sklower, K. .ds [T UNIX Programmer's Manual .ds [I Dept. of Electrical Engineering and Computer Science, Univ. of California .ds [C Berkeley, CA .ds [D June 1981 .ds [L Joy et al 81 .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .\"Wood.R.J.-1982-05-3 .ds [F Wood 82 .]- .ds [L Wood 82 .ds [A Wood, R.J. .ds [T A Window Based Display Management System .ds [R Univ. of Maryland, TR (in preparation) .ds [D May 1982 .nr [T 0 .nr [A 1 .nr [O 0 .][ 4 tech-report .]> .ls \n(Ls .AP "Technical description" .pp These are listings of the files that are to be #\fIinclude\fRd to use the window library. The first file should be included in any program using windows; it includes the second file automatically. .sp .ce \fB\fR .sp .nf .ls 1 .sz -2 .ta \w'#define 'u +\w'WWtoBcursor(w) 'u +4i #include #define Wwrap(w,on) ((w)\->w_status &= ~WWRAPOFF, \\ (w)\->w_status |= (on)?0:WWRAPOFF, 0) #define Wnewline(w,on) ((w)\->w_status &= ~WNEWLINE, \\ (w)\->w_status |= (on)?WNEWLINE:0, 0) #define Wsetmode(w,m) ((w)\->w_mode &= ~MODEMASK, \\ (w)\->w_mode |= m & MODEMASK, 0) #define Wsetpopup(w,p) ((w)\->w_popup = (p), 0) #define Wcurup(w,n) (WAcursor (w, \\ (w)\->w_cursor.row+(w)\->w_bstart.row\-(n), \\ (w)\->w_cursor.col+(w)\->w_bstart.col)) #define Wcurdown(w,n) (WAcursor (w, \\ (w)\->w_cursor.row+(w)\->w_bstart.row+(n), \\ (w)\->w_cursor.col+(w)\->w_bstart.col)) #define Wcurleft(w,n) (WAcursor (w, \\ (w)\->w_cursor.row+(w)\->w_bstart.row, \\ (w)\->w_cursor.col+(w)\->w_bstart.col\-(n))) #define Wcurright(w,n) (WAcursor (w, \\ (w)\->w_cursor.row+(w)\->w_bstart.row, \\ (w)\->w_cursor.col+(w)\->w_bstart.col+(n))) #define WWtoBcursor(w) (WAcursor (w, \\ (w)\->w_textbuf\->b_cursor.row\-(w)\->IYO, \\ (w)\->w_textbuf\->b_cursor.col\-(w)\->IXO)) /* NOTE: THESE MACROS MAY BE SYSTEM DEPENDENT */ #define WCHAROF(c) ((c)&0377) #define WMODEOF(c) ((c)>>NBPB) /* Function types for non-integer functions */ Win *Wopen (), *Wlink (), *Wfind (), *Wboxfind (); .sz +2 .ls .fi .bp .ce \fB\fR .sp .nf .ls 1 .sz -2 .ta 12n 24n 36n 48n 60n 72n #define NBPB 8 /* Number of bits per byte */ union chr { struct { char ch; /* NOTE: this is known to be low byte */ char mode; } ch_two; short ch_all; }; /* ch_all is set to ' ' or (' '|(WBUF<