Programmer’s Reference Manual for Curses on the Sun Workstation Sun Microsystems, Inc. • • Mountain View, CA 94043 • 415-960-1300 Part Wo: $00*1 168-0! Revision A of !5 May, 1985 2550 Garcia Avenue Acknowledgements This manual was derived from the paper entitled Curses — A Screen Updating and Cursor Movement Library Package by Ken Arnold, University of California at Berkeley. This package would not exist without the work of Bill Joy, who, in writing his editor, created the capability to generally describe terminals, wrote the routines which read this database, and, most importantly, those which implement optimal cursor movement, which routines were simply lifted nearly intact. Doug Merritt and Kurt Shoens also were extremely important, as were both wil- ling to waste time listening to Ken Arnold rant and rave. The help and/or support of Ken Abrams, Alan Char, Mark Horton, and Joe Kalash, was, and is, also greatly appreciated. Copyright ® 1985 by Sun Microsystems. This publication is protected by Federal Copyright Law, with all rights reserved. No part of this publication may be reproduced, stored in a retrieval system, translated, transcribed, or transmit- ted, in any form, or by any means manual, electric, electronic, electro-magnetic, mechanical, chemical, optical, or otherwise, without prior explicit written permission from Sun Microsystems. — Ill — Contents Chapter 1 Introduction 1-1 Chapter 2 Variables 2-1 Chapter 3 Programming Curses 3-1 Chapter 4 Cursor Motion Optimization: Standing Alone 4-1 Chapter 5 Curses Functions 6-1 Appendix A Capabilities from termcap A-l Appendix B The WINDOW structure B-l Appendix C Examples C-l Contents Chapter 1 Introduction 1-1 1.1. Overview 1-1 1.2. Terminology 1-1 1.2.1. Cursor Addressing Conventions 1-2 1.3. Compiling Things 1-2 1.4. Screen Updating 1-3 1.5. Naming Conventions 1-3 Chapter 2 Variables 2-1 Chapter 3 Programming Curses 3-1 3.1. Starting up 3-1 3.2. The Nitty-Gritty 3-1 3.2.1. Output 3-1 3.2.2. Input 3-2 3.2.3. Miscellaneous 3-2 3.3. Finishing up 3-2 Chapter 4 Cursor Motion Optimization: Standing Alone 4-1 4.1. Terminal Information 4-1 4.2. Movement Optimizations, or, Getting Over Yonder 4-2 Chapter 5 Curses Functions 5-1 5.1. Output Functions 5-1 5.1.1. addch and waddch — Add Character to Window 5-1 5.1.2. addstr and waddstr — Add String to Window 5-1 5.1.3. box — Draw Box Around Window 5-2 5.1.4. clear and wclear — Reset Window 5-2 5.1.5. clearok — Set Clear Flag 5-2 5.1.6. clrtobot and wclrtobot — Clear to Bottom 5-2 5.1.7. clrtoeol and wclrtoeol — Clear to End of Line 5-3 5.1.8. delch and wdelch — Delete Character 5-3 5.1.9. deleteln and wdeleteln — Delete Current Line 5-3 5.1.10. erase and werase — Erase Window 5-3 5.1.11. insch and winsch — Insert Character 5-3 5.1.12. insert In and winsertln — Insert Line 5-4 5.1.13. move and wmove — Move 5-4 — vn — 5.1.14. overlay — Overlay Windows 5-4 5.1.15. overwrite — Overwrite Windows 5-4 5.1.16. printw and vprintw — Print to Window 5-5 5.1.17. refresh and wrefresh — Synchronize 5-5 5.1.18. standout and wstandout — Put Characters in Standout Mode 5-5 5.2. Input Functions 5-6 5.2.1. crmode and nocrmode — Set or Unset from cbreak mode 5-6 5.2.2. echo and noecho — Turn Echo On or Off 5-6 5.2.3. getch and wgetch — Get Character from Terminal 5-6 5.2.4. getstr and wgetstr — Get String from Terminal 5-6 5.2.5. raw and noraw — Turn Raw Mode On or Off 5-7 5.2.6. scanw and wscanw — Read String from Terminal 5-7 5.3. Miscellaneous Functions 5-7 5.3.1. delwin — Delete a Window 5-7 5.3.2. endwin — Finish up Window Routines 5-7 5.3.3. getyx — Get Current Coordinates 5-8 5.3.4. inch and winch — Get Character at Current Coordinates 5-8 5.3.5. initscr — Initialize Screen Routines 5-8 5.3.6. leaveok — Set Leave Cursor Flag 5-8 5.3.7. longname — Get Full Name of Terminal 5-9 5.3.8. mvwin — Move Home Position of Window 5-9 5.3.9. newwin — Create a New Window 5-9 5.3.10. nl and nonl — Turn Newline Mode On or Off 5-9 5.3.11. scrollok — Set Scroll Flag for Window 5-10 5.3.12. touchwin — Indicate Window Has Been Changed 5-10 5.3.13. subwin — Create a Subwindow 5-10 5.3.14. unctrl — Return Representation of Character 5-10 5.4. Details 5-10 5.4.1. gettmode — Get tty Statistics 5-11 5.4.2. mvcur — Move Cursor 5-11 5.4.3. scroll — Scroll Window 5-11 5.4.4. savetty and resetty — Save and Reset tty Flags 5-11 5.4.5. setterm — Set Terminal Characteristics 5-11 5.4.6. tstp 5-12 Appendix A Capabilities from termcap A-l A.l. Disclaimer A-l A. 2. Overview A-l A. 3. Variables Set By setterm() A-2 A. 4. Variables Set By gettmode() A-3 Appendix B The WINDOW structure B-l Appendix C Examples C-l C.l. Screen Updating C-l C.1.1. Twinkle C _1 C.1.2. Life C_4 C.2. Motion optimization C _7 C.2.1. Twinkle qjj — ix — Chapter 1 Introduction CURSES is a Library Package for: • Updating a screen with reasonable optimization, • Getting input from the terminal in a screen-oriented fashion, and • Moving the cursor optimally from one point to another, independent of the two previous func- tions. These routines all use the termcap database to describe the capabilities of the terminal. 1.1. Overview In making available the generalized terminal descriptions in termcap, much information was made available to the programmer, but little work was taken out of one’s hands. CURSES helps the programmer perform the required functions, those of movement optimization and optimal screen updating, without doing any of the dirty work, and (hopefully) with nearly as much ease as is necessary to simply print or read things. The CURSES package is split into three parts: 1. Screen updating without user input; 2. Screen updating with user input; and 3. Cursor motion optimization. It is possible to use the motion optimization without using either of the other two, and screen updating and input can be done without any programmer knowledge of the motion optimization, or indeed the termcap database itself. 1.2. Terminology In this document, the following terminology is used with reasonable consistency: Revision A of 15 May 1985 1-1 Introduction Curses Reference Manual Table 1-1: Description of Terms Term Description window An internal representation containing an image of what a section of the terminal screen may look like at some point in time. This subsection can either encompass the entire terminal screen, or any smaller portion down to a single character within that screen. Note that the term window is used elsewhere in the Sun sys- tem manuals when describing the window management packages for driving the bitmapped screens. CURSES windows bear little, if any, resemblance to the win- dow system concepts. terminal Sometimes called terminal screen. The package’s idea of what the terminal’s screen currently looks like, that is, what the user sees now. This is a special screen: screen This is a subset of windows which are as large as the terminal screen, that is, they start at the upper left hand corner and encompass the lower right hand corner. One of these, stdscr, is automatically provided for the programmer. 1.2.1. Cursor Addressing Conventions The CURSES library routines address positions on a screen with the y coordinate first and the x coordinate second. This follows the convention of most terminals that address the screen in row, column order. The reader should note this convention. 1.3. Compiling Things To use the CURSES library, it is necessary to have certain types and variables defined. There- fore, the programmer must have a line: #include at the top of the program source. The header file needs to include , so one should not do so oneself*. Also, compilations should have the following form: tutorial% cc [ C-compiler options ] filename . . . — lcursea — Itermllb 1 The screen package also uses the Standard I/O library, so includes . It is redun- dant (but harmless) for the programmer to include too. 1-2 Revision A of 15 May 1985 Curses Reference Manual Introduction 1.4. Screen Updating To update the screen optimally, it is necessary for the routines to know what the screen currently looks like and what the programmer wants it to look like next. For this purpose, a data type (structure) named WINDOW is defined which describes a window image to the rou- tines, including its starting position on the screen (the (y, x) coordinates of the upper left hand corner) and its size. One of these (called cursor for current screen) is a screen image of what the terminal currently looks like. Another screen (called stdscr, for standard screen ) is provided by default to make changes on. A window is a purely internal representation. It is used to build and store a potential image of a portion of the terminal. It doesn’t bear any necessary relation to what is really on the terminal screen. It is more like an array of characters on which to make changes. When one has a window which describes what some part the terminal should look like, the rou- tine re fresh () (or wre fresh () if the window is not stdscr ) is called, re fresh () makes the terminal, in the area covered by the window, look like that window. Note, therefore, that changing something on a window does not ‘change the terminal’. Actual updates to the terminal screen are made only by calling re fresh () or wre fresh (). This allows the programmer to maintain several different ideas of what a portion of the terminal screen should look like. Also, changes can be made to windows in any order, without regard to motion efficiency. Then, at will, the programmer can effectively say ‘make it look like this,’ and let the package worry about the best way to do this. 1.5. Naming Conventions As hinted above, the routines can use several windows, but two are automatically given: cursor, which knows what the terminal looks like, and stdscr , which is what the programmer wants the terminal to look like next. The user should never really access cursor directly. Changes should be made to the appropriate screen, and then the routine refresh () (or wrefreshQ) should be called. Many functions are set up to deal with stdscr as a default screen. For example, to add a charac- ter to stdscr, one calls addch() with the desired character. If a different window is to be used, the routine waddchQ (for window-specific addchQ) is provided 2 . This convention of prepending function names with a ‘w’ when they are to be applied to specific windows is con- sistent. The only routines which do not do this are those to which a window must always be specified. To move the current (y, x) coordinates from one point to another, the routines move () and wmove () are provided. However, it is often desirable to first move and then perform some I/O operation. To avoid clumsiness, most I/O routines can be preceded by the prefix ‘mv’ and the desired (y, x) coordinates then can be added to the arguments to the function. For example, the calls move (y, x) ; addch (ch) ; 2 Actually, addch () is really a ^define macro with arguments, as are most of the "functions" which deal with etdeer as a default. Revision A of 15 May 1985 1-3 Introduction Curses Reference Manual can be replaced by mvaddch(y, x, ch) ; and wmove (win, y, x) ; waddchfwin, ch) ; can be replaced by mvwaddch (win , y, x, ch) ; Note that the window description pointer (win) comes before the added (y, x) coordinates. If such pointers are needed, they are always the first parameters passed. 1-4 Revision A of 15 May 1985 Chapter 2 Variables Many variables that describe the terminal environment are available to the programmer. They are: Table 2-1: Variables to Describe the Terminal Environment Type Name Description WINDOW * cursor current version of the screen (terminal screen). WINDOW * stdscr standard screen. Most updates are done here. char * Def _term default terminal type if type cannot be determined bool My_term use the terminal specification in Def_term as terminal, ir- relevant of real terminal type char * ttytype full name of the current terminal. int LINES number of lines on the terminal int COLS number of columns on the terminal int ERR error flag returned by routines on a fail. int OK error flag returned by routines when things go right. There are also several ^define constants and types which are of general usefulness: reg storage class ‘register’ (for example, reg irvt i;) bool boolean type, actually a ‘char’ (for example, bool doneit;) TRUE boolean ‘true’ flag (1). FALSE boolean ‘false’ flag (0). Revision A of 15 May 1985 2-1 Chapter 3 Programming Curses This is a description of how to actually use the screen package. In it, we assume all updating, reading, and so on, is applied to stdscr. All instructions will work on any window, by changing the function name and parameters as mentioned in chapter 1. 3.1. Starting up To use the screen package, the routines must know about terminal characteristics, and the space for cursor and stdscr must be allocated. These functions are performed by initscr () . Since it must allocate space for the windows, it can overflow core when attempting to do so. On this rather rare occasion, initscr () returns ERR. initscr () must always be called before any of the routines which affect windows are used. If it is not, the program will core dump as soon as either cursor or stdscr are referenced. However, it is usually best to wait to call it until after you are sure you will need it, like after checking for startup errors. Terminal status changing routines like nl () and crmode () should be called after initscr () . Now that the screen windows have been allocated, you can set them up for the run. If you want to, say, allow the window to scroll, use scrollokQ . If you want the cursor to be left after the last change, use leaveokQ. If this isn’t done, refresh () moves the cursor to the window’s current (y, x) coordinates after updating it. New windows of your own can be created, too, by using the functions newwin () and subwin () . del win () gets rid of old windows. If you wish to change the official size of the terminal by hand, just set the variables LINES and COLS to be what you want, and then call initscr () . This is best done before, but can be done either before or after, the first call to initscr () , as it always deletes any existing stdscr and/or cursor before creating new ones. 3.2. The Nitty-Gritty 3.2.1. Output Now that we have set things up, we will want to actually update the terminal. The basic func- tions used to change what appears on a window are addch() and move () . addchQ adds a character at the current (y, x) coordinates, returning ERR if it would cause the window to ille- gally scroll, that is, printing a character in the lower right-hand corner of a terminal which Revision A of 15 May 1985 3-1 Programming Curses Curses Reference Manual automatically scrolls if scrolling is not allowed, move () changes the current (y, x) coordinates to whatever you want them to be. It returns ERR if you try to move off the window when scrolling is not allowed. As mentioned above, you can combine the two into mv addch () to do both things in one fell swoop. The other output functions, such as addstr () and printv () , all call addch () to add charac- ters to the window. After you have put on the window what you want there, when you want the portion of the ter- minal covered by the window to be made to look like it, you must call refresh () . To optimize finding changes, re fresh () assumes that any part of the window not changed since the last re fresh () of that window has not been changed on the terminal, that is, that you have not refreshed a portion of the terminal with an overlapping window. If this is not the case, the rou- tine touchwinQ is provided to make it look like the entire window has been changed, thus making re fresh () check the whole subsection of the terminal for changes. If you call wre fresh () with cursor , it will make the screen look like cursor thinks it looks like. This is useful for implementing a command to redraw the screen in case it get messed up. 3.2.2. Input Input is essentially a mirror image of output. The complementary function to addch () is getch () which, if echo is set, calls addch () to echo the character. Since the screen package needs to know what is on the terminal at all times, if characters are to be echoed, the tty must be in raw or cbreak mode. If it is not, getch () sets it to be cbreak, reads in the character, and then resets the mode of the terminal to what it was before the call. 3.2.3. Miscellaneous All sorts of functions exist for maintaining and changing information about the windows. For the most part, the descriptions in section 5.4. should suffice. 3.3. Finishing up To do certain optimizations, and, on some terminals, to work at all, some things must be done before the screen routines start up. These functions are performed in getttmode () and setterm(), which are called by initscr (). To clean up after the routines, the routine endwin () is provided. It restores tty modes to what they were when initscr () was first called. Thus, anytime after the call to initscr, endwin () should be called before exiting. 3-2 Revision A of 15 May 1985 Chapter 4 Cursor Motion Optimization: Standing Alone It is possible to use the cursor optimization functions of this screen package without the over- head and additional size of the screen updating functions. The screen updating functions are designed for uses where parts of the screen are changed, but the overall image remains the same. Certain other programs will find it difficult to use these functions in this manner without consid- erable unnecessary program overhead. For such applications, such as some l crt hacks' 3 and optimizing caf(l)-type programs, all that is needed is the motion optimizations. This, therefore, is a description of what goes on at the lower levels of this screen package. The descriptions assume a certain amount of familiarity with programming problems and some finer points of C. None of it is terribly difficult, but you should be forewarned. 4.1. Terminal Information To use a terminal’s features to the best of a program’s abilities, you must first know what they are. The termcap database describes these, but a certain amount of decoding is necessary, and there are, of course, both efficient and inefficient ways of reading them in. The algorithm that CURSES uses is taken from vi and is efficient. It reads them into a set of variables whose names are two uppercase letters with some mnemonic value. For example, HO is a string which moves the cursor to the "home" position 4 . As there are two types of variables involving ttys, there are two routines. The first, gettmode () , sets some variables based upon the tty modes accessed by gtty( 2) and atty( 2). The second, setterm(), does a larger task by reading in the descriptions from the termcap database. This is the way these routines are used by initscr () : if > (isatty (O) ) { gettmode () ; if (sp=getenv ("TERM") ) setterm(sp) ; else setterm(Def_term) ; puts (TI) ; puts (VS) ; s Graphics programs designed to run on character-oriented terminals. 4 These names are identical to those variables used in the /ete/termeap database to describe each capa- bility. See Appendix A for a complete list of those read, and to . If the mapping is not done, refresh () can do more optimi- zation, so it is recommended, but not required, that it be turned off. Revision A of 15 May 1985 5-9 Curses Functions Curses Reference Manual 5.8.11. scrollok — Set Scroll Flag for Window scrollok (win, boolf) t WINDOW ♦win; bool boolf; Set the scroll flag for the given window. If boolf is FALSE, scrolling is not allowed. This is its default setting. 5.3.12. touchwin — Indicate Window Has Been Changed touchwin (win) WINDOW +win ; Make it appear that the every location on the window has been changed. This is usually only needed for refreshes with overlapping windows. 5.8.18. subwin — Create a Subwindow WINDOW ♦ subwin (win, lines, cols, begin_y, begin_x) WINDOW ♦win; int lines, cols, begin_y, begin_x; Create a new window with lines lines and cols columns starting at position ( begin_y , begxn_x ) in the middle of the window win. This means that any change made to either window in the area covered by the subwindow is made on both windows. begin_y, begin_x are specified relative to the overall screen, not the relative (0, 0) of win. If either lines or cols is 0 (zero), that dimen- sion is set to ( LINES — begin_y) or ( COLS — begin_x) respectively. 5.8.14 • unctrl — Return Representation of Character unctrl(ch) f char ch ; This is actually a debug function for the library, but it is of general usefulness. It returns a string which is a representation of ch. Control characters become their upper-case equivalents preceded by a Other letters stay just as they are. 5.4. Details 5-10 Revision A of 15 May 1985 Curses Reference Manual Curses Functions 5.4.I. gettmode — Get tty Statistics gettmod© () Get the tty stats. This is normally called by initscr () . 5.4-2. mvcur — Move Cursor mvcur(lasty, lastx, newy, newx) int lasty, lastx, newy, newx; Moves the terminal’s cursor from (tasty, lastx) to (newy, newx) in an approximation of optimal fashion. It is possible to use this optimization without the benefit of the screen routines. With the screen routines, this should not be called by the user, move () and re fresh () should be used to move the cursor position, so that the routines know what’s going on. 5.4.8. scroll — Scroll Window scroll (win) WINDOW *win; Scroll the window upward one line. This is normally not used by the user. 5.4.4. savetty and resetty — Save and Reset tty Flags savetty() t resetty () f savetty () saves the current tty characteristic flags, resetty () restores them to what savetty () stored. These functions are performed automatically by initscr () and endwin () . 5.4.5. setterm — Set Terminal Characteristics setterm (name) char *name ; Set the terminal characteristics to be those of the terminal named name. This is normally called by initscr () . Revision A of 15 May 1985 5-11 Curses Functions Curses Reference Manual 5 .^. 6 . tstp tstp () If the new ffy(4) driver is in use, this function saves the current tty state and then puts the pro- cess to sleep. When the process gets restarted, it restores the tty state and then calls vre fresh (cursor) to redraw the screen, initscr () sets the signal SIGTSTP to trap to this routine. 5-12 Revision A of 15 May 1985 Appendix A Capabilities from termcap A.l. Disclaimer The description of terminals is a difficult business, and we only attempt to summarize the capa- bilities here. For a full description see the termcap(5) manual pages. A.2. Overview Capabilities from termcap are of three kinds: string valued options, numeric valued options, and boolean options. The string valued options are the most complicated, since they may include padding information. Intelligent terminals often require padding on intelligent operations at high (and sometimes even low) speed. This is specified by a number before the string in the capability, and has meaning for the capabilities which have a P at the front of their comment. This normally is a number of milliseconds to pad the operation. In the current system which has no true programmable delays, we do this by sending a sequence of pad characters (normally nulls, but can be changed — specified by PC). In some cases, the pad is better computed as some number of milliseconds times the number of affected lines (to the bottom of the screen usually, except when terminals have insert modes which will shift several lines.) This is specified as, for example, 12« before the capability, to say 12 milliseconds per affected whatever (currently always line). Capabilities where this makes sense say P* . Revision A of 15 May 1985 A-l Capabilities from termcap Curses Reference Manual A.3. Variables Set By setterm() Table A-l: Variables Set by setterm() Type Name variables set by settermf) Pad Description char * AL P* Add new blank Line bool AM Automatic Margins char * BC Back Cursor movement bool BS Backspace works char * BT P Back Tab bool CA Cursor Addressable char * CD P* Clear to end of Display char * CE P Clear to End of line char * CL P* CLear screen char * CM P Cursor Motion char * DC P* Delete Character char * DL P* Delete Line sequence char * DM Delete Mode (enter) char * DO DOwn line sequence char * ED End Delete mode bool EO can Erase Overstrikes with char * El End Insert mode char * HO HOme cursor bool HZ HaZeltine ~ braindamage char * IC P Insert Character bool IN Insert-Null blessing char * IM enter Insert Mode (IC usually set, too) char * IP P* Pad after char Inserted using IM+IE char * LL quick to Last Line, column 0 char * MA Ctrl character MAp for cmd mode bool MI can Move in Insert mode bool NC No Cr: \r sends \r\n then eats \n char * ND Non-Destructive space bool OS OverStrike works char PC Pad Character char * SE Standout End (may leave space) char * SF P Scroll Forwards char * SO Stand Out begin (may leave space) char * SR P Scroll in Reverse char * TA P TAb (not A I or with padding) char * TE Terminal address enable Ending sequence char * TI Terminal address enable Initialization char * UC Underline a single Character A-2 Revision A of 15 May 1985 Curses Reference Manual Capabilities from termcap Type Name variables set by settermf) Pad Description char * UE Underline Ending sequence bool UL Underlining works even though !OS char * UP UPline char * US Underline Starting sequence 7 char * VB Visible Bell char * VE Visual End sequence char * VS Visual Start sequence bool XN a Newline gets eaten after wrap Names starting with X are reserved for severely nauseous glitches A.4. Variables Set By gettmodeQ Table A-2: Variables Set By gettmodeQ variables set by gettmodef) type name description NONL Term can’t hack linefeeds doing a CR B*T*T*jy GT Gtty indicates Tabs j*x*i*j y** UPPERCASE Terminal generates only uppercase letters 7 US and UE, if they do not exist in the termcap entry, are copied from SO and SE in »etterm() Revision A of 15 May 1985 A-3 Appendix B The WINDOW structure The WINDOW structure is defined as follows: # define WINDOW struct _win_! struct _win_st { short _cury , _curx ; short _maxy , _maxx ; short _begy, _begx; short _flags; bool _clear ; bool _leave; bool _scroll ; char **_y; short *_firstch; short *_lastch; }; # define _SUBWIN 01 # define _ENDLINE 02 # define _FULLWIN 04 # define _SCROLLWIN 010 # define .STANDOUT 0200 _cury and _curx are the current (y, x) coordinates for the window. New characters added to the screen are added at this point. _maxy and _maxx are the maximum values allowed for [_cury, _curx). _begy and _begx are the starting (y, x) coordinates on the terminal for the window, that is, the window’s home. _cury, _curx, _maxy, and _maxx are measured relative t° [_begy, _begx), not the terminal’s home. _clear tells if a clear-screen sequence is to be generated on the next re fresh () call. This is only meaningful for screens. The initial clear-screen for the first re fresh () call is generated by initially setting clear to be TRUE for cursor, which always generates a clear-screen if set, irrelevant of the dimensions of the window involved. _leave is TRUE if the current (y, x) coordi- nates and the cursor are to be left after the last character changed on the terminal, or not moved if there is no change. _ecroll is TRUE if scrolling is allowed. 7 All variables not normally accessed directly by the user are named with an initial to avoid conflicts with the user’s variables. Revision A of 15 May 1985 R-l The WINDOW structure Curses Reference Manual y is a pointer to an array of lines which describe the terminal. Thus: _y[i] is a pointer to the «th line, and _y[i] [J] is the j th character on the ith line. _flags can have one or more values or’d into it. _SUBWIN means that the window is a subwin- dow, which indicates to delvin() that the space for the lines is not to be freed. _ENDLINE says that the end of the line for this window is also the end of a screen. _EULLWIN says that this window is a screen. SCROLLWIN indicates that the last character of this screen is at the lower right-hand corner of the terminal; that is, if a character was put there, the terminal would scroll. _ STANDOUT says that all characters added to the screen are in standout mode. B-2 Revision A of 15 May 1985 Appendix C Examples Here we present a few examples of how to use the package. They attempt to be representative, though not comprehensive. C.l. Screen Updating The following examples are intended to demonstrate the basic structure of a program using the screen updating sections of the package. Several of the programs require calculational sections which are irrelevant to the example, and are therefore usually not included. It is hoped that the data structure definitions give enough of an idea to allow understanding of what the relevant portions do. The rest is left as an exercise to the reader. C.1.1. Twinkle This is a moderately simple program which prints pretty patterns on the screen that might even hold your interest for 30 seconds or more. It switches between patterns of asterisks, putting them on one by one in random order, and then taking them off in the same fashion. It is more efficient to write this using only the motion optimization, as is demonstrated below. Revision A of 15 May 1985 C-l Examples Curses Reference Manual # include courses. h> # include /* * the idea for this program was a product of the imagination of * Kurt Schoens . Not responsible for minds lost or stolen. •/ # define # define # define NCOLS 80 NLINES 24 MAXPATTERNS 4 struct Iocs { char >; y. x; typedef struct Iocs LOCS; LOCS Layout [NCOLS * NLINES]; int Pattern, Numstars ; /* current board layout */ /* current pattern number */ /* number of stars in pattern */ main() { char *getenv () ; int die () ; srand (getpid () ) ; /* initialize random sequence */ initscr () ; signal (SIGINT, die); noecho () ; nonl () ; leaveok (stdscr , TRUE); scrollok (stdscr , FALSE); for ( ; ; ) { makeboard () ; puton (’*’); puton ( ' ' ) ; > > /* * On program exit, move the cursor to the lower left corner by * direct addressing, since current location is not guaranteed. * We lie and say we used to be at the upper right corner to guarantee * absolute addressing. */ die() { /* make the board setup */ /* put on '*'s */ /* cover up with ' ’ s */ signal (SIGINT, SIG_IGN) ; mvcur (0, C0LS-1, LINES-1, 0) ; C-2 Revision A of 15 May 1985 Curses Reference Manual Examples endwin () ; exit (O) ; /* * Make the current board setup . It picks a random pattern and * calls ison() to determine if the character is on that pattern * or not . */ makeboard () { reg int y, x; reg LOCS *lp; Pattern = rand() % MAXPATTERNS; lp = Layout; for (y =0; y < NLINES; y++) for (x = 0; x < NCOLS; x++) if (ison (y , x)) { lp->y = y; lp++->x = x; > Numstars = lp - Layout; > /* * Return TRUE if (y, x) is on the current pattern. */ ison (y, x) reg int y, x; •( switch (Pattern) { case 0: /* alternating lines */ return ! (y & 01) ; case 1 : /* box */ if (x >= LINES && y >= NCOLS) return FALSE; if (y < 3 | | y >= NLINES - 3) return TRUE; return (x < 3 | | x >= NCOLS - 3) ; case 2: /* holy pattern! */ return ( (x + y) & 01) ; case 3: /* bar across center */ return (y >= 9 && y <= 15) ; > /* NOTREACHED */ > puton (ch) reg char ch; { reg LOCS *lp; reg int r ; Revision A of 15 May 1985 C-3 Examples Curses Reference Manual reg LOCS *end ; LOCS temp ; end = &Layout [Numstars] ; for (lp = Layout; lp < end; lp + + ) { r = rand () % Numstars; temp = *lp ; *lp = Layout [r] ; Layout [r] = temp; > for (lp = Layout; lp < end; lp+ + ) { mvaddch (lp->y, lp->x, ch) ; refresh () ; > > C.1.2. Life This program plays the famous computer pattern game of life (Scientific American, May, 1974). The calculational routines create a linked list of structures defining where each piece is. Nothing here claims to be optimal, merely demonstrative. This program, however, is a very good place to use the screen updating routines, as it allows them to worry about what the last position looked like, so you don’t have to. It also demonstrates some of the input routines. C-4 Revision A of 15 May 1985 Curses Reference Manual Examples # include # include /* * Run a life game. This is a demonstration program for * the Screen Updating section of the -lcurses cursor package. */ struct lst_st { /♦ linked list element ♦/ }; int struct lst_st y, x; ♦next , ♦last; /* /* (y. x) doubly position of piece linked ♦/ typedef struct lst_st LIST; LIST ♦Head ; /♦ head of linked list ♦/ main (ac, int char av) ac; ♦av [] ; { int die () ; evalargs(ac, av) ; initscr () ; signal (SIGINT, die); crmode () ; noecho () ; nonl () ; getstart () ; for (;;) { prboard () ; update () ; > > /* evaluate arguments ♦/ /♦ initialize screen package ♦/ /♦ set to restore tty stats ♦/ /♦ set for char -by- char ♦/ /♦ input ♦/ /♦ for optimization ♦/ /♦ get starting position */ /♦ print out current board */ /* update board position */ /* * This is the routine which is called when rubout is hit. * It resets the tty stats to their original values . This * is the normal way of leaving the program. V die() { > signal (SIGINT. SIG_IGN) ; mvcur (0 , C0LS-1, LINES-1, 0) ; endwin () ; exit (0) ; /* ignore rubouts */ /* go to bottom of screen */ /* set terminal to initial state */ /* * Get the starting position from the user. They keys u, i, o, j, 1, * m. , , and . are used for moving their relative directions from the Revision A of 15 May 1985 C-5 Examples Curses Reference Manual * k key. Thus, u move diagonally up to the left, , moves directly down, * etc. x places a piece at the current position, ” " takes it away. * The input can also be from a file. The list is built after the * board setup is ready. */ getstartQ •( reg char c; reg int x, y; char *buf; box(stdscr, * |', move (1, 1) ; do { re fresh () ; if ( (c=getch () ) == ’ q ’ ) break ; (c) i 'u' : 'i' : 'o': *3': ' 1 ' : 'm' : adjustyx(c) ; break ; 'f ' : mvaddstr (0, 0, "File name: ") ; getstr (buf) ; readfile (buf) ; break ; 'x' : addch ( 'X* ) ; break; i • . addch ( ' ’ ) ; break ; > if (Head != NULL) /* start new list */ del list (Head) ; Head = malloc (sizeof (LIST)); /* * loop through the screen looking for 'x's, and add a list * element for each one */ for (y = 1; y < LINES - 1; y ++ ) for (x = 1; x < COLS - 1; x+ + ) { move (y , x) ; switch cas© case case cas© case case case case case case case > /* box in the screen */ /* move to upper left corner */ /* print current position */ C-6 Revision A of 15 May 1985 Curses Reference Manual Examples > > if (inch () == 'x') addlist(y, x) ; /* * Print out the current board position from the linked list */ prboardQ ■{ reg LIST *hp; erase (); /* clear out last position */ box(stdscr, * |', /* box in the screen */ /* * go through the list adding each piece to the newly * blank board */ for (hp = Head; hp; hp = hp->next) mvaddch (hp->y, hp->x, 'X'); re fresh () ; > C.2. Motion optimization The following example shows how motion optimization is written on its own. Programs which flit from one place to another without regard for what is already there usually do not need the over- head of both space and time associated with screen updating. They should instead use motion optimization. C.2.1. Twinkle The twinkle program is a good candidate for simple motion optimization. Here is how it could be written (only the routines that have been changed are shown): Revision A of 15 May 1985 C-7 Examples Curses Reference Manual mainQ •( reg char *sp ; char *getenv () ; int _putchar(), die(); srand (getpid () ) ; /* initialize random sequence */ if (isatty (0) ) { gettmode () ; if (sp=getenv ("TERM") ) setterm(sp) ; signal (SIGINT, die); > else { printf ("Need a terminal on %d0, _tty_ch) ; exit (1) ; > .puts (TI) ; _puts (VS) ; noecho () ; nonl () ; tputs (CL , NLINES, _putchar) ; for ( ; ; ) { makeboard () ; /* make the board setup */ puton ('*'); /* put on ' * ' s */ puton ( ' ' ) ; /* cover up with ' ' s */ > > /* * _putchar defined for tputs () (and _puts()) V _putchar (c) reg char c; •{ putchar (c) ; > puton (ch) char ch ; •{ static int reg LOCS reg int reg LOCS LOCS lasty, lastx; *ip; r; *end ; ten^s; end = fiLayout [Numstars] ; for (lp = Layout; lp < end; lp ++ ) { r = rand() % Numstars; tenp = *lp; *lp = Layout [r] ; C-8 Revision A of 15 May 1985 Curses Reference Manual Examples > > Layout [r] = temp ; for (lp = Layout; Ip < end; lp+ + ) /* prevent scrolling */ if ( ! AM || (lp->y < NLINES - 1 || lp->x < NCOLS mvcur(lasty, lastx, lp->y, lp->x) ; putchar (ch) ; lasty = lp->y; if ((lastx = lp->x + 1) >= NCOLS) if (AM) { lastx =0; lasty++; > else > lastx = NCOLS - 1; 1 )) { Revision A of 15 May 1985 C-9 Index A addch, 5-1 addstr, 5-1 B box, 5-2 c clear, 5-2 clearok, 5-2 clrtobot, 5-2 clrtoeol, 5-3 compiling, 1-2 crmode, 5-6 current screen, 1-3 curses library, 1-2 D delch, 5-3 deleteln, 5-3 delwin, 5-7 detail functions, 5-10 thru 5-12 gettmode, 5-11 mvcur, 5-11 resetty, 5-11 savetty, 5-11 scroll, 5-11 setterm, 5-11 tstp, 5-12 E echo, 5-6 endwin, 5-7 erase, 5-3 F functions details, 5-10 thru 5-12 input, 5-6 thru 5-7 miscellaneous, 5-7 thru 5-10 output, 5-1 thru 5-5 G getch, 5-6 getstr, 5-6 gettmode, 5-11 getyx, 5-8 I inch, 5-8 initscr, 5-8 input functions, 5-6