home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1987 / 07 / holub.lst < prev    next >
File List  |  1987-07-28  |  44KB  |  1,158 lines

  1.                               Listing 1 -- vbios.c
  2.  
  3.   1| #include <stdio.h>
  4.   2| #include <dos.h>   /* (Microsoft file) includes for int86() */
  5.   3| 
  6.   4| /*   VBIOS.C: Various cursor and i/o routine using
  7.   5|  *   the bios interrupts (see below for greater detail):
  8.   6|  *----------------------------------------------------------
  9.   7|  *   Copyright (C) 1987 Allen I. Holub. All rights reserved.
  10.   8|  *----------------------------------------------------------
  11.   9|  * Externally accessable routines:
  12.  10|  *
  13.  11|  * int   vb_getpage ()          Get active video page #
  14.  12|  * void  vb_putchar (c)         write a single character
  15.  13|  * void  vb_getchar (c)         get a key from the bios.
  16.  14|  * void  vb_puts    (s, move)   write a string
  17.  15|  * void  vb_replace (c)         write char w/o moving cursor
  18.  16|  * int   vb_inchar  (attrib)    Get character & attribute
  19.  17|  * 
  20.  18|  * void  vb_setcur  (posn)      Set cur pos as int on cur page
  21.  19|  * int   vb_getcur  ()          Get cur pos as int from cur page
  22.  20|  * void  vb_ctoyx (y,x)         Set cursor position to (y,x)
  23.  21|  * void  vb_getyx (&y, &x)      Get cursor position
  24.  22|  *
  25.  23|  * int   vb_iscolor()           color monitor installed
  26.  24|  * void  vb_cursize (top,bot)   Set cursor size
  27.  25|  * void  vb_blockcur()          make a block cursor
  28.  26|  * void  vb_normalcur()         revert to a normal cursor
  29.  27|  *
  30.  28|  * void  vb_scroll(l,r,t,b,a)   Scroll region
  31.  29|  */
  32.  30| 
  33.  31| /*--------------------------------------------------------*/
  34.  32| 
  35.  33| extern int      int86( int, union REGS *, union REGS *);
  36.  34| 
  37.  35| /*--------------------------------------------------------*/
  38.  36| 
  39.  37| #define VIDEO_INT     0x10    /* Video interrupt          */
  40.  38| #define KB_INT        0x16    /* Keyboard interrupt       */
  41.  39| 
  42.  40| #define CUR_SIZE      0x1     /* Set cursor size          */
  43.  41| #define SET_POSN      0x2     /* Modify cursor posn       */
  44.  42| #define READ_POSN     0x3     /* Read current cursor posn */
  45.  43| #define WRITE         0x9     /* Write character          */
  46.  44| #define WRITE_TTY     0xe     /* Write char & move cursor */
  47.  45| #define GET_VMODE     0xf     /* Get video mode & disp pg */
  48.  46| 
  49.  47| /*--------------------------------------------------------*/
  50.  48| 
  51.  49| static union REGS       Regs;      /* Used to talk to DOS */
  52.  50| static int              Attribute; /* Current attribute   */
  53.  51| 
  54.  52| /*--------------------------------------------------------*/
  55.  53| 
  56.  54| void    vb_scroll( x_left, x_right, y_top, y_bottom, amt )
  57.  55| {
  58.  56|         /* Scroll the indicated region on the screen.
  59.  57|          * If amt is negative, scroll down.
  60.  58|          */
  61.  59| 
  62.  60|         if( amt < 0 )
  63.  61|         {
  64.  62|             Regs.h.ah = 7    ;
  65.  63|             Regs.h.al = -amt ;
  66.  64|         }
  67.  65|         else
  68.  66|         {
  69.  67|             Regs.h.ah = 6   ;
  70.  68|             Regs.h.al = amt ;
  71.  69|         }
  72.  70| 
  73.  71|         Regs.h.bh = 0x07    ;
  74.  72|         Regs.h.cl = x_left  ;
  75.  73|         Regs.h.ch = y_top   ;
  76.  74|         Regs.h.dl = x_right ;
  77.  75|         Regs.h.dh = y_bottom ;
  78.  76|         int86(0x10, &Regs, &Regs);
  79.  77| }
  80.  78| 
  81.  79| /*--------------------------------------------------------*/
  82.  80| 
  83.  81| int     vb_inchar( attrib )
  84.  82| int     *attrib;
  85.  83| {
  86.  84|         /* Return the character at the current cursor 
  87.  85|          * position and, if attrib is non-NULL, put the
  88.  86|          * attribute there. Note that vb_getpage() will mess
  89.  87|          * up the fields in the Regs structure so it must
  90.  88|          * be called first.
  91.  89|          */
  92.  90| 
  93.  91|         Regs.h.bh = vb_getpage() ;
  94.  92|         Regs.h.ah = 8 ;
  95.  93| 
  96.  94|         int86( VIDEO_INT, &Regs, &Regs );
  97.  95| 
  98.  96|         if( attrib )
  99.  97|                 *attrib = Regs.h.ah & 0xff ;
  100.  98| 
  101.  99|         return( Regs.h.al & 0xff );
  102. 100| }
  103. 101| 
  104. 102| /*--------------------------------------------------------*/
  105. 103| 
  106. 104| int     vb_getpage()
  107. 105| {
  108. 106|         /* Returns the currently active display page number
  109. 107|          */
  110. 108| 
  111. 109|         Regs.h.ah = GET_VMODE;
  112. 110|         int86( VIDEO_INT, &Regs, &Regs );
  113. 111| 
  114. 112|         return (int) Regs.h.bh ;        
  115. 113| }
  116. 114| 
  117. 115| /*--------------------------------------------------------*/
  118. 116| 
  119. 117| void    vb_cursize( top_line, bot_line )
  120. 118| {
  121. 119|         /* Scan lines are numberd 0 at the top and 7 at the
  122. 120|          * bottom on the color card. On the monochrome card
  123. 121|          * they're 0-12. If top & bot are reversed you'll
  124. 122|          * get a 2 part cursor. Top_line determines the
  125. 123|          * position of the top scan line of the cursor,
  126. 124|          * bot_line is the bottom. A normal cursor can be
  127. 125|          * created with vb_cursize(6,7). Cursize(0,7) will
  128. 126|          * fill the entire area occupied by a character.
  129. 127|          * Cursize(0,1) will put a line over the character
  130. 128|          * rather than under it.
  131. 129|          */
  132. 130| 
  133. 131|         Regs.h.ch = top_line ;
  134. 132|         Regs.h.cl = bot_line ;
  135. 133|         Regs.h.ah = CUR_SIZE ;
  136. 134|         int86( VIDEO_INT, &Regs, &Regs );
  137. 135| }
  138. 136| 
  139. 137| /*--------------------------------------------------------*/
  140. 138| 
  141. 139| int vb_iscolor()   /* Returns true if a color card is active */
  142. 140| { 
  143. 141|         Regs.h.ah = GET_VMODE ;
  144. 142|         int86( VIDEO_INT, &Regs, &Regs );
  145. 143|         return( Regs.h.al != 7 );
  146. 144| }
  147. 145| 
  148. 146| void vb_blockcur()     /* Make the cursor a block curser */
  149. 147| {
  150. 148|         vb_cursize( 0, vb_iscolor() ? 7 : 12 );
  151. 149| }
  152. 150| 
  153. 151| void vb_normalcur()      /* Make it an underline cursor */
  154. 152| {
  155. 153|         if( vb_iscolor() )
  156. 154|                 vb_cursize(  6,  7 );
  157. 155|         else
  158. 156|                 vb_cursize( 11, 12 );
  159. 157| }
  160. 158| 
  161. 159| /*--------------------------------------------------------*/
  162. 160| 
  163. 161| void    vb_setcur( posn )
  164. 162| int     posn;
  165. 163| {
  166. 164|         /* Modify current cursor position. The top byte of
  167. 165|          * "posn" value holds the row (y), the bottom byte,
  168. 166|          * the column (x). The top-left corner of the screen
  169. 167|          * is (0,0). Pagenum is the video page number. Note
  170. 168|          * that vb_getpage() will mess up the fields in the
  171. 169|          * Regs structure so it must be called first.
  172. 170|          */
  173. 171| 
  174. 172|         Regs.h.bh = vb_getpage() ;
  175. 173|         Regs.x.dx = posn         ;
  176. 174|         Regs.h.ah = SET_POSN     ;
  177. 175|         int86( VIDEO_INT, &Regs, &Regs );
  178. 176| }
  179. 177| 
  180. 178| int     vb_getcur()
  181. 179| {
  182. 180|         /* Get current cursor position. The top byte of the
  183. 181|          * return value holds the row, the bottom by the
  184. 182|          * column. Pagenum is the video page number. Note
  185. 183|          * that vb_getpage() will mess up the fields in the
  186. 184|          * Regs structure so it must be called first.
  187. 185|          */
  188. 186| 
  189. 187|         Regs.h.bh = vb_getpage() ;
  190. 188|         Regs.h.ah = READ_POSN    ;
  191. 189|         int86( VIDEO_INT, &Regs, &Regs );
  192. 190|         return( Regs.x.dx );
  193. 191| }
  194. 192| 
  195. 193| /*----------------------------------------------------------
  196. 194|  * vb_cotyx() and vb_getyx also get the cursor position.
  197. 195|  * They use x and y values, however.
  198. 196|  */
  199. 197| 
  200. 198| void    vb_ctoyx ( y, x )
  201. 199| {
  202. 200|         vb_setcur( (y << 8) | (x & 0xff) );
  203. 201| }
  204. 202| 
  205. 203| void    vb_getyx( yp, xp )
  206. 204| int     *yp, *xp;
  207. 205| {
  208. 206|         register int    posn;
  209. 207| 
  210. 208|         posn = vb_getcur();
  211. 209|         *xp  = posn        & 0xff ;
  212. 210|         *yp  = (posn >> 8) & 0xff ;
  213. 211| }
  214. 212| 
  215. 213| /*--------------------------------------------------------*/
  216. 214| 
  217. 215| vb_replace(c)
  218. 216| {
  219. 217|         /* Overwrite the character at the current cursor
  220. 218|          * position without moving the cursor.
  221. 219|          */
  222. 220| 
  223. 221|         Regs.h.ah = 10 ;
  224. 222|         Regs.h.al = c;          /* write c              */
  225. 223|         Regs.h.bl = 0x07;       /* Normal characters    */
  226. 224|         Regs.h.bh = 0;          /* Display page 0       */
  227. 225|         Regs.x.cx = 1;          /* # of times to write  */
  228. 226| 
  229. 227|         int86( VIDEO_INT, &Regs, &Regs );
  230. 228| }
  231. 229| 
  232. 230| /*--------------------------------------------------------*/
  233. 231| 
  234. 232| vb_putchar( c )
  235. 233| {
  236. 234|         /* Write a character to the screen in TTY mode.
  237. 235|          * Only normal printing characters, BS, BEL, CR and
  238. 236|          * LF are recognized. The cursor is automatically
  239. 237|          * advanced and lines will wrap.
  240. 238|          */
  241. 239| 
  242. 240|         Regs.h.bl = 0x07;
  243. 241|         Regs.h.al = c;
  244. 242|         Regs.h.ah = WRITE_TTY ;
  245. 243|         int86( VIDEO_INT, &Regs, &Regs );
  246. 244| }
  247. 245| 
  248. 246| /*--------------------------------------------------------*/
  249. 247| 
  250. 248| vb_puts( str, move_cur )
  251. 249| register char   *str;
  252. 250| {
  253. 251|         /* Write a string to the screen in TTY mode. If
  254. 252|          * move_cur is true the cursor is left at the end
  255. 253|          * of string. If not the cursor will be restored to
  256. 254|          * its original position (before the write).
  257. 255|          */
  258. 256| 
  259. 257|         register int    posn;
  260. 258| 
  261. 259|         if( !move_cur )
  262. 260|                 posn = vb_getcur();
  263. 261| 
  264. 262|         while( *str )
  265. 263|                 vb_putchar( *str++ );
  266. 264| 
  267. 265|         if( !move_cur )
  268. 266|                 vb_setcur( posn );
  269. 267| }
  270. 268| 
  271. 269| /*--------------------------------------------------------*/
  272. 270| 
  273. 271| int     vb_getchar()
  274. 272| {
  275. 273|         /* Get a character with a direct video bios call.
  276. 274|          * This routine can be used to complement stderr as
  277. 275|          * it can be used to get characters from the keyboard,
  278. 276|          * even when input redirected. The typed character
  279. 277|          * is returned in the low byte of the returned
  280. 278|          * integer, the high byte holds the auxillary byte
  281. 279|          * used to mark ALT keys and such. See the Technical
  282. 280|          * Reference for more info.
  283. 281|          */
  284. 282| 
  285. 283|         Regs.h.ah = 0 ;
  286. 284|         int86( KB_INT, &Regs, &Regs );
  287. 285|         return( (int)Regs.x.ax );
  288. 286| }
  289. 287| 
  290. 288| /*--------------------------------------------------------*/
  291. 289| #ifdef MAIN
  292. 290| 
  293. 291| main()
  294. 292| {
  295. 293|         vb_replace( 'X' );
  296. 294|         vb_putchar('\n');
  297. 295|         vb_putchar('\r');
  298. 296| }
  299. 297| 
  300. 298| #endif
  301.                           Listing 2 -- /include/box.h
  302.  
  303.   1| /*-------------------------------------------------------*
  304.   2|  * BOX.H:  Copyright (c) 1987, Allen I. Holub.
  305.   3|  *                  All rights reserved.
  306.   4|  *
  307.   5|  *  #defines for the box-drawing characters on the IBM PC.
  308.   6|  *
  309.   7|  *-------------------------------------------------------*
  310.   8|  *      The names are:
  311.   9|  *
  312.  10|  *      UL      Upper left corner
  313.  11|  *      UR      Upper right corner
  314.  12|  *      LL      lower left corner
  315.  13|  *      LR      lower right corner
  316.  14|  *      CEN     Center (intersection of two lines)
  317.  15|  *      TOP     Tee with the flat piece on top
  318.  16|  *      BOT     Bottom tee              
  319.  17|  *      LEFT    Left tee
  320.  18|  *      RIGHT   Right tee
  321.  19|  *      HORIZ   Horizontal line
  322.  20|  *      VERT    Vertical line.
  323.  21|  *
  324.  22|  *
  325.  23|  *                      UL    -TOP-     UR              HORIZ
  326.  24|  *                              |
  327.  25|  *                      L                R                V
  328.  26|  *                      E       |        I                E
  329.  27|  *                      F--   -CEN-    --G                R
  330.  28|  *                      T       |        H                T
  331.  29|  *                      |                T              
  332.  30|  *                              |
  333.  31|  *                      LL    -BOT-     LR
  334.  32|  *
  335.  33|  *
  336.  34|  * The D_XXX  defines have double horizontal and vertical lines
  337.  35|  * The HD_XXX defines have double horizontal lines only
  338.  36|  * The VD_XXX defines have double vertial lines only
  339.  37|  *
  340.  38|  * If your terminal is not IBM compatible, #define all of these
  341.  39|  * as '+', except for the VERT #defines, which should be a |,
  342.  40|  * and the HORIZ #defines, which should be a -.
  343.  41|  */
  344.  42| 
  345.  43| #define VERT            179
  346.  44| #define RIGHT           180
  347.  45| #define UR              191
  348.  46| #define LL              192
  349.  47| #define BOT             193
  350.  48| #define TOP             194
  351.  49| #define LEFT            195
  352.  50| #define HORIZ           196
  353.  51| #define CEN             197
  354.  52| #define LR              217
  355.  53| #define UL              218
  356.  54| 
  357.  55| #define D_VERT          186
  358.  56| #define D_RIGHT         185
  359.  57| #define D_UR            187
  360.  58| #define D_LL            200
  361.  59| #define D_BOT           202
  362.  60| #define D_TOP           203
  363.  61| #define D_LEFT          204
  364.  62| #define D_HORIZ         205
  365.  63| #define D_CEN           206
  366.  64| #define D_LR            188
  367.  65| #define D_UL            201
  368.  66| 
  369.  67| #define HD_VERT         179
  370.  68| #define HD_RIGHT        181
  371.  69| #define HD_UR           184
  372.  70| #define HD_LL           212
  373.  71| #define HD_BOT          207
  374.  72| #define HD_TOP          209
  375.  73| #define HD_LEFT         198
  376.  74| #define HD_HORIZ        205
  377.  75| #define HD_CEN          216
  378.  76| #define HD_LR           190
  379.  77| #define HD_UL           213
  380.  78| 
  381.  79| #define VD_VERT         186
  382.  80| #define VD_RIGHT        182
  383.  81| #define VD_UR           183
  384.  82| #define VD_LL           211
  385.  83| #define VD_BOT          208
  386.  84| #define VD_TOP          210
  387.  85| #define VD_LEFT         199
  388.  86| #define VD_HORIZ        196
  389.  87| #define VD_CEN          215
  390.  88| #define VD_LR           189
  391.  89| #define VD_UL           214
  392.                          Listing 3 -- /include/curses.h
  393.  
  394.   1| /*-------------------------------------------------------*
  395.   2|  * CURSES.H:  Copyright (c) 1987, Allen I. Holub.        *
  396.   3|  *                  All rights reserved.                 *
  397.   4|  *-------------------------------------------------------*
  398.   5|  */
  399.   6| 
  400.   7| typedef struct
  401.   8| {
  402.   9|     int x_org;     /* X coordinate of upper-left corner    */
  403.  10|     int y_org;     /* Y coordinate of upper-left corner    */
  404.  11|     int x_size;    /* Horizontal size of text area.        */
  405.  12|     int y_size;    /* Vertical   size of text area.        */
  406.  13|     int row;       /* Current cursor row (0 to y_size-1)   */
  407.  14|     int col;       /* Current cursor column (0 to x_size-1)*/
  408.  15|     int scroll_ok; /* Scrolling permitted in this window   */
  409.  16| }
  410.  17| WINDOW;
  411.  18| 
  412.  19| # define        bool    unsigned int
  413.  20| # define        reg     register
  414.  21| # define        TRUE    (1)
  415.  22| # define        FALSE   (0)
  416.  23| # define        ERR     (0)
  417.  24| # define        OK      (1)
  418.  25| 
  419.  26| /*------------------------------------------------------------
  420.  27|  * Reminder: The comma opperator goes left to right and
  421.  28|  *              evaluates to the rightmost thing in the list.
  422.  29|  *
  423.  30|  * The following macros implement many of the curses functions
  424.  31|  * note that stdscr only has meaning when passed to getyx.
  425.  32|  *------------------------------------------------------------
  426.  33|  */
  427.  34| 
  428.  35| #define stdscr          0 
  429.  36| 
  430.  37| #define getyx(win,y,x)  (win ? ((x)=win->col,(y)=win->row)  \
  431.  38|                              : getpos(&x,&y))
  432.  39| 
  433.  40| #define mvinch(y,x)     ( move (  y,x), inch ( ) )
  434.  41| #define mvwinch(w,y,x)  ( wmove(w,y,x), winch(w) )
  435.  42| 
  436.  43| #define addch(c)           putchar(c)
  437.  44| #define endwin()
  438.  45| #define erase()            clear()
  439.  46| #define initscr()
  440.  47| #define printw             printf
  441.  48| #define refresh()
  442.  49| #define scroll(w)          wscroll(w,1);
  443.  50| #define scrollok(win,flag) ((win)->scroll_ok = (flag))
  444.  51| #define subwin(w,a,b,c,d)  newwin(a,b,c,d)
  445.  52| #define wclear             werase
  446.  53| #define wrefresh(win)
  447.  54| 
  448.  55| /*----------------------------------------------------------*/
  449.  56| 
  450.  57| extern  WINDOW *newwin  (int ,int ,int ,int );
  451.  58| extern  int box         (WINDOW *,int ,int );
  452.  59| extern  int clear       (void);
  453.  60| extern  int crmode      (void);
  454.  61| extern  int echo        (void);
  455.  62| extern  int getch       (void);
  456.  63| extern  int move        (int ,int );
  457.  64| extern  int nl          (void);
  458.  65| extern  int nocrmode    (void);
  459.  66| extern  int noecho      (void);
  460.  67| extern  int nonl        (void);
  461.  68| extern  int waddch      (WINDOW *, int  );
  462.  69| extern  int waddstr     (WINDOW *, char *);
  463.  70| extern  int wclrtoeol   (WINDOW *       );
  464.  71| extern  int werase      (WINDOW *       );
  465.  72| extern  int wgetch      (WINDOW *       );
  466.  73| extern  int wmove       (WINDOW *, int   ,int );
  467.  74| extern  int wprintw     (WINDOW *, char *,... );
  468.  75| extern  int wscroll     (WINDOW *, int       );
  469.                              Listing 4 -- curses.c
  470.  
  471.   1| #include <stdio.h>
  472.   2| #include <ctype.h>
  473.   3| #include <curses.h>  /* routines in this file.           */
  474.   4| #include <box.h>     /* of IBM box-drawing characters    */
  475.   5| #include <stdarg.h>  /* va_list and va_start (ANSI)      */
  476.   6| 
  477.   7| /*-------------------------------------------------------*
  478.   8|  * CURSES.C:  Copyright (c) 1987, Allen I. Holub.        *
  479.   9|  *                  All rights reserved.                 *
  480.  10|  *-------------------------------------------------------*
  481.  11|  *
  482.  12|  * This file is a DOS implementation of some of the Unix
  483.  13|  * CURSES functions. It is Unix compatible but is a proper
  484.  14|  * subset, not a full implementation, of curses. It works
  485.  15|  * on the IBM-PC. In all of these y is the row number and
  486.  16|  * x is the column number. The upper left corner is (0,0):
  487.  17|  *
  488.  18|  * I/O functions ------------------------------------------
  489.  19|  *
  490.  20|  * waddch( win, ch )      Works like putc()
  491.  21|  * waddstr( win, str)     Works like puts()
  492.  22|  * wprintw(win,fmt,arg...)  Like printf but writes to the
  493.  23|  *                          indicated window.
  494.  24|  * wrefresh(win)          See below.
  495.  25|  * box(win, vert, horiz)  Draws a box around the window.
  496.  26|  *
  497.  27|  * Cursor movement and screen control ---------------------
  498.  28|  *
  499.  29|  * werase(win)       erase the entire window
  500.  30|  * wclrtoeol(win)    erase from cursor position to the end
  501.  31|  *                   of line
  502.  32|  *
  503.  33|  * wmove(win,y,x)  Move the cursor to postion (y,x) rela-
  504.  34|  *                 tive to the orgin of the indicated window.
  505.  35|  *
  506.  36|  * getxy(win,y,x)    MACRO: puts the current cursor postion
  507.  37|  *                   into y and x. Note that this is a macro,
  508.  38|  *                   don't put an & in front of y and x in
  509.  39|  *                   the invocation.
  510.  40|  *
  511.  41|  * wgetch(win)       works like getchar but echos to the
  512.  42|  *                   indicated window.  If crmode is
  513.  43|  *                   inactive, it is activated for the
  514.  44|  *                   duration of this subroutine.
  515.  45|  *
  516.  46|  * scroll(win)          Scrolls the window up one line.
  517.  47|  * wscroll( win, amt )  NOT A CURSES FUNCTION. Scrolls
  518.  48|  *                      window by indicated amount. A
  519.  49|  *                      negaitve amt scrolls down.
  520.  50|  *
  521.  51|  * Initialization stuff -------------------------------------
  522.  52|  *
  523.  53|  * initscr()              Initialize
  524.  54|  * endwin()               Clean up
  525.  55|  * scrollok(win, flag);   enable/disable scrolling for window.
  526.  56|  * newwin(lines,cols,begin_y,begin_x)     Create a new window.
  527.  57|  *
  528.  58|  * Terminal control -----------------------------------------
  529.  59|  *        Because of the perversities of DOS, these work in a
  530.  60|  *        slightly nonstandard way. In particular echo, noecho,
  531.  61|  *        nl, and nonl only work if crmode() is active.
  532.  62|  *        Moreover, they are ignored for the non-w fundtions.
  533.  63|  *        For portability reasons, it's best to always set
  534.  64|  *        crmode() at the top of your program.
  535.  65|  *
  536.  66|  * crmode();              Turn off input buffering.
  537.  67|  * nocrmode();            Turn it back on again.  (default)
  538.  68|  * noecho();              Turn off automatic echo.
  539.  69|  * echo();                Turn it back on again.  (default)
  540.  70|  * nl();                  Turn on CR-NL mapping   (default)
  541.  71|  * nonl();                turn it off again.
  542.  72|  *
  543.  73|  * Functions that affect the whole screen. ------------------
  544.  74|  *
  545.  75|  * move(y,x)              move cursor to abs. position (y,x)
  546.  76|  * addch(c)               Write a character.
  547.  77|  * clear()                Clear the screen
  548.  78|  * printw()               works like printf
  549.  79|  * getch()                get a character from the keyboard.
  550.  80|  * refresh()              See below.
  551.  81|  *
  552.  82|  *-----------------------------------------------------------
  553.  83|  * The real curses keeps an two internal representations of
  554.  84|  * the screen, when you change something it just modifies
  555.  85|  * one of these reprsentations. You must issue a refresh()
  556.  86|  * or wrefresh() call to actually modify the screen. My
  557.  87|  * version of curses refreshes the screen immediately after
  558.  88|  * every write. refresh() and wrefresh() macros have been
  559.  89|  * provided for UNIX compatability, however. These macros
  560.  90|  * don't do anything, but you should scatter them liberally
  561.  91|  * about your code if you want it to be portable.
  562.  92|  *
  563.  93|  * I've corrected one bug in the real curses that might
  564.  94|  * cause problems when you port your code. The real curses
  565.  95|  * (at least the one at Berkeley), doesn't scroll properly
  566.  96|  * in that it leaves junk on the bottom line of the window
  567.  97|  * after a scroll. I've corrected the problem here but,
  568.  98|  * again, if you want real portability you should do a
  569.  99|  * wclrtoeol(win) after every scroll. Unfortunately, there's
  570. 100|  * no way to determine that the screen has scrolled without
  571. 101|  * actually keeping track of the characters that are written
  572. 102|  * to the screen. Ugh.
  573. 103|  *
  574. 104|  * Other differences: curses doesn't know about characters
  575. 105|  * that it hasn't actually put on the screen with an addch().
  576. 106|  * So, if echo is enabled, curses won't erase the echoed
  577. 107|  * characters when it scrolls the screen and so forth. The
  578. 108|  * curses presented here doesn't exibit this behaviour, but
  579. 109|  * if you want compatablility with Unix, turn off echo (with
  580. 110|  * a noecho() call) and then echo all characters yourself.
  581. 111|  *
  582. 112|  * The purpose of the four #defines immediately below is to
  583. 113|  * make it easy to modify this package. They all map function
  584. 114|  * calls to video-bios subroutines [vb_xxx()]. If you want to
  585. 115|  * use your own functions (that do direct video access or send
  586. 116|  * out escape sequences to a normal terminal, for example)
  587. 117|  * just change the #defines and recompile. The functions must
  588. 118|  * behave as follows:
  589. 119|  *
  590. 120|  * cmove(y,x)   Move the cursor to position (y,x) (y is row)
  591. 121|  *              where (0,0) is the upper-left corner of the
  592. 122|  *              screen.
  593. 123|  * curpos(y,x)  Put the (y,x) cursor position into the
  594. 124|  *              integers pointed to by y and x.
  595. 125|  * replace(c)   Print c at the current cursor position without
  596. 126|  *              moving the cursor. This routine must be able
  597. 127|  *              to put a character into the 80th column
  598. 128|  *              without scrolling the screen or wrapping
  599. 129|  *              around.
  600. 130|  *
  601. 131|  * doscroll(l,r,t,b,a)  Scroll a region of the screen with the
  602. 132|  *                      top left corner at (t,l) and the bottom
  603. 133|  *              right corner at (b,r). "a" is the number of
  604. 134|  *              lines to scroll (up if a is positive, down if
  605. 135|  *              it's negative).
  606. 136|  *
  607. 137|  * inchar()     Returns the character at the current curser
  608. 138|  *              position.
  609. 139|  */
  610. 140| 
  611. 141| #define cmove(y,x)           vb_ctoyx(y,x);
  612. 142| #define curpos(y,x)          vb_getyx(y,x);
  613. 143| #define replace(c)           vb_replace(c);
  614. 144| #define doscroll(l,r,t,b,a)  vb_scroll(l,r,t,b,a);
  615. 145| #define inchar()             vb_inchar(NULL)
  616. 146| 
  617. 147| #define min(a,b)             ((a) < (b) ? (a) : (b))
  618. 148| 
  619. 149| /*--------------------------------------------------------*/
  620. 150| 
  621. 151| static int Echo   = 1;  /* Echo enabled                   */
  622. 152| static int Crmode = 0;  /* If 1, use buffered input       */
  623. 153| static int Nl     = 1;  /* If 1, map \r to \n on input    */
  624. 154|                         /* and map both to \n\r on output */
  625. 155| 
  626. 156| /*--------------------------------------------------------*/
  627. 157| 
  628. 158| noecho  (     ) {  Echo = 0;                    }
  629. 159| echo    (     ) {  Echo = 1;                    }
  630. 160| nl      (     ) {  Nl   = 1;                    }
  631. 161| nonl    (     ) {  Nl   = 0;                    }
  632. 162| getpos  (yp,xp) {  return curpos(yp, xp);       }
  633. 163| move    (y, x ) {  cmove(y, x);                 }
  634. 164| inch    (     ) {  return inchar();             }
  635. 165| 
  636. 166|  /*--------------------------------------------------------*/
  637. 167| 
  638. 168| crmode()
  639. 169| {
  640. 170|     FILE        *console;
  641. 171| 
  642. 172|     setvbuf(stdin, NULL, _IONBF, 0);  /* Turn off buffering */
  643. 173|     Crmode = 1;
  644. 174| }
  645. 175| 
  646. 176| nocrmode()
  647. 177| {
  648. 178|     freopen( "/dev/con", "r", stdin );
  649. 179|     Crmode = 0;
  650. 180| }
  651. 181| 
  652. 182| /*--------------------------------------------------------*/
  653. 183| 
  654. 184| WINDOW  *newwin( lines, cols, begin_y, begin_x )
  655. 185| 
  656. 186| int     cols;     /* Horizontal size (including border)   */
  657. 187| int     lines;    /* Vergtical size  (including bofder)   */
  658. 188| int     begin_y;  /* X coordinate of upper-left corner    */
  659. 189| int     begin_x;  /* Y coordinate of upper-left corner    */
  660. 190| {
  661. 191|         WINDOW  *win, *malloc();
  662. 192| 
  663. 193|         if( !(win = malloc( sizeof(WINDOW) )) )
  664. 194|                 ferr("Out of memory\n");
  665. 195| 
  666. 196|         win->x_org      = begin_x;
  667. 197|         win->y_org      = begin_y;
  668. 198|         win->x_size     = cols   ;
  669. 199|         win->y_size     = lines  ;
  670. 200|         win->row        = 0;
  671. 201|         win->col        = 0;
  672. 202|         win->scroll_ok  = 0;
  673. 203| 
  674. 204|         werase(win);
  675. 205|         return win;
  676. 206| }
  677. 207| 
  678. 208| /*--------------------------------------------------------*/
  679. 209| 
  680. 210| int     waddch( win, c )
  681. 211| WINDOW  *win;
  682. 212| int     c;
  683. 213| {
  684. 214|     /*  Print a character: The following are handled
  685. 215|      *  specially:
  686. 216|      *
  687. 217|      *  \n  Clear the line from the current cursor position
  688. 218|      *      to the right edge of the window. Then:
  689. 219|      *      if nl() is active:
  690. 220|      *          go to the left edge of the next line
  691. 221|      *      else
  692. 222|      *          go to the current column on the next line
  693. 223|      *      In addition, if scrolling is enabled, the window
  694. 224|      *      scrolls if you're on the bottom line.
  695. 225|      *  \t  is expanded into an 8-space field. If the tab
  696. 226|      *      goes past the right edge of the window, the
  697. 227|      *      cursor wraps to the next line.
  698. 228|      *  \r  gets you to the beginning of the current line.
  699. 229|      *
  700. 230|      *  \b  backs up one space but may not back up past
  701. 231|      *      the left edge of the window. Nondestructive. The
  702. 232|      *      curses documentation doesn't say that \b is
  703. 233|      *      handled explicitly but it does indeed work.
  704. 234|      *
  705. 235|      *  The following is not supported by Unix. Don't use
  706. 236|      *  explicit escape sequences if portability is a
  707. 237|      *  consideration:
  708. 238|      *
  709. 239|      *  ESC This is not standard curses but is useful. All
  710. 240|      *      characters between an ASCII ESC and an alphabetic
  711. 241|      *      character are sent to the output but are otherwise
  712. 242|      *      igonred. This let's you send escape sequences
  713. 243|      *      directly to the terminal if you like. I'm
  714. 244|      *      assuming here that you won't change windows in the
  715. 245|      *      middle of an escape sequence.
  716. 246|      *
  717. 247|      * Return ERR if the character would have caused the
  718. 248|      * window to scroll illegally.
  719. 249|      */
  720. 250| 
  721. 251|     static  int     saw_esc = 0;
  722. 252|     static  WINDOW  *oldwin = NULL;
  723. 253|     int             rval    = OK;
  724. 254| 
  725. 255|     if( oldwin != win )
  726. 256|     {
  727. 257|         cmove(win->y_org + win->row, win->x_org + win->col);
  728. 258|         oldwin = win;
  729. 259|     }
  730. 260| 
  731. 261|     if( saw_esc )
  732. 262|     {
  733. 263|             if( isalpha( c ) )
  734. 264|                     saw_esc = 0;
  735. 265| 
  736. 266|             putchar(c);
  737. 267|     }
  738. 268|     else
  739. 269|     {
  740. 270|             switch( c )
  741. 271|             {
  742. 272|             case '\033':
  743. 273|                     saw_esc = 1;
  744. 274|                     putchar('\033');
  745. 275|                     break;
  746. 276| 
  747. 277|             case '\b':
  748. 278|                     if( win->col > 0 )
  749. 279|                     {
  750. 280|                             putchar('\b');
  751. 281|                             --( win->col );
  752. 282|                     }
  753. 283|                     break;
  754. 284| 
  755. 285|             case '\t':
  756. 286|                     do
  757. 287|                     {
  758. 288|                             waddch( win, ' ' );
  759. 289|                     }
  760. 290|                     while( win->col % 8 );
  761. 291|                     break;
  762. 292| 
  763. 293|             case '\r':
  764. 294|                     win->col = 0;
  765. 295|                     cmove(win->y_org + win->row, win->x_org);
  766. 296|                     break;
  767. 297| 
  768. 298|             default :
  769. 299|                     putchar(c);
  770. 300|                     if( ++(win->col) < win->x_size )
  771. 301|                             break;
  772. 302| 
  773. 303|                     /* fall through to newline */
  774. 304| 
  775. 305|             case '\n':
  776. 306|                     wclrtoeol( win );
  777. 307| 
  778. 308|                     if( Nl )
  779. 309|                         win->col = 0;
  780. 310| 
  781. 311|                     if( ++(win->row) >= win->y_size )
  782. 312|                     {
  783. 313|                         rval = wscroll( win, 1 );
  784. 314|                         --( win->row );
  785. 315|                     }
  786. 316| 
  787. 317|                     cmove( win->y_org + win->row,
  788. 318|                            win->x_org + win->col);
  789. 319|                     break;
  790. 320|             }
  791. 321|     }
  792. 322| 
  793. 323|     return rval;
  794. 324| }
  795. 325| 
  796. 326| /*--------------------------------------------------------*/
  797. 327| 
  798. 328| waddstr( win, str )
  799. 329| WINDOW  *win;
  800. 330| char    *str;
  801. 331| {
  802. 332|         while( *str )
  803. 333|                 waddch( win, *str );
  804. 334| }
  805. 335| 
  806. 336| /*--------------------------------------------------------*/
  807. 337| 
  808. 338| static int Errcode = OK;
  809. 339| 
  810. 340| static wputc(c, win) WINDOW *win;
  811. 341| {
  812. 342|         Errcode |= waddch(win,c);
  813. 343| }
  814. 344| 
  815. 345| wprintw(win, fmt)
  816. 346| WINDOW  *win;
  817. 347| char    *fmt;
  818. 348| {
  819. 349|     /* The doprnt() function used here is explained in depth
  820. 350|      * in Allen Holub, The C Companion (Prentice-Hall: 1987),
  821. 351|      * pp. 213-237. If you don't have this book, an alternate
  822. 352|      * approach is explained in the text.
  823. 353|      */
  824. 354| 
  825. 355|     va_list args;
  826. 356|     va_start( args, fmt );
  827. 357| 
  828. 358|     Errcode = OK;
  829. 359|     doprnt( wputc, win, fmt, args );
  830. 360|     return Errcode;
  831. 361| }
  832. 362| 
  833. 363| /*--------------------------------------------------------*/
  834. 364| 
  835. 365| box( win, vert, horiz )
  836. 366| WINDOW  *win;
  837. 367| {
  838. 368|     /* Draws a box in the outermost characters of the window
  839. 369|      * using vert for the vertical characters and horiz for
  840. 370|      * the horizontal ones. I've extended this function to
  841. 371|      * support the IBM box-drawing characters. That is,
  842. 372|      * if IBM box-drawing characters are specified for vert
  843. 373|      * and horiz, box() will use the correct box-drawing
  844. 374|      * characters in the corners. These are defined in
  845. 375|      * box.h as:
  846. 376|      *
  847. 377|      *      HORIZ   (0xc4)  single horizontal line
  848. 378|      *      D_HORIZ (0xcd)  double horizontal line.
  849. 379|      *      VERT    (0xb3)  single vertical line
  850. 380|      *      D_VERT  (0xba)  double vertical line.
  851. 381|      */
  852. 382| 
  853. 383|     int     i, nrows;
  854. 384|     int     ul, ur, ll, lr;
  855. 385| 
  856. 386|     if( !( (horiz == HORIZ || horiz == D_HORIZ) &&
  857. 387|            (vert  == VERT  || vert  == D_VERT ) ))
  858. 388|     {
  859. 389|             ul = ur = ll = lr = vert ;
  860. 390|     }
  861. 391|     else
  862. 392|     {
  863. 393|         if( vert == VERT )
  864. 394|         {
  865. 395|             if(horiz==HORIZ)
  866. 396|                 ul=UL,    ur=UR,    ll=LL,    lr=LR;
  867. 397|             else
  868. 398|                 ul=HD_UL, ur=HD_UR, ll=HD_LL, lr=HD_LR;
  869. 399|         }
  870. 400|         else
  871. 401|         {
  872. 402|             if(horiz==HORIZ)
  873. 403|                 ul=VD_UL, ur=VD_UR, ll=VD_LL, lr=VD_LR;
  874. 404|             else
  875. 405|                 ul=D_UL,  ur=D_UR,  ll=D_LL,  lr=D_LR;
  876. 406|         }
  877. 407|     }
  878. 408| 
  879. 409|     cmove( win->y_org, win->x_org );
  880. 410| 
  881. 411|     putchar( ul );                          /* Top line */
  882. 412| 
  883. 413|     for( i = win->x_size-2; --i >= 0 ; )
  884. 414|             putchar( horiz );
  885. 415| 
  886. 416|     putchar( ur );
  887. 417|     nrows = win->y_size - 2 ;              /* Two sides */
  888. 418|     i     = win->y_org  + 1 ;
  889. 419| 
  890. 420|     while( --nrows >= 0 )
  891. 421|     {
  892. 422|             cmove( i,   win->x_org );
  893. 423|             putchar( vert );
  894. 424| 
  895. 425|             cmove( i++, win->x_org + (win->x_size - 1) );
  896. 426|             putchar( vert );
  897. 427|     }
  898. 428| 
  899. 429|     cmove(i, win->x_org);               /* Bottom line */
  900. 430|     putchar( ll );  
  901. 431| 
  902. 432|     for( i = win->x_size-2; --i >= 0 ; )
  903. 433|             putchar( horiz );
  904. 434| 
  905. 435|     putchar( lr );
  906. 436| }
  907. 437| 
  908. 438| /*--------------------------------------------------------*/
  909. 439| 
  910. 440| werase( win )
  911. 441| WINDOW  *win;
  912. 442| {
  913. 443|     vb_scroll( win->x_org, win->x_org + (win->x_size - 1), 
  914. 444|                win->y_org, win->y_org + (win->y_size - 1),
  915. 445|                win->y_size );
  916. 446| 
  917. 447|     cmove( win->y_org, win->x_org );
  918. 448|     win->row = 0;
  919. 449|     win->col = 0;
  920. 450| }
  921. 451| 
  922. 452| /*----------------------------------------------------------
  923. 453|  * Scroll the window if scrolling is enabled. Return 1 if we
  924. 454|  * scrolled. (I'm not sure if the Unix function returns 1
  925. 455|  * on a scroll but it's convenient to do it here. Don't
  926. 456|  * assume anything about the return value if you're porting
  927. 457|  * to Unix. Wscroll() is not a curses function. It lets you
  928. 458|  * specify a scroll amount and direction (scroll down by -amt
  929. 459|  * if amt is negative); scroll() is a macro that evaluates to
  930. 460|  * a wscroll call with an amt of 1. Note that the Unix curses
  931. 461|  * gets very confused when you scroll explicitly (using
  932. 462|  * scroll()). In particular, it doesn't clear the bottom line
  933. 463|  * after a scroll but it thinks that it has. Therefore, when
  934. 464|  * you try to clear the bottom line, it thinks that there's
  935. 465|  * nothing there to clear and ignores your wclrtoeol()
  936. 466|  * commands. Same thing happens when you try to print spaces
  937. 467|  * to the bottom line; it thinks that spaces are already there
  938. 468|  * and does nothing. You have to fill the bottom line with
  939. 469|  * non-space characters of some sort, and then erase it.
  940. 470|  */
  941. 471| 
  942. 472| wscroll(win, amt)
  943. 473| WINDOW  *win;
  944. 474| {
  945. 475|     if( win->scroll_ok )
  946. 476|         doscroll( win->x_org, win->x_org + (win->x_size-1), 
  947. 477|                   win->y_org, win->y_org + (win->y_size-1),
  948. 478|                   amt);
  949. 479| 
  950. 480|     return win->scroll_ok ;
  951. 481| }
  952. 482| 
  953. 483| /*--------------------------------------------------------*/
  954. 484| 
  955. 485| wmove( win, y, x )
  956. 486| WINDOW  *win;
  957. 487| {
  958. 488|     /* Seek into the window. It's not permitted to seek
  959. 489|      * outside of the window area.
  960. 490|      */
  961. 491| 
  962. 492|     cmove( win->y_org + (win->row = min(y,win->y_size-1)) ,
  963. 493|            win->x_org + (win->col = min(x,win->x_size-1)) );
  964. 494| }
  965. 495| 
  966. 496| /*--------------------------------------------------------*/
  967. 497| 
  968. 498| static  getcon( win )
  969. 499| WINDOW  *win;
  970. 500| {
  971. 501|     /* Get a character from DOS without echoing. We need
  972. 502|      * to do this in order to support (echo/noecho). We'll
  973. 503|      * also do noncrmode input buffering here. Maximum input
  974. 504|      * line length is 132 columns.
  975. 505|      *
  976. 506|      * In nocrmode(), DOS is used to get a line and all the
  977. 507|      * normal command-line editing functions are available.
  978. 508|      * Note that since there's no way to turn off echo in
  979. 509|      * this case, characters will be echoed to the screen
  980. 510|      * regardles of the status of echo().
  981. 511|      * In order to retain control of the window, input
  982. 512|      * fetched for wgetch() is always done in crmode, even
  983. 513|      * if Crmode isn't set.
  984. 514|      * If nl() mode is enabled, carriage return (Enter, ^M)
  985. 515|      * and linefeed (^J) are both mapped to '\n', otherwise
  986. 516|      * they are not mapped.
  987. 517|      */
  988. 518| 
  989. 519|     static unsigned char  buf[ 133 ] = { 133, 0 };
  990. 520|     static unsigned char  *p         = buf;
  991. 521|     static          int   numchars   = 0;
  992. 522|     register        int   c;
  993. 523| 
  994. 524|     if( Crmode || win )
  995. 525|     {
  996. 526|             if( (c = bdos(8,0,0) & 0xff) == ('Z'-'@') )
  997. 527|                     return EOF ;
  998. 528| 
  999. 529|             if( c == '\r' &&  Nl)
  1000. 530|                     c = '\n' ;
  1001. 531| 
  1002. 532|             if( Echo )
  1003. 533|             {
  1004. 534|                 if( win )  waddch ( win, c );
  1005. 535|                 else       addch  (      c );
  1006. 536|             }
  1007. 537| 
  1008. 538|             return c;
  1009. 539|     }
  1010. 540|     else if( numchars )
  1011. 541|     {
  1012. 542|             --numchars  ;
  1013. 543|             return *p++ ;
  1014. 544|     }
  1015. 545|     else
  1016. 546|     {
  1017. 547|             bdos(10, buf, 0);
  1018. 548|             numchars =  buf[1];
  1019. 549|             p        = &buf[2];
  1020. 550|     }
  1021. 551| }
  1022. 552| 
  1023. 553| wgetch (win)  WINDOW *win; { return getcon( win  ); }
  1024. 554| getch  (   )               { return getcon( NULL ); }
  1025. 555| 
  1026. 556| /*--------------------------------------------------------*/
  1027. 557| 
  1028. 558| clear()
  1029. 559| {
  1030. 560|         doscroll( 0, 79, 0, 24, 25 );
  1031. 561|         move( 0, 0 );
  1032. 562| }
  1033. 563| 
  1034. 564| /*--------------------------------------------------------*/
  1035. 565| 
  1036. 566| wclrtoeol( win )
  1037. 567| WINDOW  *win;
  1038. 568| {
  1039. 569|     /* Clear from cursor to end of line, the cursor isn't
  1040. 570|      * moved. The main reson that this is included here is
  1041. 571|      * because you have to call it after printing every
  1042. 572|      * newline in order to compensate for a bug in the real
  1043. 573|      * curses. This bug has been corrected in the curses
  1044. 574|      * presented here, however, so you don't have to use
  1045. 575|      * this routine if you're not interested in portability.
  1046. 576|      * Note that you must use a replace function on the
  1047. 577|      * rightmost character to prevent scrolling.
  1048. 578|      */
  1049. 579| 
  1050. 580|     register int    i;
  1051. 581| 
  1052. 582|     for( i = win->x_size - win->col - 1; --i >= 0 ;)
  1053. 583|             putchar(' ');
  1054. 584| 
  1055. 585|     replace(' ');
  1056. 586|     cmove( win->y_org + win->row, win->x_org + win->col )
  1057. 587| }
  1058. 588| 
  1059. 589| /*--------------------------------------------------------*/
  1060. 590| #ifdef MAIN
  1061. 591| 
  1062. 592| WINDOW  *boxwin( lines, cols, y_start, x_start )
  1063. 593| {
  1064. 594|     /* This routine works just like the newwin() except that
  1065. 595|      * the window has a box around it that won't be destoyed
  1066. 596|      * by writes to the window. It accomplishes this feat by
  1067. 597|      * creating two windows, one inside the other, with a box
  1068. 598|      * drawn around the outer one.
  1069. 599|      */
  1070. 600| 
  1071. 601|     WINDOW *outer, *inner;
  1072. 602| 
  1073. 603|     outer = newwin(lines,   cols,   y_start,   x_start);
  1074. 604| 
  1075. 605| #ifdef MSDOS
  1076. 606|     box( outer, VERT, HORIZ );
  1077. 607| #else
  1078. 608|     box( outer,  '|',  '-'  );
  1079. 609| #endif
  1080. 610| 
  1081. 611|     wrefresh ( outer );
  1082. 612|     return newwin( lines-2, cols-2, y_start+1, x_start+1 ); 
  1083. 613| }
  1084. 614| 
  1085. 615| pattern()
  1086. 616| {
  1087. 617|     clear();
  1088. 618|     printf("01234567890123456789012345678901234567890 0\n");
  1089. 619|     printf("01234567890123456789012345678901234567890 1\n");
  1090. 620|     printf("01234567890123456789012345678901234567890 2\n");
  1091. 621|     printf("01234567890123456789012345678901234567890 3\n");
  1092. 622|     printf("01234567890123456789012345678901234567890 4\n");
  1093. 623|     printf("01234567890123456789012345678901234567890 5\n");
  1094. 624|     printf("01234567890123456789012345678901234567890 6\n");
  1095. 625|     printf("01234567890123456789012345678901234567890 7\n");
  1096. 626|     printf("01234567890123456789012345678901234567890 8\n");
  1097. 627|     printf("01234567890123456789012345678901234567890 9\n");
  1098. 628|     printf("01234567890123456789012345678901234567890 10\n");
  1099. 629|     printf("01234567890123456789012345678901234567890 11\n");
  1100. 630|     printf("01234567890123456789012345678901234567890 12\n");
  1101. 631|     printf("01234567890123456789012345678901234567890 13\n");
  1102. 632|     printf("01234567890123456789012345678901234567890 14\n");
  1103. 633|     printf("01234567890123456789012345678901234567890 15\n");
  1104. 634|     printf("01234567890123456789012345678901234567890 16\n");
  1105. 635|     printf("01234567890123456789012345678901234567890 17\n");
  1106. 636|     printf("01234567890123456789012345678901234567890 18\n");
  1107. 637|     printf("01234567890123456789012345678901234567890 19\n");
  1108. 638|     printf("01234567890123456789012345678901234567890 20\n");
  1109. 639|     printf("01234567890123456789012345678901234567890 21\n");
  1110. 640|     printf("01234567890123456789012345678901234567890 22\n");
  1111. 641|     printf("          1         2         3         4 n");
  1112. 642| }
  1113. 643| 
  1114. 644| main()
  1115. 645| {
  1116. 646|         /* All coordinates are (y,x) */
  1117. 647| 
  1118. 648|         WINDOW  *win1, *win2;
  1119. 649|         char    str[128];
  1120. 650|         int     c;
  1121. 651| 
  1122. 652|         initscr(); /* Initialize curses                  */
  1123. 653|         noecho();  /* Echo off (it screws up the screen) */
  1124. 654|         crmode();  /* Put terminal into CBREAK mode      */
  1125. 655| 
  1126. 656|         pattern();
  1127. 657| 
  1128. 658|         win1 = boxwin(10, 20,  0, 0 );
  1129. 659|         win2 = boxwin(10, 20, 21, 11);
  1130. 660| 
  1131. 661|         scrollok( win1, TRUE );
  1132. 662|         wprintw(win1, "This is window one, doo wha\n" );
  1133. 663|         wrefresh( win1 );
  1134. 664|         wprintw(win2, "This is window 2.\nPress a key\n" );
  1135. 665|         wrefresh( win2 );
  1136. 666| 
  1137. 667|         c = wgetch(win2);
  1138. 668|         wmove(win1, 5, 0 );
  1139. 669| 
  1140. 670|         wprintw   (win1, "Got %c, 0x%x\n", c, c );
  1141. 671|         wrefresh(win1);
  1142. 672| 
  1143. 673|         while( (c = wgetch(win1) & 0x7f) != 'q' )
  1144. 674|         {
  1145. 675|                 if( c == 'X'-'@' )
  1146. 676|                     wclrtoeol( win1 );
  1147. 677|                 else
  1148. 678|                     waddch( win1, c );
  1149. 679| 
  1150. 680|                 wrefresh( win1 );
  1151. 681|         }
  1152. 682| 
  1153. 683|         move(23,0);
  1154. 684|         refresh();
  1155. 685|         endwin();
  1156. 686| }
  1157. 687| #endif
  1158.