1 /******************************************************************************
2 *
3 *  NSSDC/CDF                                            Windowing functions.
4 *
5 *  Version 4.0a, 15-Dec-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  29-Jan-91, H Leckner  Original version (for CDF V2.0).
10 *   V1.1   4-Aug-91, J Love     TRUE/FALSE.  Minor change to borders (well
11 *                    H Leckner  maybe).
12 *   V1.2  13-Aug-91, H Leckner  Fixed border labeling.
13 *   V1.3   8-Oct-91, J Love     Modified for IRIX 4.0 port, etc.
14 *                    H Leckner
15 *   V2.0  30-Apr-92, H Leckner  CDF V2.2.  IBM PC port.  Added `input_field'
16 *                    J Love     and `get_input'.
17 *   V2.1  20-Jul-92, J Love     CDF V2.3 (shareable/NeXT/zVar).
18 *   V3.0   9-Dec-93, J Love     CDF V2.4.  Generalized for all platforms.
19 *   V3.1  21-Dec-94, J Love	CDF V2.5.
20 *   V3.2  23-Jan-95, J Love	IRIX 6.x (64-bit).
21 *   V3.2a 31-Jan-95, J Love	Fixed `WindowSize' for VMS.
22 *   V3.2b  7-Feb-95, J Love	Made `WindowLocation' and `WindowSize'
23 *				function prototypes `static'.
24 *   V3.2c  3-Mar-95, J Love	Moved `EncodeKeyDefinitions', etc. to this
25 *				file.
26 *   V3.3   4-Apr-95, J Love	POSIX.
27 *   V3.3a 18-Apr-95, J Love	More POSIX.
28 *   V3.3b 13-Jun-95, J Love	Linux.
29 *   V3.4  16-Jun-95, J Love	`key_waiting'.
30 *   V3.4a 11-Jul-95, J Love	`key_waiting' for UNIX.
31 *   V3.4b  7-Sep-95, J Love	CDFexport-related changes.
32 *   V3.4c 19-Sep-95, J Love	Macintosh event handling.
33 *   V3.4d 28-Sep-95, J Love	Increased precision of `zzzzz' on Macintosh.
34 *				The CDF cursor.
35 *   V3.5   3-Oct-96, J Love	CDF V2.6.
36 *   V3.5a  2-Sep-97, J Love	Special keys for AIX.
37 *   V4.0  14-Nov-97, J Love	Windows NT/Visual C++.
38 *   V4.0a 15-Dec-97, J Love	IEEE floating-point on Alpha/OpenVMS.
39 *   V4.1   2-May-01, M Liu      Special keys for CYGWIN.
40 *   V4.2  11-Jul-05, M Liu      Added MingW port for PC.
41 *
42 *******************************************************************************
43 * NOTES:
44 *    1. All functions return TRUE if successful, FALSE if an error occurred.
45 *    2. The borders provided by SMG are not used.  SMG$DRAW_RECTANGLE is used
46 *       if a border is requested.  This is to allow the `draw_horizontal_line'
47 *       and 'draw_vertical_line' functions the ability to draw a line all the
48 *       way to the border (where SMG "tees" the line).
49 *    3. On the IBM PC...
50 *       a) It doesn't seem to be possible to OR in attributes with a
51 *          character.  Currently using `wattrset' before writing characters.
52 *       b) The cursor cannot be positioned on a character position that has
53 *          not been written to.
54 *    4. On the VAX (SMG), using SMG$SET_CURSOR_ABS doesn't seem to work if
55 *	the pasteboard is being batched (SMG$BEGIN/END_PASTEBOARD_UPDATE).
56 *	The cursor is always placed at (1,1) when the screen is updated.  So
57 *	don't do that.
58 ******************************************************************************/
59 
60 /******************************************************************************
61 * Include files.
62 ******************************************************************************/
63 
64 #include "windoz.h"
65 
66 #if defined(win32)
67 #include "windows.h"
68 #endif
69 
70 #if defined(mac)
71 #include "fsi.rh"
72 #endif
73 
74 /******************************************************************************
75 * Macros.
76 ******************************************************************************/
77 
78 #define INTERPRET_ESC_SEQUENCES	1
79 #define ESC			27
80 
81 /******************************************************************************
82 * Global variables.
83 ******************************************************************************/
84 
85 #if defined(SMGui)
86 static long pbid;
87 static long kbid;
88 static int keyWaiting;
89 #endif
90 
91 #if defined(CURSESui)
92 static int batchCount;			/* When zero (0), updates to screen
93 					   (pasteboard) are applied
94 					   immediately. */
95 #endif
96 
97 #if defined(COWui)
98 #if defined(mac)
99 static WindowPtr fsiWindowP;		/* Full screen interface window
100 					   pointer. */
101 static MenuHandle appleMenuHfsi;	/* Menu handle for apple. */
102 #endif
103 static WINDOWid cursorWIND;		/* Window in which the cursor was
104 					   last set. */
105 static int cursorRow;			/* Row at which cursor was last set. */
106 static int cursorCol;			/* Column at which cursor was last
107 					   set. */
108 static Logical cursorVisible;		/* TRUE if the cursor is currently
109 					   visible. */
110 static int batchCount;			/* When zero (0), updates to screen
111 					   (pasteboard) are applied
112 					   immediately. */
113 static char *pbNewChars;		/* New characters for the
114 					   pasteboard. */
115 static char *pbNewAttrs;		/* New attributes for the
116 					   pasteboard. */
117 static char *pbCurrentChars;		/* Current characters on the
118 					   pasteboard. */
119 static char *pbCurrentAttrs;		/* Current attributes on the
120 					   pasteboard. */
121 static char *pbNullChars;		/* Pasteboard of null characters. */
122 static char *pbBlankChars;		/* Pasteboard of blank characters. */
123 static char *pbNormalAttrs;		/* Normal pasteboard of attributes. */
124 #endif
125 
126 static WINDOWid WINDhead;		/* Head of window linked list.  1st
127 					   window on list is most occluded.
128 					   Last window on list is on top of
129 					   all other windows (most recently
130 					   pasted). */
131 static Logical cursorOn;		/* TRUE if the cursor has been set to
132 					   be visible (when not occluded). */
133 
134 /******************************************************************************
135 * Local function prototypes.
136 ******************************************************************************/
137 
138 #if defined(SMGui)
139 static void KeyWaitingAST PROTOARGs((void));
140 #endif
141 
142 #if defined(CURSESui)
143 static void WindowLocation PROTOARGs((LocalId id, int *row, int *col));
144 #endif
145 
146 #if defined(CURSESui) || defined(SMGui)
147 static void WindowSize PROTOARGs((LocalId id, int *rows, int *cols));
148 #endif
149 
150 static int RenditionMapping PROTOARGs((int));
151 static WINDOWid AddWIND PROTOARGs((LocalId, Logical, Logical));
152 static Logical MoveWINDtoEnd PROTOARGs((WINDOWid));
153 static Logical DeleteWIND PROTOARGs((WINDOWid));
154 static Logical DeleteWINDs PROTOARGs((void));
155 
156 #if defined(CURSESui) || defined(COWui)
157 static Logical RefreshWINDs PROTOARGs((int level));
158 #endif
159 
160 #if defined(CURSESui)
161 static int EraseWindow PROTOARGs((LocalId));
162 #endif
163 
164 #if defined(COWui)
165 #if defined(mac)
166 static void InvertCursor PROTOARGs((WINDOWid wid, int rowN, int colN));
167 #endif
168 static Logical CharOccluded PROTOARGs((WINDOWid wid, int rowN, int colN));
169 #endif
170 
171 static char *KeyToken PROTOARGs((int, int));
172 static char *AlphaKey PROTOARGs((int, int));
173 static char *ControlKey PROTOARGs((int, int));
174 
175 /******************************************************************************
176 * begin_pasteboard_update.
177 ******************************************************************************/
178 
begin_pasteboard_update()179 int begin_pasteboard_update () {
180 #if defined(SMGui)
181   if (StatusBad(smg$begin_pasteboard_update(&pbid))) return FALSE;
182   return TRUE;
183 #endif
184 #if defined(CURSESui)
185   batchCount++;
186   return TRUE;
187 #endif
188 #if defined(COWui)
189   batchCount++;
190   return TRUE;
191 #endif
192 }
193 
194 /******************************************************************************
195 * change_rendition.
196 ******************************************************************************/
197 
change_rendition(wid,row,col,num_rows,num_cols,rendition)198 int change_rendition (wid, row, col, num_rows, num_cols, rendition)
199 WINDOWid wid;
200 int row;
201 int col;
202 int num_rows;
203 int num_cols;
204 int rendition;
205 {
206 #if defined(SMGui)
207   long rowN = row + 1;
208   long colN = col + 1;
209   uLong rend = RenditionMapping (rendition);
210   if (StatusBad(smg$change_rendition(&(wid->id),&rowN,&colN,
211 				     &num_rows,&num_cols,&rend))) return FALSE;
212   return TRUE;
213 #endif
214 #if defined(CURSESui)
215   int i,j;
216   wattrset (wid->id, RenditionMapping(rendition));
217   for (i = 0; i < num_rows; i++)
218      for (j = 0; j < num_cols; j++)
219 	mvwaddch (wid->id, row+i, col+j,
220 		  mvwinch(wid->id,row+i,col+j) & A_CHARTEXT);
221   if (!RefreshWINDs(UPDATE_)) return FALSE;
222   return TRUE;
223 #endif
224 #if defined(COWui)
225   char rend = RenditionMapping (rendition);
226   char *attrs = wid->id->attrs;
227   int i, j;
228   for (i = 0; i < num_rows; i++)
229      for (j = 0; j < num_cols; j++) {
230 	int charN = (wid->id->nCols*(row+i)) + (col+j);
231 	attrs[charN] = rend;
232      }
233   if (!RefreshWINDs(UPDATE_)) return FALSE;
234   return TRUE;
235 #endif
236 }
237 
238 /******************************************************************************
239 * create_pasteboard.
240 ******************************************************************************/
241 
create_pasteboard()242 int create_pasteboard () {
243 #if defined(SMGui)
244   if (StatusBad(smg$create_pasteboard(&pbid,NULL,NULL,NULL,NULL,NULL))) {
245     return FALSE;
246   }
247   if (StatusBad(smg$create_virtual_keyboard(&kbid,NULL,NULL,NULL,NULL))) {
248     return FALSE;
249   }
250   if (StatusBad(smg$enable_unsolicited_input(&pbid,KeyWaitingAST,NULL))) {
251     return FALSE;
252   }
253   keyWaiting = 0;
254   WINDhead = NULL;
255   set_cursor_mode (CURSORon);
256   return TRUE;
257 #endif
258 #if defined(CURSESui)
259   initscr ();
260   keypad (stdscr, TRUE);
261   noecho ();
262   nonl ();
263   raw ();
264   refresh ();			/* Clears screen. */
265   batchCount = 0;
266   WINDhead = NULL;
267   set_cursor_mode (CURSORon);
268   return TRUE;
269 #endif
270 #if defined(COWui)
271   int charN, nChars = NUMfsiROWS * NUMfsiCOLS;
272 #if defined(mac)
273   Rect eraseRect = { 0, 0, WINDOWfsiHEIGHT, WINDOWfsiWIDTH };
274 #endif
275   batchCount = 0;
276   WINDhead = NULL;
277   cursorWIND = NULL;
278   cursorVisible = FALSE;
279   cursorOn = FALSE;
280   pbCurrentChars = (char *) cdf_AllocateMemory (nChars, FatalError);
281   pbCurrentAttrs = (char *) cdf_AllocateMemory (nChars, FatalError);
282   pbNewChars = (char *) cdf_AllocateMemory (nChars, FatalError);
283   pbNewAttrs = (char *) cdf_AllocateMemory (nChars, FatalError);
284   pbNullChars = (char *) cdf_AllocateMemory (nChars, FatalError);
285   pbBlankChars = (char *) cdf_AllocateMemory (nChars, FatalError);
286   pbNormalAttrs = (char *) cdf_AllocateMemory (nChars, FatalError);
287   for (charN = 0; charN < nChars; charN++) {
288      pbNullChars[charN] = 0;
289      pbBlankChars[charN] = ' ';
290      pbNormalAttrs[charN] = 0;
291   }
292   memmove (pbCurrentChars, pbBlankChars, nChars);
293   memmove (pbCurrentAttrs, pbNormalAttrs, nChars);
294   set_cursor_mode (CURSORon);
295 #if defined(mac)
296   EraseRect (&eraseRect);
297   ShowWindow (fsiWindowP);
298 #endif
299 #if defined(win32)
300    /* Jeff...maybe nothing needs to be done. */
301 #endif
302   return TRUE;
303 #endif
304 }
305 
306 /******************************************************************************
307 * create_virtual_display.
308 * The window is not visibile until the function `paste_virtual_display' is
309 * used.
310 ******************************************************************************/
311 
create_virtual_display(num_rows,num_cols,wid,borderMode,rendition)312 int create_virtual_display (num_rows, num_cols, wid, borderMode, rendition)
313 int num_rows;
314 int num_cols;
315 WINDOWid *wid;
316 int borderMode;			/* If BORDER, draw border around display. */
317 int rendition;			/* Rendition of border (if bordered). */
318 {
319 #if defined(SMGui)
320   LocalId id;
321   uLong attrs = 0;
322   uLong rend = RenditionMapping (NORMAL);   /* Default for display. */
323   long nRows = num_rows;
324   long nCols = num_cols;
325   if (StatusBad(smg$create_virtual_display(&nRows,&nCols,&id,
326 					   &attrs,&rend,NULL))) return FALSE;
327   *wid = AddWIND (id, FALSE, (borderMode == BORDER));
328   if (borderMode == BORDER) draw_rectangle (*wid, 0, 0, num_rows - 1,
329 					    num_cols - 1, rendition);
330   return TRUE;
331 #endif
332 #if defined(CURSESui)
333   LocalId id = newwin (num_rows, num_cols, 0, 0);
334   if (id == NULL) return FALSE;
335   keypad (id, TRUE);
336   *wid = AddWIND (id, FALSE, (borderMode == BORDER));
337   erase_display (*wid, 0, 0, num_rows - 1, num_cols - 1);
338   if (borderMode == BORDER) draw_rectangle (*wid, 0, 0, num_rows - 1,
339 					    num_cols - 1, rendition);
340   return TRUE;
341 #endif
342 #if defined(COWui)
343   LocalId id;
344   int nChars = num_rows * num_cols;
345   if (num_rows < 1 || num_rows > NUMfsiROWS) return FALSE;
346   if (num_cols < 1 || num_cols > NUMfsiCOLS) return FALSE;
347   id = (LocalId) cdf_AllocateMemory (sizeof(COWvd), FatalError);
348   id->nRows = num_rows;
349   id->nCols = num_cols;
350   id->atRowN = 0;
351   id->atColN = 0;
352   id->chars = (char *) cdf_AllocateMemory (nChars, FatalError);
353   id->attrs = (char *) cdf_AllocateMemory (nChars, FatalError);
354   *wid = AddWIND (id, FALSE, (borderMode == BORDER));
355   memmove (id->chars, pbBlankChars, nChars);
356   memmove (id->attrs, pbNormalAttrs, nChars);
357   if (borderMode == BORDER) draw_rectangle (*wid, 0, 0, num_rows - 1,
358 					    num_cols - 1, rendition);
359   return TRUE;
360 #endif
361 }
362 
363 /******************************************************************************
364 * delete_pasteboard.
365 ******************************************************************************/
366 
delete_pasteboard(eraseMode)367 int delete_pasteboard (eraseMode)
368 int eraseMode;
369 {
370 #if defined(SMGui)
371   uLong flags = (eraseMode == ERASE ? SMG$M_ERASE_PBD : 0);
372   Logical status = DeleteWINDs();
373   if (StatusBad(smg$delete_pasteboard(&pbid,&flags))) return FALSE;
374   return status;
375 #endif
376 #if defined(CURSESui)
377   Logical status = DeleteWINDs();
378   if (eraseMode == ERASE) {     /* Don't change default attributes first. */
379     EraseWindow (stdscr);
380     wrefresh (stdscr);
381   }
382   endwin ();
383   return status;
384 #endif
385 #if defined(COWui)
386   Logical status = DeleteWINDs();
387 #if defined(mac)
388   Rect eraseRect = { 0, 0, WINDOWfsiHEIGHT, WINDOWfsiWIDTH };
389 #endif
390 #if defined(mac)
391   if (eraseMode == ERASE) EraseRect (&eraseRect);
392 #endif
393   cdf_FreeMemory (pbCurrentChars, FatalError);
394   cdf_FreeMemory (pbCurrentAttrs, FatalError);
395   cdf_FreeMemory (pbNewChars, FatalError);
396   cdf_FreeMemory (pbNewAttrs, FatalError);
397   cdf_FreeMemory (pbNullChars, FatalError);
398   cdf_FreeMemory (pbBlankChars, FatalError);
399   cdf_FreeMemory (pbNormalAttrs, FatalError);
400 #if defined(mac)
401   HideWindow (fsiWindowP);
402 #endif
403   return status;
404 #endif
405 }
406 
407 /******************************************************************************
408 * delete_virtual_display.
409 ******************************************************************************/
410 
delete_virtual_display(wid)411 int delete_virtual_display (wid)
412 WINDOWid wid;
413 {
414   if (!DeleteWIND(wid)) return FALSE;
415   return TRUE;
416 }
417 
418 /******************************************************************************
419 * draw_horizontal_line.
420 ******************************************************************************/
421 
draw_horizontal_line(wid,rowN,LcolN,RcolN,rendition,teeEnds)422 int draw_horizontal_line (wid, rowN, LcolN, RcolN, rendition, teeEnds)
423 WINDOWid wid;           /* Window id. */
424 int rowN;               /* Row number. */
425 int LcolN;              /* Left column number (start) -- numbered from zero. */
426 int RcolN;              /* Right column number (stop) -- numbered from zero. */
427 int rendition;          /* Rendition to use. */
428 Logical teeEnds;	/* If TRUE, draw ACS_LTEE and ACS_RTEE at the ends of
429 			   the line (ACS_HLINE is drawn at all of the other
430 			   positions).  If FALSE, draw ACS_HLINE at all of the
431 			   positions.  On SMG systems (VAX/VMS), this option
432 			   is ignored (SMG decides whether or not to tee the
433 			   ends based on the existing characters at those
434 			   positions). */
435 {
436 #if defined(SMGui)
437   long startRowN = rowN + 1;
438   long endRowN = startRowN;
439   long startColN = LcolN + 1;
440   long endColN = RcolN + 1;
441   uLong rend = RenditionMapping(rendition);
442   if (StatusBad(smg$draw_line(&(wid->id),&startRowN,&startColN,
443 			      &endRowN,&endColN,&rend,NULL))) return FALSE;
444 #endif
445 #if defined(CURSESui)
446    int colN;            /* Column number -- numbered from zero. */
447    wattrset (wid->id, RenditionMapping(rendition));
448    mvwaddch (wid->id, rowN, LcolN, (teeEnds ? ACS_LTEE : ACS_HLINE));
449    for (colN = LcolN + 1; colN < RcolN; colN++)
450       mvwaddch (wid->id, rowN, colN, ACS_HLINE);
451    mvwaddch (wid->id, rowN, RcolN, (teeEnds ? ACS_RTEE : ACS_HLINE));
452    if (!RefreshWINDs(UPDATE_)) return FALSE;
453    return TRUE;
454 #endif
455 #if defined(COWui)
456    int colN,            /* Column number -- numbered from zero. */
457        charN;		/* Character number -- numbered from zero. */
458    char rend = RenditionMapping (rendition);
459    short nCols = wid->id->nCols;
460    char *chars = wid->id->chars,
461 	*attrs = wid->id->attrs;
462    charN = (rowN * nCols) + LcolN;
463    chars[charN] = (teeEnds ? ACS_LTEE : ACS_HLINE);
464    attrs[charN] = rend;
465    for (colN = LcolN + 1; colN < RcolN; colN++) {
466       charN = (rowN * nCols) + colN;
467       chars[charN] = ACS_HLINE;
468       attrs[charN] = rend;
469    }
470    charN = (rowN * nCols) + RcolN;
471    chars[charN] = (teeEnds ? ACS_RTEE : ACS_HLINE);
472    attrs[charN] = rend;
473    if (!RefreshWINDs(UPDATE_)) return FALSE;
474    return TRUE;
475 #endif
476 }
477 
478 /******************************************************************************
479 * draw_vertical_line.
480 ******************************************************************************/
481 
draw_vertical_line(wid,TrowN,BrowN,colN,rendition,teeEnds)482 int draw_vertical_line (wid, TrowN, BrowN, colN, rendition, teeEnds)
483 WINDOWid wid;           /* Window id. */
484 int TrowN;              /* Top row number (start) -- numbered from zero. */
485 int BrowN;              /* Bottom row number (stop) -- numbered from zero. */
486 int colN;               /* Column number -- numbered from zero. */
487 int rendition;          /* Rendition to use. */
488 Logical teeEnds;	/* If TRUE, draw ACS_TTEE and ACS_BTEE at the ends of
489 			   the line (ACS_VLINE is drawn at all of the other
490 			   positions).  If FALSE, draw ACS_VLINE at all of the
491 			   positions.  On SMG systems (VAX/VMS), this option
492 			   is ignored (SMG decides whether or not to tee the
493 			   ends based on the existing characters at those
494 			   positions). */
495 {
496 #if defined(SMGui)
497   long startRowN = TrowN + 1;
498   long endRowN = BrowN + 1;
499   long startColN = colN + 1;
500   long endColN = startColN;
501   uLong rend = RenditionMapping(rendition);
502   if (StatusBad(smg$draw_line(&(wid->id),&startRowN,&startColN,
503 			      &endRowN,&endColN,&rend,NULL))) return FALSE;
504 #endif
505 #if defined(CURSESui)
506    int rowN;            /* Row number -- numbered from zero. */
507    wattrset (wid->id, RenditionMapping(rendition));
508    mvwaddch (wid->id, TrowN, colN, (teeEnds ? ACS_TTEE : ACS_VLINE));
509    for (rowN = TrowN + 1; rowN < BrowN; rowN++)
510       mvwaddch (wid->id, rowN, colN, ACS_VLINE);
511    mvwaddch (wid->id, BrowN, colN, (teeEnds ? ACS_BTEE : ACS_VLINE));
512    if (!RefreshWINDs(UPDATE_)) return FALSE;
513    return TRUE;
514 #endif
515 #if defined(COWui)
516    int rowN,            /* Row number -- numbered from zero. */
517        charN;		/* Character number -- numbered from zero. */
518    char rend = RenditionMapping (rendition);
519    short nCols = wid->id->nCols;
520    char *chars = wid->id->chars,
521 	*attrs = wid->id->attrs;
522    charN = (TrowN * nCols) + colN;
523    chars[charN] = (teeEnds ? ACS_TTEE : ACS_VLINE);
524    attrs[charN] = rend;
525    for (rowN = TrowN + 1; rowN < BrowN; rowN++) {
526       charN = (rowN * nCols) + colN;
527       chars[charN] = ACS_VLINE;
528       attrs[charN] = rend;
529    }
530    charN = (BrowN * nCols) + colN;
531    chars[charN] = (teeEnds ? ACS_BTEE : ACS_VLINE);
532    attrs[charN] = rend;
533    if (!RefreshWINDs(UPDATE_)) return FALSE;
534    return TRUE;
535 #endif
536 }
537 
538 /******************************************************************************
539 * draw_rectangle.
540 ******************************************************************************/
541 
draw_rectangle(wid,Trow,Lcol,Brow,Rcol,rendition)542 int draw_rectangle (wid, Trow, Lcol, Brow, Rcol, rendition)
543 WINDOWid wid;
544 int Trow;		/* Top row number. */
545 int Lcol;		/* Left column number. */
546 int Brow;		/* Bottom row number. */
547 int Rcol;		/* Right column number. */
548 int rendition;		/* Video attributes. */
549 {
550 #if defined(SMGui)
551   long startRow = Trow + 1;
552   long startCol = Lcol + 1;
553   long endRow = Brow + 1;
554   long endCol = Rcol + 1;
555   uLong rend = RenditionMapping (rendition);
556   if (StatusBad(smg$draw_rectangle(&(wid->id),&startRow,&startCol,
557 				   &endRow,&endCol,&rend,NULL))) return FALSE;
558   return TRUE;
559 #endif
560 #if defined(CURSESui)
561   int x, y;
562   wattrset (wid->id, RenditionMapping(rendition));
563   mvwaddch (wid->id, Trow, Lcol, ACS_ULCORNER);
564   for (x = Lcol+1; x <= Rcol-1; x++) mvwaddch (wid->id, Trow, x, ACS_HLINE);
565   mvwaddch (wid->id, Trow, Rcol, ACS_URCORNER);
566   for (y = Trow+1; y <= Brow-1; y++) mvwaddch (wid->id, y, Rcol, ACS_VLINE);
567   mvwaddch (wid->id, Brow, Rcol, ACS_LRCORNER);
568   for (x = Rcol-1; x >= Lcol+1; x--) mvwaddch (wid->id, Brow, x, ACS_HLINE);
569   mvwaddch (wid->id, Brow, Lcol, ACS_LLCORNER);
570   for (y = Brow-1; y >= Trow+1; y--) mvwaddch (wid->id, y, Lcol, ACS_VLINE);
571   if (!RefreshWINDs(UPDATE_)) return FALSE;
572   return TRUE;
573 #endif
574 #if defined(COWui)
575   char rend = RenditionMapping (rendition);
576   short nCols = wid->id->nCols;
577   char *chars = wid->id->chars,
578        *attrs = wid->id->attrs;
579   int charN, x, y;
580   charN = (Trow * nCols) + Lcol;
581   chars[charN] = ACS_ULCORNER;
582   attrs[charN] = rend;
583   for (x = Lcol + 1; x <= Rcol - 1; x++) {
584      charN = (Trow * nCols) + x;
585      chars[charN] = ACS_HLINE;
586      attrs[charN] = rend;
587   }
588   charN = (Trow * nCols) + Rcol;
589   chars[charN] = ACS_URCORNER;
590   attrs[charN] = rend;
591   for (y = Trow + 1; y <= Brow - 1; y++) {
592      charN = (y * nCols) + Rcol;
593      chars[charN] = ACS_VLINE;
594      attrs[charN] = rend;
595   }
596   charN = (Brow * nCols) + Rcol;
597   chars[charN] = ACS_LRCORNER;
598   attrs[charN] = rend;
599   for (x = Rcol - 1; x >= Lcol + 1; x--) {
600      charN = (Brow * nCols) + x;
601      chars[charN] = ACS_HLINE;
602      attrs[charN] = rend;
603   }
604   charN = (Brow * nCols) + Lcol;
605   chars[charN] = ACS_LLCORNER;
606   attrs[charN] = rend;
607   for (y = Brow - 1; y >= Trow + 1; y--) {
608      charN = (y * nCols) + Lcol;
609      chars[charN] = ACS_VLINE;
610      attrs[charN] = rend;
611   }
612   if (!RefreshWINDs(UPDATE_)) return FALSE;
613   return TRUE;
614 #endif
615 }
616 
617 /******************************************************************************
618 * end_pasteboard_update.
619 ******************************************************************************/
620 
end_pasteboard_update()621 int end_pasteboard_update ()
622 {
623 #if defined(SMGui)
624   if (StatusBad(smg$end_pasteboard_update(&pbid))) return FALSE;
625   return TRUE;
626 #endif
627 #if defined(CURSESui)
628   batchCount = MaxInt (0, batchCount - 1);
629   if (!RefreshWINDs(UPDATE_)) return FALSE;
630   return TRUE;
631 #endif
632 #if defined(COWui)
633   batchCount = MaxInt (0, batchCount - 1);
634   if (!RefreshWINDs(UPDATE_)) return FALSE;
635   return TRUE;
636 #endif
637 }
638 
639 /******************************************************************************
640 * erase_display.
641 * This routine erases the BOX specified by the starting and ending character
642 * positions (which is different from what SMG$ERASE_DISPLAY does on a VAX).
643 ******************************************************************************/
644 
erase_display(wid,startRow,startCol,endRow,endCol)645 int erase_display (wid, startRow, startCol, endRow, endCol)
646 WINDOWid wid;
647 int startRow;
648 int startCol;
649 int endRow;
650 int endCol;
651 {
652 #if defined(SMGui)
653   long startRowN = startRow + 1;
654   long endRowN = endRow + 1;
655   long startColN = startCol + 1;
656   long nCols = endCol - startCol + 1;
657   long rowN;
658   for (rowN = startRowN; rowN <= endRowN; rowN++)
659      if (StatusBad(smg$erase_chars(&(wid->id),&nCols,
660 				   &rowN,&startColN))) return FALSE;
661   return TRUE;
662 #endif
663 #if defined(CURSESui)
664   int i, j;
665   wattrset (wid->id, RenditionMapping(NORMAL));
666   for (i = startRow; i <= endRow; i++)
667      for (j = startCol; j <= endCol; j++) mvwaddch (wid->id, i, j, ' ');
668   if (!RefreshWINDs(UPDATE_)) return FALSE;
669   return TRUE;
670 #endif
671 #if defined(COWui)
672   int i, j, charN;
673   char rend = RenditionMapping (NORMAL);
674   char *chars = wid->id->chars,
675        *attrs = wid->id->attrs;
676   short nCols = wid->id->nCols;
677   for (i = startRow; i <= endRow; i++)
678      for (j = startCol; j <= endCol; j++) {
679 	charN = (i * nCols) + j;
680 	chars[charN] = ' ';
681 	attrs[charN] = rend;
682      }
683   if (!RefreshWINDs(UPDATE_)) return FALSE;
684   return TRUE;
685 #endif
686 }
687 
688 /******************************************************************************
689 * input_field.
690 * The caller must turn the cursor on/off before calling this routine.
691 * This is only used by CDFlist and CDFwalk (ie. expendable).
692 ******************************************************************************/
693 
input_field(wid,field,fieldRow,fieldCol,fieldLen,exitKeys,exitKey,toggleInsertModeKey,moveToSOLkey,moveToEOLkey,deleteToSOLkey,deleteToEOLkey,refreshKey)694 int input_field (wid, field, fieldRow, fieldCol, fieldLen, exitKeys, exitKey,
695 		 toggleInsertModeKey, moveToSOLkey, moveToEOLkey,
696 		 deleteToSOLkey, deleteToEOLkey, refreshKey)
697 WINDOWid wid;
698 char *field;                    /* The field may contain an initial value. */
699 int fieldRow;
700 int fieldCol;
701 int fieldLen;                   /* Maximum length of field. */
702 int *exitKeys;                  /* Keys which cause input field to be
703 				   exited (NUL-terminated). */
704 int *exitKey;			/* Key which actually caused exit. */
705 int toggleInsertModeKey;        /* Key causing insert mode to be toggled
706 				   (between insert and overstrike). */
707 int moveToSOLkey;		/* Key causing cursor to move to the start
708 				   of the field. */
709 int moveToEOLkey;		/* Key causing cursor to move to the end of
710 				   the field. */
711 int deleteToSOLkey;		/* Key causing the characters in front of
712 				   the cursor to be deleted (and then the
713 				   cursor/remaining characters are moved up. */
714 int deleteToEOLkey;		/* Key causing the characters starting at the
715 				   cursor to be deleted. */
716 int refreshKey;			/* Key causing the screen to be refreshed. */
717 {
718   int curLen = (int) strlen(field);
719   int insertMode = FALSE;	/* Initially in insert mode. */
720   int firstCol = fieldCol;
721   int lastCol = fieldCol + fieldLen - 1;
722   int curChar, colN, key, i;
723   /****************************************************************************
724   * Write current field contents and position cursor.
725   ****************************************************************************/
726   if (!put_chars(wid,field,curLen,
727 		 fieldRow,fieldCol,FALSE,NORMAL)) return FALSE;
728   for (colN = firstCol + curLen; colN <= lastCol; colN++)
729      if (!put_chars(wid," ",1,fieldRow,colN,FALSE,NORMAL)) return FALSE;
730   curChar = 0;
731   if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
732   /****************************************************************************
733   * Read keystrokes until return/exit.
734   ****************************************************************************/
735   for (;;) {
736      if (!read_input(
737 #if defined(CURSESui)
738 		     wid,
739 #endif
740 			 &key,PASSTHRUri,TRUE)) return FALSE;
741      /*************************************************************************
742      * Check for an exit key.
743      *************************************************************************/
744      for (i = 0; exitKeys[i] != NUL; i++)
745 	if (key == exitKeys[i]) {
746 	  *exitKey = key;
747 	  return TRUE;
748 	}
749      /*************************************************************************
750      * Left arrow key.
751      *************************************************************************/
752      if (key == KB_LEFTARROW) {
753        if (curChar > 0) {
754 	 curChar--;
755 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
756        }
757        else
758 	 ring_bell ();
759        continue;
760      }
761      /*************************************************************************
762      * Right arrow key.
763      *************************************************************************/
764      if (key == KB_RIGHTARROW) {
765        if (curChar < curLen && curChar < fieldLen - 1) {
766 	 curChar++;
767 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
768        }
769        else
770 	 ring_bell ();
771        continue;
772      }
773      /*************************************************************************
774      * Delete key.
775      *************************************************************************/
776      if (key == KB_DELETE) {
777        if (curChar > 0) {
778 	 int charsToEnd = curLen - curChar;
779 	 memmove (&field[curChar-1], &field[curChar], charsToEnd + 1);
780 	 curLen--;
781 	 curChar--;
782 	 if (charsToEnd > 0)
783 	   if (!put_chars(wid,&field[curChar],charsToEnd,fieldRow,
784 			  firstCol+curChar,FALSE,NORMAL)) return FALSE;
785 	 if (!put_chars(wid," ",1,fieldRow,
786 			firstCol+curLen,FALSE,NORMAL)) return FALSE;
787 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
788        }
789        else
790 	 ring_bell ();
791        continue;
792      }
793      /*************************************************************************
794      * Move to start-of-line (SOL) key.
795      *************************************************************************/
796      if (key == moveToSOLkey) {
797        if (curChar > 0) {
798 	 curChar = 0;
799 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
800        }
801        else
802 	 ring_bell ();
803        continue;
804      }
805      /*************************************************************************
806      * Move to end-of-line (EOL) key.
807      *************************************************************************/
808      if (key == moveToEOLkey) {
809        if (curLen < fieldLen && curChar < curLen) {
810 	 curChar = curLen;
811 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
812 	 continue;
813        }
814        if (curLen == fieldLen && curChar < curLen - 1) {
815 	 curChar = curLen - 1;
816 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
817 	 continue;
818        }
819        ring_bell ();
820        continue;
821      }
822      /*************************************************************************
823      * Delete to start-of-line (SOL) key.
824      *************************************************************************/
825      if (key == deleteToSOLkey) {
826        if (curChar > 0) {
827 	 int charsToEnd = curLen - curChar;
828 	 int charsToStart = curChar + 1;
829 	 int colN, i;
830 	 memmove (field, &field[curChar], charsToEnd + 1);
831 	 curLen = charsToEnd;
832 	 curChar = 0;
833 	 if (!put_chars(wid,field,curLen,
834 			fieldRow,firstCol,FALSE,NORMAL)) return FALSE;
835 	 for (colN = firstCol+curLen, i = 0; i < charsToStart-1; colN++, i++)
836 	    if (!put_chars(wid," ",1,fieldRow,colN,FALSE,NORMAL)) return FALSE;
837 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
838        }
839        else
840 	 ring_bell ();
841        continue;
842      }
843      /*************************************************************************
844      * Delete to end-of-line (EOL) key.
845      *************************************************************************/
846      if (key == deleteToEOLkey) {
847        if (curChar < curLen) {
848 	 int charsToEnd = curLen - curChar;
849 	 int colN, i;
850 	 field[curChar] = NUL;
851 	 curLen = curChar;
852 	 for (colN = firstCol+curChar, i = 0; i < charsToEnd; colN++, i++)
853 	    if (!put_chars(wid," ",1,fieldRow,colN,FALSE,NORMAL)) return FALSE;
854 	 if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
855        }
856        else
857 	 ring_bell ();
858        continue;
859      }
860      /*************************************************************************
861      * Toggle insert mode key.
862      *************************************************************************/
863      if (key == toggleInsertModeKey) {
864        insertMode = (insertMode ? FALSE : TRUE);
865        continue;
866      }
867      /*************************************************************************
868      * Refresh key.
869      *************************************************************************/
870      if (key == refreshKey) {
871        repaint_screen ();
872        continue;
873      }
874      /*************************************************************************
875      * All the other keys (ignored if not printable).
876      *************************************************************************/
877      if (Printable(key)) {
878        if (insertMode) {
879 	 if (curLen < fieldLen) {
880 	   int charsToEnd = curLen - curChar;
881 	   memmove (&field[curChar+1], &field[curChar], charsToEnd + 1);
882 	   field[curChar] = key;
883 	   curLen++;
884 	   if (!put_chars(wid,&field[curChar],charsToEnd+1,fieldRow,
885 			  firstCol+curChar,FALSE,NORMAL)) return FALSE;
886 	   if (curChar < fieldLen - 1) curChar++;
887 	 }
888 	 else
889 	   ring_bell ();
890        }
891        else {
892 	 field[curChar] = key;
893 	 if (curChar == curLen) {
894 	   curLen++;
895 	   field[curLen] = NUL;
896 	 }
897 	 if (!put_chars(wid,&field[curChar],1,fieldRow,
898 			firstCol+curChar,FALSE,NORMAL)) return FALSE;
899 	 if (curChar < fieldLen - 1) curChar++;
900        }
901        if (!set_cursor_abs(wid,fieldRow,firstCol+curChar)) return FALSE;
902      }
903      else
904        ring_bell ();
905   }
906 }
907 
908 /******************************************************************************
909 * inq_cursor_mode.
910 ******************************************************************************/
911 
inq_cursor_mode(cursorMode)912 int inq_cursor_mode (cursorMode)
913 int *cursorMode;
914 {
915   *cursorMode = (cursorOn ? CURSORon : CURSORoff);
916   return TRUE;
917 }
918 
919 /******************************************************************************
920 * label_border.
921 ******************************************************************************/
922 
label_border(wid,label,rendition)923 int label_border(wid, label, rendition)
924 WINDOWid wid;
925 char *label;
926 int rendition;
927 {
928 #if defined(SMGui)
929   int len = (int) strlen(label);
930   static struct dsc$descriptor_s descr = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,NULL};
931   uLong position = SMG$K_TOP;
932   uLong rend = RenditionMapping(rendition);
933   int nRows, nCols;
934   long startRow = 1;
935   long startCol;
936   WindowSize (wid->id, &nRows, &nCols);
937   if (!wid->bordered) return FALSE;
938   if (len > nCols - 2) return FALSE;
939   startCol = (nCols - len) / 2 + 1;
940   descr.dsc$w_length = len;
941   descr.dsc$a_pointer = label;
942   if (StatusBad(smg$put_chars(&(wid->id),&descr,&startRow,&startCol,
943 			      NULL,&rend,NULL,NULL))) return FALSE;
944   return TRUE;
945 #endif
946 #if defined(CURSESui)
947   int len = (int) strlen (label);
948   int nRows, nCols, i, startCol;
949   WindowSize (wid->id, &nRows, &nCols);
950   if (!wid->bordered) return FALSE;
951   if (len > nCols - 2) return FALSE;
952   wattrset (wid->id, RenditionMapping(rendition));
953   startCol = (nCols - len) / 2;
954   for (i = 0; i < len; i++) mvwaddch (wid->id, 0, startCol + i, label[i]);
955   if (!RefreshWINDs(UPDATE_)) return FALSE;
956   return TRUE;
957 #endif
958 #if defined(COWui)
959   int len = (int) strlen (label);
960   int nCols = wid->id->nCols;
961   char rend = RenditionMapping (rendition);
962   char *chars = wid->id->chars,
963        *attrs = wid->id->attrs;
964   int i, startCol;
965   if (!wid->bordered) return FALSE;
966   if (len > nCols - 2) return FALSE;
967   startCol = (nCols - len) / 2;
968   for (i = 0; i < len; i++) {
969      chars[startCol+i] = label[i];
970      attrs[startCol+i] = rend;
971   }
972   if (!RefreshWINDs(UPDATE_)) return FALSE;
973   return TRUE;
974 #endif
975 }
976 
977 /******************************************************************************
978 * paste_virtual_display.
979 * It is illegal to paste a virtual display that is already pasted (use
980 * `repaste_virtual_display').  It is also illegal to paste a virtual display
981 * that is being batched.
982 ******************************************************************************/
983 
paste_virtual_display(wid,row,col)984 int paste_virtual_display (wid, row, col)
985 WINDOWid wid;
986 int row;
987 int col;
988 {
989 #if defined(SMGui)
990   long rowN = row + 1;
991   long colN = col + 1;
992   if (wid->pasted) return FALSE;
993   if (StatusBad(smg$paste_virtual_display(&(wid->id),&pbid,
994 					  &rowN,&colN,NULL))) return FALSE;
995   wid->pasted = TRUE;
996   if (!MoveWINDtoEnd(wid)) return FALSE;
997   return TRUE;
998 #endif
999 #if defined(CURSESui)
1000   if (wid->pasted) return FALSE;
1001   mvwin (wid->id, row, col);
1002   wid->pasted = TRUE;
1003   if (!MoveWINDtoEnd(wid)) return FALSE;
1004   if (!RefreshWINDs(UPDATE_)) return FALSE;
1005   return TRUE;
1006 #endif
1007 #if defined(COWui)
1008   if (wid->pasted) return FALSE;
1009   wid->id->atRowN = row;
1010   wid->id->atColN = col;
1011   wid->pasted = TRUE;
1012   if (!MoveWINDtoEnd(wid)) return FALSE;
1013   if (!RefreshWINDs(UPDATE_)) return FALSE;
1014   return TRUE;
1015 #endif
1016 }
1017 
1018 /******************************************************************************
1019 * put_chars.
1020 ******************************************************************************/
1021 
put_chars(wid,string,len,row,col,eraseMode,rendition)1022 int put_chars (wid, string, len, row, col, eraseMode, rendition)
1023 WINDOWid wid;
1024 char *string;
1025 int len;
1026 int row;
1027 int col;
1028 int eraseMode;
1029 int rendition;
1030 {
1031 #if defined(SMGui)
1032   static struct dsc$descriptor_s descr = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,NULL};
1033   uLong rend = RenditionMapping (rendition);
1034   long rowN = row + 1;
1035   long colN = col + 1;
1036   if (eraseMode == ERASE) {
1037     int nRows, nCols;
1038     long nChars, startCol;
1039     WindowSize (wid->id, &nRows, &nCols);
1040     nChars = (wid->bordered ? nCols - 2 : nCols);
1041     startCol = (wid->bordered ? 2 : 1);
1042     if (StatusBad(smg$erase_chars(&(wid->id),&nChars,
1043 				  &rowN,&startCol))) return FALSE;
1044   }
1045   descr.dsc$w_length = len;
1046   descr.dsc$a_pointer = string;
1047   if (StatusBad(smg$put_chars(&(wid->id),&descr,&rowN,
1048 			      &colN,NULL,&rend,NULL,NULL))) return FALSE;
1049   return TRUE;
1050 #endif
1051 #if defined(CURSESui)
1052   int nRows, nCols, colN, i;
1053   WindowSize (wid->id, &nRows, &nCols);
1054   if (eraseMode == ERASE) {
1055     wattrset (wid->id, RenditionMapping(NORMAL));
1056     for (colN = 1; colN <= nCols - 2; colN++) mvwaddch (wid->id,row,colN,' ');
1057   }
1058   wattrset (wid->id, RenditionMapping(rendition));
1059   for (i = 0; i < len; i++) mvwaddch (wid->id, row, col + i, string[i]);
1060   if (!RefreshWINDs(UPDATE_)) return FALSE;
1061   return TRUE;
1062 #endif
1063 #if defined(COWui)
1064   short nCols = wid->id->nCols;
1065   char rend;
1066   char *chars = wid->id->chars;
1067   char *attrs = wid->id->attrs;
1068   int colN, i, charN;
1069   if (eraseMode == ERASE) {
1070     rend = RenditionMapping (NORMAL);
1071     for (colN = 1; colN <= nCols - 2; colN++) {
1072        charN = (row * nCols) + colN;
1073        chars[charN] = ' ';
1074        attrs[charN] = rend;
1075     }
1076   }
1077   rend = RenditionMapping (rendition);
1078   for (i = 0; i < len; i++) {
1079      charN = (row * nCols) + (col + i);
1080      chars[charN] = string[i];
1081      attrs[charN] = rend;
1082   }
1083   if (!RefreshWINDs(UPDATE_)) return FALSE;
1084   return TRUE;
1085 #endif
1086 }
1087 
1088 /******************************************************************************
1089 * read_display.
1090 * Use only by CDFlist and CDFwalk (ie. expendable).
1091 ******************************************************************************/
1092 
read_display(wid,row,string)1093 int read_display (wid, row, string)
1094 WINDOWid wid;
1095 int row;
1096 char *string;
1097 {
1098 #if defined(SMGui)
1099   static struct dsc$descriptor_s descr = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,NULL};
1100   int nRows, nCols; long rowN = row + 1; char *stringT;
1101   WindowSize (wid->id, &nRows, &nCols);
1102   stringT = (char *) cdf_AllocateMemory (nCols, FatalError);
1103   descr.dsc$w_length = nCols;
1104   descr.dsc$a_pointer = stringT;
1105   if (StatusBad(smg$read_from_display(&(wid->id),&descr,NULL,&rowN))) {
1106     cdf_FreeMemory (stringT, FatalError);
1107     return FALSE;
1108   }
1109   if (wid->bordered) {
1110     memmove (string, &stringT[1], nCols-2);
1111     string[nCols-2] = NUL;
1112   }
1113   else {
1114     memmove (string, stringT, nCols);
1115     string[nCols] = NUL;
1116   }
1117   cdf_FreeMemory (stringT, FatalError);
1118   return TRUE;
1119 #endif
1120 #if defined(CURSESui)
1121   int colN, charN, nRows, nCols, nChars, startCol;
1122   WindowSize (wid->id, &nRows, &nCols);
1123   nChars = (wid->bordered ? nCols - 2 : nCols);
1124   startCol = (wid->bordered ? 1 : 0);
1125   for (colN = startCol, charN = 0; charN < nChars; colN++, charN++)
1126      string[charN] = (char) mvwinch (wid->id, row, colN);
1127   string[nChars] = NUL;
1128   return TRUE;
1129 #endif
1130 #if defined(COWui)
1131   int charN, i;
1132   int nCols = wid->id->nCols;
1133   int nChars = (wid->bordered ? nCols - 2 : nCols);
1134   int startCol = (wid->bordered ? 1 : 0);
1135   char *chars = wid->id->chars;
1136   for (i = 0; i < nChars; i++) {
1137      charN = (row * nCols) + (startCol + i);
1138      string[i] = chars[charN];
1139   }
1140   string[nChars] = NUL;
1141   return TRUE;
1142 #endif
1143 }
1144 
1145 /******************************************************************************
1146 * read_input.
1147 *
1148 * TRUE is returned if a key was read.  FALSE is returned if blocking is
1149 * disabled and a key is not available or if an error occurred.
1150 *
1151 * The `wid' parameter is only used on CURSES-based systems.  This is because
1152 * `getch' on POSIXshell systems (VAX and DEC Alpha) would move the cursor to
1153 * `0,0' (which isn't where it should be).  `wgetch' is used instead because
1154 * the cursor will be positioned in the proper place in the window.  If
1155 * `wgetch' (on POSIXshell systems) moves the cursor at least it will move to
1156 * the right place (which is probably where it already is) and not to `0,0'.
1157 ******************************************************************************/
1158 
read_input(wid,tcode,mode,block)1159 int read_input (
1160 #if defined(CURSESui)
1161 		wid,
1162 #endif
1163 		     tcode, mode, block)
1164 #if defined(CURSESui)
1165 WINDOWid wid;
1166 #endif
1167 int *tcode;		/* Out: key entered. */
1168 int mode;		/* Case conversion mode. */
1169 Logical block;		/* Block until key available? */
1170 {
1171 #if defined(SMGui)
1172   /****************************************************************************
1173   * SMG.
1174   ****************************************************************************/
1175   uShort terminator_code;
1176   if (!block) {
1177     if (keyWaiting == 0) return FALSE;
1178   }
1179   if (StatusBad(smg$read_keystroke(&kbid,&terminator_code,
1180 				   NULL,NULL,NULL,NULL,NULL))) return FALSE;
1181   *tcode = terminator_code;
1182   if (keyWaiting > 0) keyWaiting--;
1183   if (ABORTkey(*tcode)) {
1184     set_cursor_mode (CURSORon);
1185     delete_pasteboard (ERASE);
1186     cdf_FreeMemory (NULL, FatalError);
1187     Exit;
1188   }
1189   switch (mode) {
1190     case PASSTHRUri: break;
1191     case TOUPPERri: *tcode = MakeUpper (*tcode); break;
1192     case TOLOWERri: *tcode = MakeLower (*tcode); break;
1193   }
1194   return TRUE;
1195 #endif
1196   /****************************************************************************
1197   * Curses.
1198   ****************************************************************************/
1199 #if defined(CURSESui)
1200   if (!block) {
1201 #if defined(unix)
1202     fd_set rset;
1203     static struct timeval tv = { 0L, 0L };
1204     FD_ZERO (&rset);
1205     FD_SET (STDIN_FILENO, &rset);
1206     if (select(STDIN_FILENO+1,
1207 #if defined(hpux)
1208 			      (int *)	/* HP-UX has this as an `int *'. */
1209 #endif
1210 				     &rset,NULL,NULL,&tv) == 0) return FALSE;
1211 #endif
1212 #if defined(dos)
1213     if (!kbhit()) return FALSE;
1214 #endif
1215   }
1216   *tcode = wgetch (wid->id);
1217   if (ABORTkey(*tcode)) {
1218     set_cursor_mode (CURSORon);
1219     delete_pasteboard (ERASE);
1220     cdf_FreeMemory (NULL, FatalError);
1221     Exit;
1222   }
1223   switch (*tcode) {
1224 #if defined(sgi)
1225     case SGI_CONSOLE_RETURN: *tcode = KB_RETURN; break;
1226 #endif
1227 #if defined(posixSHELL)
1228     case POSIX_SHELL_DELETE: *tcode = KB_DELETE; break;
1229 #endif
1230 #if defined(hpux)
1231     case HPUX_DELETE: *tcode = KB_DELETE; break;
1232 #endif
1233 #if defined(AIX)
1234     case AIX_RETURN: *tcode = KB_RETURN; break;
1235     case AIX_DELETE: *tcode = KB_DELETE; break;
1236 #endif
1237 #if defined(__CYGWIN__)
1238     case CYGWIN_DELETE: *tcode = KB_DELETE; break;
1239 #endif
1240 #if defined(__MINGW32__)
1241     case MINGW32_DELETE: *tcode = KB_DELETE; break;
1242 #endif
1243     default: break;
1244   }
1245   switch (mode) {
1246     case PASSTHRUri: break;
1247     case TOUPPERri: *tcode = MakeUpper (*tcode); break;
1248     case TOLOWERri: *tcode = MakeLower (*tcode); break;
1249   }
1250 #if INTERPRET_ESC_SEQUENCES
1251   if (*tcode == ESC) {
1252     int key1 = wgetch (wid->id);
1253     int key2 = wgetch (wid->id);
1254     switch (key1) {
1255       case 'O':
1256 	switch (key2) {
1257 	  case 'A': *tcode = KEY_UP; break;
1258 	  case 'B': *tcode = KEY_DOWN; break;
1259 	  case 'C': *tcode = KEY_RIGHT; break;
1260 	  case 'D': *tcode = KEY_LEFT; break;
1261 	  default: break;
1262 	}
1263 	break;
1264       default:
1265 	break;
1266     }
1267   }
1268 #endif
1269   return TRUE;
1270 #endif
1271   /****************************************************************************
1272   * COW.
1273   ****************************************************************************/
1274 #if defined(COWui)
1275 #if defined(win32)
1276   MSG msg;
1277   for (;;) {
1278 	  if (!PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
1279 		  if (block) continue;
1280 		  return FALSE;
1281 	  }
1282 	  if (msg.message == WM_KEYDOWN) {
1283 	    int scanCode = (msg.lParam & 0x00FF0000) >> 16;
1284 	    switch (scanCode) {
1285 	      case 0x4B:
1286 		*tcode = KB_LEFTARROW;
1287 		return TRUE;
1288 	      case 0x4D:
1289 		*tcode = KB_RIGHTARROW;
1290 		return TRUE;
1291 	      case 0x48:
1292 		*tcode = KB_UPARROW;
1293 		return TRUE;
1294 	      case 0x50:
1295 		*tcode = KB_DOWNARROW;
1296 		return TRUE;
1297 	    }
1298 	  }
1299 	  if (msg.message == WM_CHAR) {
1300 		  *tcode = (int) msg.wParam;
1301 		 switch (mode) {
1302 		   case PASSTHRUri: break;
1303 		   case TOUPPERri: *tcode = MakeUpper (*tcode); break;
1304 		   case TOLOWERri: *tcode = MakeLower (*tcode); break;
1305 		 }
1306 		  return TRUE;
1307 	  }
1308 	  if (!TranslateMessage(&msg)) DispatchMessage (&msg);
1309   }
1310 #endif
1311 #if defined(mac)
1312   EventRecord event;
1313   for (;;) {
1314      SystemTask ();
1315      GetNextEvent(everyEvent,&event);
1316      switch (event.what) {
1317        /*********************************************************************
1318        * Null event.
1319        *********************************************************************/
1320        case nullEvent: {
1321 	 WindowPtr whichWindow;
1322 	 switch (FindWindow(event.where,&whichWindow)) {
1323 	   case inContent:
1324 	     SetCursor (CDF_CURSOR);
1325 	     break;
1326 	   default:
1327              SetCursor (ARROW_CURSOR);
1328              break;
1329          }
1330          break;
1331        }
1332        /*********************************************************************
1333        * Mouse down event.
1334        *********************************************************************/
1335        case mouseDown: {
1336 	 WindowPtr whichWindow;
1337 	 switch (FindWindow(event.where,&whichWindow)) {
1338 	   case inMenuBar: {
1339 	     long tempL = MenuSelect (event.where);
1340 	     short menuId = HighSHORTinLONG (tempL);
1341 	     short itemN = LowSHORTinLONG (tempL);
1342 	     switch (menuId) {
1343 	       case APPLEmi:
1344 	         switch (itemN) {
1345 	           case ABOUTin:
1346 	             DisplayAbout ();
1347 	             break;
1348 	           default: {
1349 	             Str255 name;
1350 	             GetItem (appleMenuHfsi, itemN, name);
1351 	             OpenDeskAcc (name);
1352 	             SetPort (fsiWindowP);
1353 	             break;
1354 	           }
1355 	         }
1356 	         break;
1357 	     }
1358 	     HiliteMenu (0);
1359 	     break;
1360 	   }
1361 	   case inDrag: {
1362              RectPtr screen = &qd.screenBits.bounds; Rect dRect;
1363              dRect.top = screen->top + 40;
1364              dRect.left = screen->left + 40;
1365              dRect.bottom = screen->bottom - 40;
1366              dRect.right = screen->right - 40;
1367              DragWindow (whichWindow, event.where, &dRect);
1368              break;
1369 	   }
1370 	   case inSysWindow:
1371 	     SystemClick (&event, whichWindow);
1372 	     break;
1373 	 }
1374 	 break;
1375        }
1376        /*********************************************************************
1377        * Key down event.
1378        *********************************************************************/
1379        case keyDown:
1380        case autoKey: {
1381 	 *tcode = (int) (event.message & charCodeMask);
1382 	 if (ABORTkeyMAC(event)) {
1383 	   delete_pasteboard (ERASE);
1384 	   cdf_FreeMemory (NULL, FatalError);
1385 	   Exit;
1386 	 }
1387 	 /*******************************************************************
1388 	 * If the command key was held down, convert the character to the
1389 	 * corresponding control character.
1390 	 *******************************************************************/
1391 	 if ((event.modifiers & cmdKey) != 0 &&
1392 	     'a' <= *tcode && *tcode <= 'z') *tcode = *tcode & 0x1F;
1393 	 /*******************************************************************
1394 	 * Convert to uppercase/lowercase if requested.
1395 	 *******************************************************************/
1396 	 switch (mode) {
1397 	   case PASSTHRUri: break;
1398 	   case TOUPPERri: *tcode = MakeUpper (*tcode); break;
1399 	   case TOLOWERri: *tcode = MakeLower (*tcode); break;
1400 	 }
1401 	 return TRUE;
1402        }
1403        /*********************************************************************
1404        * Active event.
1405        *********************************************************************/
1406        case activateEvt:
1407          if ((event.modifiers & activeFlag) != 0) {	/* Activate. */
1408            SetCursor (CDF_CURSOR);
1409          }
1410          else {						/* Deactivate. */
1411 	   /* Nothing to be done. */
1412          }
1413          break;
1414        /*********************************************************************
1415        * Update event.
1416        *********************************************************************/
1417        case updateEvt:
1418 	 BeginUpdate ((WindowPtr) event.message);
1419 	 if (!RefreshWINDs(SOFT_)) return FALSE;
1420 	 EndUpdate ((WindowPtr) event.message);
1421          break;
1422      }
1423      if (!block) return FALSE;
1424   }
1425 #endif
1426 #endif
1427 }
1428 
1429 /******************************************************************************
1430 * repaint_screen.
1431 ******************************************************************************/
1432 
repaint_screen()1433 int repaint_screen () {
1434 #if defined(SMGui)
1435   if (StatusBad(smg$repaint_screen(&pbid))) return FALSE;
1436   return TRUE;
1437 #endif
1438 #if defined(CURSESui)
1439 #if defined(posixSHELL)
1440   wrefresh (stdscr);
1441 #else
1442   wrefresh (curscr);
1443 #endif
1444   return TRUE;
1445 #endif
1446 #if defined(COWui)
1447   if (!RefreshWINDs(HARD_)) return FALSE;
1448   return TRUE;
1449 #endif
1450 }
1451 
1452 /******************************************************************************
1453 * repaste_virtual_display.
1454 ******************************************************************************/
1455 
repaste_virtual_display(wid,row,col)1456 int repaste_virtual_display (wid, row, col)
1457 WINDOWid wid;
1458 int row;
1459 int col;
1460 {
1461 #if defined(SMGui)
1462   long rowN = row + 1;
1463   long colN = col + 1;
1464   if (StatusBad(smg$repaste_virtual_display(&(wid->id),&pbid,
1465 					    &rowN,&colN,NULL))) return FALSE;
1466   if (!MoveWINDtoEnd(wid)) return FALSE;
1467   return TRUE;
1468 #endif
1469 #if defined(CURSESui)
1470   if (!wid->pasted) return FALSE;
1471   mvwin (wid->id, row, col);
1472   if (!MoveWINDtoEnd(wid)) return FALSE;
1473   if (!RefreshWINDs(UPDATE_)) return FALSE;
1474   return TRUE;
1475 #endif
1476 #if defined(COWui)
1477   if (!wid->pasted) return FALSE;
1478   wid->id->atRowN = row;
1479   wid->id->atColN = col;
1480   if (!MoveWINDtoEnd(wid)) return FALSE;
1481   if (!RefreshWINDs(UPDATE_)) return FALSE;
1482   return TRUE;
1483 #endif
1484 }
1485 
1486 /******************************************************************************
1487 * ring_bell.
1488 ******************************************************************************/
1489 
ring_bell()1490 int ring_bell () {
1491 #if defined(SMGui)
1492   long nRows = 1;
1493   long nCols = 1;
1494   long rowN = 1;
1495   long colN = 1;
1496   long cursorRow, cursorCol;
1497   LocalId id, cursorId;
1498   if (StatusBad(smg$find_cursor_display(&pbid,&cursorId,
1499 					NULL,NULL))) return FALSE;
1500   if (cursorId != 0) cursorRow = smg$cursor_row (&cursorId);
1501   if (cursorId != 0) cursorCol = smg$cursor_column (&cursorId);
1502   if (StatusBad(smg$begin_pasteboard_update(&pbid))) return FALSE;
1503   if (StatusBad(smg$create_virtual_display(&nRows,&nCols,&id,
1504 					   NULL,NULL,NULL))) return FALSE;
1505   if (StatusBad(smg$paste_virtual_display(&id,&pbid,
1506 					  &rowN,&colN,NULL))) return FALSE;
1507   if (StatusBad(smg$ring_bell(&id))) return FALSE;
1508   if (StatusBad(smg$delete_virtual_display(&id))) return FALSE;
1509   if (StatusBad(smg$end_pasteboard_update(&pbid))) return FALSE;
1510   if (cursorId != 0)
1511     if (StatusBad(smg$set_cursor_abs(&cursorId,
1512 				     &cursorRow,
1513 				     &cursorCol))) return FALSE;
1514   return TRUE;
1515 #endif
1516 #if defined(CURSESui)
1517   beep ();
1518   return TRUE;
1519 #endif
1520 #if defined(COWui)
1521 #if defined(win32)
1522    Beep ((DWORD) 800, (DWORD) 150);
1523 #endif
1524 #if defined(mac)
1525   short ticks = 1;
1526   SysBeep (ticks);
1527 #endif
1528   return TRUE;
1529 #endif
1530 }
1531 
1532 /******************************************************************************
1533 * set_cursor_abs.
1534 *
1535 * CURSES:
1536 * After setting the cursor position in the specified window, only refresh that
1537 * window.  Refreshing all windows (using `RefreshWINDs') will put the physical
1538 * screen cursor where the `top' window's virtual cursor is.
1539 ******************************************************************************/
1540 
set_cursor_abs(wid,row,col)1541 int set_cursor_abs (wid, row, col)
1542 WINDOWid wid;
1543 int row;
1544 int col;
1545 {
1546 #if defined(SMGui)
1547   long rowN = row + 1;
1548   long colN = col + 1;
1549   if (StatusBad(smg$set_cursor_abs(&(wid->id),&rowN,&colN))) return FALSE;
1550   return TRUE;
1551 #endif
1552 #if defined(CURSESui)
1553   wmove (wid->id, row, col);
1554   wrefresh (wid->id);
1555   return TRUE;
1556 #endif
1557 #if defined(COWui)
1558   /****************************************************************************
1559   * Undisplay current cursor (if it exists and is visible).
1560   ****************************************************************************/
1561   if (cursorOn && cursorWIND != NULL && cursorWIND->pasted &&
1562       !CharOccluded(cursorWIND,cursorRow,cursorCol)) {
1563 #if defined(mac)
1564     InvertCursor (cursorWIND, cursorRow, cursorCol);
1565 #endif
1566 #if defined(win32)
1567     SetCursorPosition (-1, -1);
1568 #endif
1569   }
1570   /****************************************************************************
1571   * Set/display new cursor (if it is visible).
1572   ****************************************************************************/
1573   cursorWIND = wid;
1574   cursorRow = row;
1575   cursorCol = col;
1576   if (cursorOn && cursorWIND != NULL && cursorWIND->pasted &&
1577       !CharOccluded(cursorWIND,cursorRow,cursorCol)) {
1578 #if defined(mac)
1579     InvertCursor (cursorWIND, cursorRow, cursorCol);
1580 #endif
1581 #if defined(win32)
1582     SetCursorPosition (cursorWIND->id->atRowN + cursorRow,
1583 		       cursorWIND->id->atColN + cursorCol);
1584 #endif
1585   }
1586   return TRUE;
1587 #endif
1588 }
1589 
1590 /******************************************************************************
1591 * set_cursor_mode.
1592 ******************************************************************************/
1593 
set_cursor_mode(cursorMode)1594 int set_cursor_mode (cursorMode)
1595 int cursorMode;                         /* CURSORon/CURSORoff */
1596 {
1597 #if defined(SMGui)
1598   uLong mode = (cursorMode == CURSORon ? SMG$M_CURSOR_ON :
1599 						 SMG$M_CURSOR_OFF);
1600   if (StatusBad(smg$set_cursor_mode(&pbid,&mode))) return FALSE;
1601   cursorOn = (cursorMode == CURSORon);
1602   return TRUE;
1603 #endif
1604 #if defined(CURSESui)
1605 #if defined(unix) || defined(posixSHELL)
1606 #if CURS_SETavail
1607   int visibility = (cursorMode == CURSORon ? 1 : 0);
1608   curs_set (visibility);
1609 #endif
1610   cursorOn = (cursorMode == CURSORon);
1611   return TRUE;
1612 #endif
1613 #if defined(dos)
1614   if (cursorMode == CURSORon)
1615     curson ();
1616   else
1617     cursoff ();
1618   cursorOn = (cursorMode == CURSORon);
1619   return TRUE;
1620 #endif
1621 #endif
1622 #if defined(COWui)
1623   /****************************************************************************
1624   * If the new mode is different than the old mode, set the new mode and
1625   * invert the current cursor (if one exists and is visible).
1626   ****************************************************************************/
1627   if (cursorMode != BOO(cursorOn,CURSORon,CURSORoff)) {
1628     cursorOn = (cursorMode == CURSORon);
1629     if (cursorWIND != NULL && cursorWIND->pasted &&
1630         !CharOccluded(cursorWIND,cursorRow,cursorCol)) {
1631 #if defined(mac)
1632       InvertCursor (cursorWIND, cursorRow, cursorCol);
1633 #endif
1634 #if defined(win32)
1635       SetCursorPosition (BOO(cursorOn,cursorWIND->id->atRowN + cursorRow,-1),
1636 			 BOO(cursorOn,cursorWIND->id->atColN + cursorCol,-1));
1637 #endif
1638     }
1639   }
1640   return TRUE;
1641 #endif
1642 }
1643 
1644 /******************************************************************************
1645 * unpaste_virtual_display.
1646 ******************************************************************************/
1647 
unpaste_virtual_display(wid)1648 int unpaste_virtual_display (wid)
1649 WINDOWid wid;
1650 {
1651 #if defined(SMGui)
1652    if (StatusBad(smg$unpaste_virtual_display(&(wid->id),&pbid))) return FALSE;
1653    wid->pasted = FALSE;
1654    return TRUE;
1655 #else
1656 #  if defined(CURSESui)
1657      LocalId tempId;
1658      int nRows, nCols, row, col;
1659      WindowSize (wid->id, &nRows, &nCols);
1660      WindowLocation (wid->id, &row, &col);
1661      tempId = newwin (nRows, nCols, row, col);
1662      if (tempId == NULL) return FALSE;
1663      wattrset (tempId, RenditionMapping(BLACK));
1664      EraseWindow (tempId);
1665      wnoutrefresh (tempId);
1666      delwin (tempId);
1667      wid->pasted = FALSE;
1668      if (!RefreshWINDs(UPDATE_)) return FALSE;
1669      return TRUE;
1670 #  else
1671 #    if defined(COWui)
1672        wid->pasted = FALSE;
1673        if (!RefreshWINDs(UPDATE_)) return FALSE;
1674        return TRUE;
1675 #    else
1676        return TRUE;
1677 #    endif
1678 #  endif
1679 #endif
1680 }
1681 
1682 /******************************************************************************
1683 * zzzzz.
1684 * Sleep, get it?
1685 ******************************************************************************/
1686 
zzzzz(seconds)1687 int zzzzz (seconds)
1688 double seconds;
1689 {
1690 #if defined(SMGui)					/* ie. VMS */
1691 #if defined(alphavmsI)
1692   time_t start_time, current_time;
1693   time (&start_time);
1694   time (&current_time);
1695   while (current_time - start_time < seconds + 1.0) time (&current_time);
1696 #else
1697   float seconds4 = seconds;
1698   if (StatusBad(lib$wait(&seconds4))) return FALSE;
1699 #endif
1700   return TRUE;
1701 #endif
1702 #if defined(CURSESui)
1703 #if defined(unix)
1704   int ms = (int) seconds;
1705 #if !defined(__QNX__)		/* Due to a `ncurses' bug under QNX. */
1706   ms *= 1000;
1707 #endif
1708   napms (ms);
1709   return TRUE;
1710 #endif
1711 #if defined(MICROSOFTC) || defined(posixSHELL)
1712   time_t start_time, current_time;
1713   time (&start_time);
1714   time (&current_time);
1715   while (current_time - start_time < seconds + 1.0) time (&current_time);
1716   return TRUE;
1717 #endif
1718 #if defined(BORLANDC)
1719   sleep ((uInt) seconds + 0.5);
1720   return TRUE;
1721 #endif
1722 #endif
1723 #if defined(COWui)
1724 #if defined(win32)
1725   MSG msg;
1726   UINT timerId = SetTimer (NULL, 0, (UINT) (1000 * seconds), NULL);
1727   for (;;) {
1728 	  GetMessage (&msg, NULL, 0, 0);
1729 	  if (msg.message == WM_TIMER) {
1730 		  KillTimer (NULL, timerId);
1731 		  break;
1732 	  }
1733 	  DispatchMessage (&msg);
1734   }
1735 #endif
1736 #if defined(mac)
1737   EventRecord event; long untilTick; short nullEventMask = 0;
1738   EventAvail (nullEventMask, &event);
1739   untilTick = event.when + (long) (seconds * 60);
1740   for (;;) {
1741      EventAvail (nullEventMask, &event);
1742      if (event.when > untilTick) break;
1743   }
1744 #endif
1745   return TRUE;
1746 #endif
1747 }
1748 
1749 /******************************************************************************
1750 * AddWIND.  Add a WIND to the linked list (at the end).
1751 ******************************************************************************/
1752 
AddWIND(id,pasted,bordered)1753 static WINDOWid AddWIND (id, pasted, bordered)
1754 LocalId id;
1755 Logical pasted;
1756 Logical bordered;
1757 {
1758   WINDOWid newWIND, tW;
1759   newWIND = (WINDOWid) cdf_AllocateMemory (sizeof(WIND), FatalError);
1760   if (WINDhead == NULL)
1761     WINDhead = newWIND;
1762   else {
1763     tW = WINDhead;
1764     while (tW->next != NULL) tW = tW->next;
1765     tW->next = newWIND;
1766   }
1767   newWIND->id = id;
1768   newWIND->pasted = pasted;
1769   newWIND->bordered = bordered;
1770   newWIND->next = NULL;
1771   return newWIND;
1772 }
1773 
1774 /******************************************************************************
1775 * MoveWINDtoEnd.
1776 * Move a WIND to the end of the linked list.  The case where WIND is already
1777 * at the end of the linked list is handled (but not as a special case).
1778 ******************************************************************************/
1779 
MoveWINDtoEnd(wid)1780 static Logical MoveWINDtoEnd (wid)
1781 WINDOWid wid;
1782 {
1783   WINDOWid tW = WINDhead;
1784   WINDOWid prevW = NULL;
1785   while (tW != NULL) {
1786     if (tW == wid) {
1787       if (prevW == NULL)
1788 	WINDhead = tW->next;
1789       else
1790 	prevW->next = tW->next;
1791       if (WINDhead == NULL)
1792 	WINDhead = tW;
1793       else {
1794 	WINDOWid sW = WINDhead;
1795 	while (sW->next != NULL) sW = sW->next;
1796 	sW->next = tW;
1797 	tW->next = NULL;
1798       }
1799       return TRUE;
1800     }
1801     prevW = tW;
1802     tW = tW->next;
1803   }
1804   return FALSE;			/* Wasn't found. */
1805 }
1806 
1807 /******************************************************************************
1808 * DeleteWIND.  Delete a WIND from the linked list.
1809 ******************************************************************************/
1810 
DeleteWIND(wid)1811 static Logical DeleteWIND (wid)
1812 WINDOWid wid;
1813 {
1814   WINDOWid tW = WINDhead;
1815   WINDOWid prevW = NULL;
1816   while (tW != NULL) {
1817     if (tW == wid) {
1818 #if defined(SMGui)
1819       if (StatusBad(smg$delete_virtual_display(&(tW->id)))) return FALSE;
1820 #endif
1821 #if defined(CURSESui)
1822       if (tW->pasted) {
1823 	wattrset (tW->id, RenditionMapping(BLACK));
1824 	EraseWindow (tW->id);
1825 	wnoutrefresh (tW->id);
1826       }
1827       delwin (tW->id);
1828 #endif
1829 #if defined(COWui)
1830       if (tW == cursorWIND) cursorWIND = NULL;
1831 #endif
1832       if (prevW == NULL)
1833 	WINDhead = tW->next;
1834       else
1835 	prevW->next = tW->next;
1836 #if defined(COWui)
1837       cdf_FreeMemory (tW->id->chars, FatalError);
1838       cdf_FreeMemory (tW->id->attrs, FatalError);
1839       cdf_FreeMemory (tW->id, FatalError);
1840 #endif
1841       cdf_FreeMemory (tW, FatalError);
1842 #if defined(CURSESui) || defined(COWui)
1843       if (!RefreshWINDs(UPDATE_)) return FALSE;
1844 #endif
1845       return TRUE;
1846     }
1847     prevW = tW;
1848     tW = tW->next;
1849   }
1850   return FALSE;			/* Wasn't found. */
1851 }
1852 
1853 /******************************************************************************
1854 * DeleteWINDs.  Delete all of the WINDs.
1855 ******************************************************************************/
1856 
DeleteWINDs()1857 static Logical DeleteWINDs () {
1858   while (WINDhead != NULL) {
1859     if (!DeleteWIND(WINDhead)) return FALSE;
1860   }
1861   return TRUE;
1862 }
1863 
1864 /******************************************************************************
1865 * RefreshWINDs.
1866 * Refresh all windows (that are pasted).  Note that this has no affect if
1867 * updates are being batched (with begin/end_pasteboard_update).
1868 ******************************************************************************/
1869 
1870 #if defined(CURSESui)
RefreshWINDs(level)1871 static Logical RefreshWINDs (level)
1872 int level;
1873 {
1874   if (batchCount < 1) {
1875     WINDOWid tW;
1876     switch (level) {
1877       case HARD_:
1878       case SOFT_:
1879       case UPDATE_:
1880 	/* Do nothing if CURSES. */
1881 	break;
1882     }
1883     tW = WINDhead;
1884     while (tW != NULL) {
1885       if (tW->pasted) {
1886 	touchwin (tW->id);
1887 	wnoutrefresh (tW->id);
1888       }
1889       tW = tW->next;
1890     }
1891     doupdate ();
1892   }
1893   return TRUE;
1894 }
1895 #endif
1896 
1897 #if defined(COWui)
RefreshWINDs(level)1898 static Logical RefreshWINDs (level)
1899 int level;
1900 {
1901   WINDOWid tW;
1902   char *savePtr;
1903   int nChars = NUMfsiROWS * NUMfsiCOLS, rowN, windCharN, pbCharN;
1904   /****************************************************************************
1905   * If updates are being batched, do nothing.
1906   ****************************************************************************/
1907   if (batchCount > 0) return TRUE;
1908   /****************************************************************************
1909   * Check level of refresh.
1910   *  Hard:   Erases window and force all non-blank/non-normal character
1911   *	     positions to be redrawn.  This will causes the characters in
1912   *	     the window to "flash" (off then on).  In this case the cursor
1913   *          does not need to be turned off.
1914   *  Soft:   Force all character positions to be redrawn.  The characters
1915   *          should not "flash".  In this case the cursor does not need to
1916   *          be turned off (it will be overwritten by a character).
1917   *  Update: In this case the cursor does need to be turned off if it is
1918   *          actually visible (not if it should be visible).  This is
1919   *	     because the operations before this refresh could have occluded
1920   *	     the cursor.
1921   ****************************************************************************/
1922   switch (level) {
1923     case HARD_: {
1924       int nChars = NUMfsiROWS * NUMfsiCOLS;
1925 #if defined(win32)
1926       /* Jeff...maybe nothing needs to be done. */
1927 #endif
1928 #if defined(mac)
1929       Rect eraseRect = { 0, 0, WINDOWfsiHEIGHT, WINDOWfsiWIDTH };
1930       EraseRect (&eraseRect);
1931 #endif
1932       memmove (pbCurrentChars, pbNullChars, nChars);
1933       memmove (pbCurrentAttrs, pbNormalAttrs, nChars);
1934       break;
1935     }
1936     case SOFT_: {
1937       int nChars = NUMfsiROWS * NUMfsiCOLS;
1938       memmove (pbCurrentChars, pbNullChars, nChars);
1939       memmove (pbCurrentAttrs, pbNormalAttrs, nChars);
1940       break;
1941     }
1942     case UPDATE_:
1943 #if defined(mac)
1944       if (cursorVisible) InvertCursor (cursorWIND, cursorRow, cursorCol);
1945 #endif
1946 #if defined(win32)
1947       SetCursorPosition (-1, -1);
1948 #endif
1949       break;
1950   }
1951   /****************************************************************************
1952   * Reset new characters/attributes...
1953   ****************************************************************************/
1954   memmove (pbNewChars, pbBlankChars, nChars);
1955   memmove (pbNewAttrs, pbNormalAttrs, nChars);
1956   /****************************************************************************
1957   * ...and then generate what the window should look like.
1958   ****************************************************************************/
1959   tW = WINDhead;
1960   while (tW != NULL) {
1961     if (tW->pasted) {
1962       for (rowN = 0; rowN < tW->id->nRows; rowN++) {
1963 	 windCharN = rowN * tW->id->nCols;
1964 	 pbCharN = ((tW->id->atRowN + rowN) * NUMfsiCOLS) + tW->id->atColN;
1965 	 memmove (&pbNewChars[pbCharN], &(tW->id->chars[windCharN]),
1966 		  tW->id->nCols);
1967 	 memmove (&pbNewAttrs[pbCharN], &(tW->id->attrs[windCharN]),
1968 		  tW->id->nCols);
1969       }
1970     }
1971     tW = tW->next;
1972   }
1973   /****************************************************************************
1974   * Redraw the characters/attributes which have changed.
1975   ****************************************************************************/
1976 #if defined(win32)
1977   TransferTextAttrs (pbNewChars, pbNewAttrs);
1978 #endif
1979 #if defined(mac)
1980   for (rowN = 0; rowN < NUMfsiROWS; rowN++) {
1981      rowCharN = rowN * NUMfsiCOLS;
1982      if (memcmp(&pbNewChars[rowCharN],
1983 		&pbCurrentChars[rowCharN],NUMfsiCOLS) != 0 ||
1984          memcmp(&pbNewAttrs[rowCharN],
1985 		&pbCurrentAttrs[rowCharN],NUMfsiCOLS) != 0) {
1986        startN = rowCharN;
1987        while (pbNewChars[startN] == pbCurrentChars[startN] &&
1988 	      pbNewAttrs[startN] == pbCurrentAttrs[startN]) startN++;
1989        endN = rowCharN + NUMfsiCOLS - 1;
1990        while (pbNewChars[startN] == pbCurrentChars[startN] &&
1991 	      pbNewAttrs[startN] == pbCurrentAttrs[startN]) endN--;
1992        for (;;) {
1993 	  upToN = startN;
1994 	  thisAttr = pbNewAttrs[startN];
1995 	  while (upToN+1 <= endN && pbNewAttrs[upToN+1] == thisAttr &&
1996 		 !LINEdrawingCHAR(pbNewChars[upToN]) &&
1997 	         !LINEdrawingCHAR(pbNewChars[upToN+1])) upToN++;
1998 	  if (BITSET(thisAttr,REVERSEbit))
1999 	    TextMode (notSrcCopy);
2000 	  else
2001 	    TextMode (srcCopy);
2002 	  if (BITSET(thisAttr,BOLDbit))
2003 	    TextFace (bold);
2004 	  else
2005 	    TextFace (0);
2006 	  /* BLINKINGbit is not yet supported. */
2007 	  startX = (FONTfsiWIDTH * (startN % NUMfsiCOLS)) + MARGINfsiSIZE;
2008 	  startY = (FONTfsiHEIGHT * rowN) + MARGINfsiSIZE;
2009 	  MoveTo (startX, startY);
2010 	  if (LINEdrawingCHAR(pbNewChars[startN])) {
2011 	    /******************************************************************
2012 	    * A line drawing character.  First erase the entire character
2013 	    * cell (including the leading line).
2014 	    ******************************************************************/
2015 	    Rect eraseRect;
2016 	    eraseRect.top = startY;
2017 	    eraseRect.bottom = startY + FONTfsiHEIGHT;
2018 	    eraseRect.left = startX;
2019 	    eraseRect.right = startX + FONTfsiWIDTH;
2020 	    EraseRect (&eraseRect);
2021 	    switch (pbNewChars[startN]) {
2022 	      case ACS_PLUS:
2023 	        Move (FONTfsiHALFwidth, 0);
2024 	        Line (0, FONTfsiHEIGHT-1);
2025 	        Move (-FONTfsiHALFwidth, -(FONTfsiHALFheight-1));
2026 	        Line (FONTfsiWIDTH-1, 0);
2027 	        break;
2028 	      case ACS_TTEE:
2029 	        Move (0, FONTfsiHALFheight);
2030 	        Line (FONTfsiWIDTH-1, 0);
2031 	        Move (-FONTfsiHALFwidth, 0);
2032 	        Line (0, FONTfsiHALFheight-1);
2033 	        break;
2034 	      case ACS_BTEE:
2035 		Move (0, FONTfsiHALFheight);
2036 		Line (FONTfsiWIDTH-1, 0);
2037 		Move (-FONTfsiHALFwidth, 0);
2038 		Line (0, -FONTfsiHALFheight);
2039 	        break;
2040 	      case ACS_LTEE:
2041 		Move (FONTfsiHALFwidth, 0);
2042 		Line (0, FONTfsiHEIGHT-1);
2043 		Move (0, -(FONTfsiHALFheight-1));
2044 		Line (FONTfsiHALFwidth, 0);
2045 	        break;
2046 	      case ACS_RTEE:
2047 		Move (FONTfsiHALFwidth, 0);
2048 		Line (0, FONTfsiHEIGHT-1);
2049 		Move (0, -(FONTfsiHALFheight-1));
2050 		Line (-FONTfsiHALFwidth, 0);
2051 	        break;
2052 	      case ACS_HLINE:
2053 		Move (0, FONTfsiHALFheight);
2054 		Line (FONTfsiWIDTH-1, 0);
2055 	        break;
2056 	      case ACS_VLINE:
2057 		Move (FONTfsiHALFwidth, 0);
2058 		Line (0, FONTfsiHEIGHT-1);
2059 	        break;
2060 	      case ACS_ULCORNER:
2061 		Move (FONTfsiHALFwidth, FONTfsiHEIGHT-1);
2062 		Line (0, -(FONTfsiHALFheight-1));
2063 		Line (FONTfsiHALFwidth, 0);
2064 	        break;
2065 	      case ACS_URCORNER:
2066 		Move (0, FONTfsiHALFheight);
2067 		Line (FONTfsiHALFwidth, 0);
2068 		Line (0, FONTfsiHALFheight-1);
2069 	        break;
2070 	      case ACS_LRCORNER:
2071 		Move (FONTfsiHALFwidth, 0);
2072 		Line (0, FONTfsiHALFheight);
2073 		Line (-FONTfsiHALFwidth, 0);
2074 	        break;
2075 	      case ACS_LLCORNER:
2076 		Move (FONTfsiHALFwidth, 0);
2077 		Line (0, FONTfsiHALFheight);
2078 		Line (FONTfsiHALFwidth, 0);
2079 	        break;
2080 	    }
2081 	  }
2082 	  else {
2083 	    /******************************************************************
2084 	    * Drawing text characters.  Since one or more line drawing
2085 	    * characters (or the cursor) may be written over, erase the
2086 	    * leading line first (which is used by the line drawing characters
2087 	    * but not the text characters).
2088 	    ******************************************************************/
2089 	    Rect eRect;
2090 	    short nChars = upToN - startN + 1;
2091 	    eRect.top = startY + FONTfsiHEIGHT - 1;
2092 	    eRect.bottom = startY + FONTfsiHEIGHT;
2093 	    eRect.left = startX;
2094 	    eRect.right = startX + (nChars * FONTfsiWIDTH);
2095 	    EraseRect (&eRect);
2096 	    Move (0, FONTfsiASCENT);
2097 	    DrawText (&pbNewChars[startN], 0, nChars);
2098 	  }
2099 	  if (upToN == endN) break;
2100 	  startN = upToN + 1;
2101        }
2102      }
2103   }
2104 #endif
2105   /****************************************************************************
2106   * Make the new characters/attributes the current characters/attributes.
2107   ****************************************************************************/
2108   savePtr = pbCurrentChars;
2109   pbCurrentChars = pbNewChars;
2110   pbNewChars = savePtr;
2111   savePtr = pbCurrentAttrs;
2112   pbCurrentAttrs = pbNewAttrs;
2113   pbNewAttrs = savePtr;
2114   /****************************************************************************
2115   * Redisplay cursor (if appropriate).
2116   ****************************************************************************/
2117   if (cursorOn && cursorWIND != NULL && cursorWIND->pasted &&
2118       !CharOccluded(cursorWIND,cursorRow,cursorCol)) {
2119 #if defined(mac)
2120     InvertCursor (cursorWIND, cursorRow, cursorCol);
2121 #endif
2122 #if defined(win32)
2123     SetCursorPosition (cursorWIND->id->atRowN + cursorRow,
2124 		       cursorWIND->id->atColN + cursorCol);
2125 #endif
2126   }
2127   return TRUE;
2128 }
2129 #endif
2130 
2131 /******************************************************************************
2132 * CharOccluded.
2133 ******************************************************************************/
2134 
2135 #if defined(COWui)
CharOccluded(wid,rowN,colN)2136 static Logical CharOccluded (wid, rowN, colN)
2137 WINDOWid wid;
2138 int rowN;
2139 int colN;
2140 {
2141   WINDOWid tW = wid->next;
2142   int pbRowN = wid->id->atRowN + rowN,
2143       pbColN = wid->id->atColN + colN;
2144   while (tW != NULL) {
2145     if (tW->pasted &&
2146 	tW->id->atRowN <= pbRowN &&
2147         pbRowN <= (tW->id->atRowN + tW->id->nRows - 1) &&
2148         tW->id->atColN <= pbColN &&
2149         pbColN <= (tW->id->atColN + tW->id->nCols - 1)) return TRUE;
2150     tW = tW->next;
2151   }
2152   return FALSE;
2153 }
2154 #endif
2155 
2156 /******************************************************************************
2157 * InvertCursor.
2158 * This is used to turn a cursor on or off.
2159 ******************************************************************************/
2160 
2161 #if defined(COWui)
2162 #if defined(mac)
InvertCursor(wid,rowN,colN)2163 static void InvertCursor (wid, rowN, colN)
2164 WINDOWid wid;
2165 int rowN;
2166 int colN;
2167 {
2168   Rect iRect;
2169   int startX = (FONTfsiWIDTH * (wid->id->atColN + colN)) + MARGINfsiSIZE,
2170       startY = (FONTfsiHEIGHT * (wid->id->atRowN + rowN)) + MARGINfsiSIZE;
2171   iRect.top = startY;
2172   iRect.bottom = startY + FONTfsiHEIGHT - 1;	/* -1 for leading line. */
2173   iRect.left = startX;
2174   iRect.right = startX + FONTfsiWIDTH;
2175   InvertRect (&iRect);
2176   cursorVisible = BOO(cursorVisible,FALSE,TRUE);
2177   return;
2178 }
2179 #endif
2180 #endif
2181 
2182 /******************************************************************************
2183 * WindowLocation.
2184 * Passes back row/column at which window is pasted.
2185 ******************************************************************************/
2186 
2187 #if defined(CURSESui)
WindowLocation(id,row,col)2188 static void WindowLocation (id, row, col)
2189 LocalId id;
2190 int *row;
2191 int *col;
2192 {
2193 #if defined(unix) || defined(posixSHELL)
2194 #if GETBEGavail
2195   getbegyx (id, *row, *col);			/* `getbegyx' is a macro. */
2196 #else
2197   *row = id->_begy;
2198   *col = id->_begx;
2199 #endif
2200 #endif
2201 #if defined(dos)
2202   *row = id->_begy;
2203   *col = id->_begx;
2204 #endif
2205   return;
2206 }
2207 #endif
2208 
2209 /******************************************************************************
2210 * WindowSize.
2211 * Passes back number of rows/columns in window.
2212 ******************************************************************************/
2213 
2214 #if defined(CURSESui) || defined(SMGui)
WindowSize(id,rows,cols)2215 static void WindowSize (id, rows, cols)
2216 LocalId id;
2217 int *rows;
2218 int *cols;
2219 {
2220 #if defined(SMGui)
2221   long height = -1, width = -1;
2222   smg$get_display_attr (&id, &height, &width, NULL, NULL, NULL, NULL);
2223   *rows = height;
2224   *cols = width;
2225 #endif
2226 #if defined(CURSESui)
2227 #if defined(unix) || defined(posixSHELL)
2228 #if GETMAXavail
2229   getmaxyx (id, *rows, *cols);			/* `getmaxyx' is a macro. */
2230 #else
2231   *rows = id->_maxy;
2232   *cols = id->_maxx;
2233 #endif
2234 #endif
2235 #if defined(dos)
2236   *rows = id->_maxy;
2237   *cols = id->_maxx;
2238 #endif
2239 #endif
2240   return;
2241 }
2242 #endif
2243 
2244 /******************************************************************************
2245 * RenditionMapping.
2246 * The BLACK rendition is ignored on non-IBM PC machines (it is the same as
2247 * NORMAL).  On IBM PCs it overrides all other renditions.
2248 ******************************************************************************/
2249 
RenditionMapping(rendition)2250 static int RenditionMapping (rendition)
2251 int rendition;
2252 {
2253   int mapped;
2254 #if defined(SMGui)
2255   mapped = 0;
2256   if ((rendition & BOLD) != 0) mapped = mapped | SMG$M_BOLD;
2257   if ((rendition & REVERSE) != 0 ||
2258       (rendition & REVERSE1) != 0 ||
2259       (rendition & REVERSE2) != 0) mapped = mapped | SMG$M_REVERSE;
2260   if ((rendition & BLINKING) != 0) mapped = mapped | SMG$M_BLINK;
2261 #endif
2262 #if defined(CURSESui)
2263 #if defined(unix) || defined(posixSHELL)
2264   mapped = A_NORMAL;
2265   if ((rendition & BOLD) != 0) mapped = mapped | A_BOLD;
2266   if ((rendition & REVERSE) != 0 ||
2267       (rendition & REVERSE1) != 0 ||
2268       (rendition & REVERSE2) != 0) mapped = mapped | A_REVERSE;
2269   if ((rendition & BLINKING) != 0) mapped = mapped | A_BLINK;
2270 #endif
2271 #if defined(dos)
2272   if ((rendition & BLACK) != 0)
2273     mapped = A_NORMAL | F_BLACK | B_BLACK;
2274   else {
2275     if ((rendition & REVERSE) != 0 ||
2276 	(rendition & REVERSE1) != 0 ||
2277 	(rendition & REVERSE2) != 0) {
2278       if ((rendition & REVERSE) != 0)
2279 	mapped = A_REVERSE | F_GRAY | B_BLUE;
2280       else
2281 	if ((rendition & REVERSE1) != 0)
2282 	  mapped = A_BOLD | F_GRAY | B_RED;
2283 	else /*REVERSE2*/
2284 	  mapped = A_BOLD | F_GRAY | B_CYAN;
2285     }
2286     else
2287       mapped = A_NORMAL | F_GRAY | B_BLUE;
2288     if ((rendition & BOLD) != 0) mapped = mapped | A_BOLD;
2289     if ((rendition & BLINKING) != 0) mapped = mapped | A_BLINK;
2290   }
2291 #endif
2292 #endif
2293 #if defined(COWui)
2294   mapped = 0;
2295   if ((rendition & BOLD) != 0) mapped = mapped | BOLD;
2296   if ((rendition & REVERSE) != 0 ||
2297       (rendition & REVERSE1) != 0 ||
2298       (rendition & REVERSE2) != 0) mapped = mapped | REVERSE;
2299   if ((rendition & BLINKING) != 0) mapped = mapped | BLINKING;
2300 #endif
2301   return mapped;
2302 }
2303 
2304 /******************************************************************************
2305 * EraseWindow.
2306 * On DECstations, DEC Alphas running OSF/1, and IBM RS6000s, `werase' doesn't
2307 * work - no idea why not.  Also, putting blanks to each position in the window
2308 * doesn't work either.  A non-blank character must first be put and then a
2309 * blank.  Again I'm baffled.  Anyway, this function is used in several places
2310 * to erase the contents of a window.
2311 ******************************************************************************/
2312 
2313 #if defined(CURSESui)
EraseWindow(id)2314 static int EraseWindow (id)
2315 LocalId id;
2316 {
2317 #if WERASEworks
2318   werase (id);
2319 #else
2320   int nRows, nCols, rowN, colN;
2321   WindowSize (id, &nRows, &nCols);
2322   for (rowN = 0; rowN < nRows; rowN++) {
2323      for (colN = 0; colN < nCols; colN++) {
2324 	mvwaddch (id, rowN, colN, '*');
2325 	mvwaddch (id, rowN, colN, ' ');
2326      }
2327   }
2328 #endif
2329   return TRUE;
2330 }
2331 #endif
2332 
2333 /******************************************************************************
2334 * MacExecuteFSI.
2335 ******************************************************************************/
2336 
2337 #if defined(mac)
2338 void MacExecuteFSI (exeFnc, qopFnc)
2339 Logical (*exeFnc) PROTOARGs((int argC, char *argV[]));
2340 Logical (*qopFnc) PROTOARGs((int *argC, char **argV[]));
2341 {
2342   int argC;
2343   char **argV;
2344   InitMacUI ();
2345   InitMacMenusFSI ();
2346   InitMacFSI ();
2347   for (;;) {
2348      if ((*qopFnc)(&argC,&argV)) {
2349        (*exeFnc) (argC, argV);
2350        FreeMacQOPs (argC, argV);
2351      }
2352      else
2353        return;
2354   }
2355 }
2356 #endif
2357 
2358 /******************************************************************************
2359 * InitMacMenusFSI.
2360 * Initialize the Macintosh menus for the full screen interface window.
2361 ******************************************************************************/
2362 
2363 #if defined(mac)
InitMacMenusFSI()2364 void InitMacMenusFSI () {
2365   appleMenuHfsi = GetMenu (APPLEri);
2366   AddResMenu (appleMenuHfsi, *((long *) "DRVR"));
2367   InsertMenu (appleMenuHfsi, 0);
2368   DrawMenuBar ();
2369   return;
2370 }
2371 #endif
2372 
2373 /******************************************************************************
2374 * InitMacFSI.
2375 * Initialize the Macintosh full screen interface window (pasteboard).
2376 ******************************************************************************/
2377 
2378 #if defined(mac)
InitMacFSI()2379 void InitMacFSI () {
2380   static WindowRecord wRecord;
2381   WindowPtr behindWindow = (WindowPtr) -1;
2382   fsiWindowP = GetNewWindow (FSIri, &wRecord, behindWindow);
2383   SetPort (fsiWindowP);
2384   TextFont (monaco);
2385   return;
2386 }
2387 #endif
2388 
2389 /******************************************************************************
2390 * EncodeKeyDefinitions.
2391 ******************************************************************************/
2392 
2393 #if defined(STDARG)
EncodeKeyDefinitions(int nLines,char ** lineS,...)2394 void EncodeKeyDefinitions (int nLines, char **lineS, ...)
2395 #else
2396 void EncodeKeyDefinitions (va_alist)
2397 va_dcl
2398 #endif
2399 {
2400 #if !defined(STDARG)
2401   int nLines;
2402   char **lineS;		/* Capital `S' because of the IBM RS6000. */
2403 #endif
2404   int lineN;		/* Line number. */
2405   va_list ap;
2406   /****************************************************************************
2407   * Start variable-length argument list scanning.
2408   ****************************************************************************/
2409 #if defined(STDARG)
2410   va_start (ap, lineS);
2411 #else
2412   VA_START (ap);
2413   nLines = va_arg (ap, int);
2414   lineS = va_arg (ap, char **);
2415 #endif
2416   /****************************************************************************
2417   * Scan lines replacing ______'s with corresponding key tokens.
2418   ****************************************************************************/
2419   for (lineN = 0; lineN < nLines; lineN++) {
2420      char *ptr1 = strchr(lineS[lineN],'_');
2421      while (ptr1 != NULL) {
2422        char *ptr2 = ptr1, *ptr = ptr1, token[MAX_KEY_TOKEN_LEN+1];
2423        int i, lenT, lenL, count, pad, key = va_arg(ap,int);
2424        while (*(ptr2+1) == '_') ptr2++;
2425        lenL = (int) (ptr2 - ptr1 + 1);
2426        strcpyX (token, KeyToken(key,lenL), MAX_KEY_TOKEN_LEN);
2427        lenT = (int) strlen (token);
2428        count = MINIMUM(lenT,lenL);
2429        pad = (lenT < lenL ? lenL - lenT : 0);
2430        for (i = 0; i < count; i++) *ptr++ = token[i];
2431        for (i = 0; i < pad; i++) *ptr++ = ' ';
2432        ptr1 = strchr (ptr2 + 1, '_');
2433      }
2434   }
2435   va_end (ap);
2436   return;
2437 }
2438 
2439 /******************************************************************************
2440 * KeyToken.
2441 * Return address of character string for key.
2442 ******************************************************************************/
2443 
KeyToken(key,maxL)2444 static char *KeyToken(key,maxL)
2445 int key;
2446 int maxL;
2447 {
2448   switch (key) {
2449     case KB_a: return AlphaKey('a',maxL);
2450     case KB_b: return AlphaKey('b',maxL);
2451     case KB_c: return AlphaKey('c',maxL);
2452     case KB_d: return AlphaKey('d',maxL);
2453     case KB_e: return AlphaKey('e',maxL);
2454     case KB_f: return AlphaKey('f',maxL);
2455     case KB_g: return AlphaKey('g',maxL);
2456     case KB_h: return AlphaKey('h',maxL);
2457     case KB_i: return AlphaKey('i',maxL);
2458     case KB_j: return AlphaKey('j',maxL);
2459     case KB_k: return AlphaKey('k',maxL);
2460     case KB_l: return AlphaKey('l',maxL);
2461     case KB_m: return AlphaKey('m',maxL);
2462     case KB_n: return AlphaKey('n',maxL);
2463     case KB_o: return AlphaKey('o',maxL);
2464     case KB_p: return AlphaKey('p',maxL);
2465     case KB_q: return AlphaKey('q',maxL);
2466     case KB_r: return AlphaKey('r',maxL);
2467     case KB_s: return AlphaKey('s',maxL);
2468     case KB_t: return AlphaKey('t',maxL);
2469     case KB_u: return AlphaKey('u',maxL);
2470     case KB_v: return AlphaKey('v',maxL);
2471     case KB_w: return AlphaKey('w',maxL);
2472     case KB_x: return AlphaKey('x',maxL);
2473     case KB_y: return AlphaKey('y',maxL);
2474     case KB_z: return AlphaKey('z',maxL);
2475     case KB_A: return AlphaKey('A',maxL);
2476     case KB_B: return AlphaKey('B',maxL);
2477     case KB_C: return AlphaKey('C',maxL);
2478     case KB_D: return AlphaKey('D',maxL);
2479     case KB_E: return AlphaKey('E',maxL);
2480     case KB_F: return AlphaKey('F',maxL);
2481     case KB_G: return AlphaKey('G',maxL);
2482     case KB_H: return AlphaKey('H',maxL);
2483     case KB_I: return AlphaKey('I',maxL);
2484     case KB_J: return AlphaKey('J',maxL);
2485     case KB_K: return AlphaKey('K',maxL);
2486     case KB_L: return AlphaKey('L',maxL);
2487     case KB_M: return AlphaKey('M',maxL);
2488     case KB_N: return AlphaKey('N',maxL);
2489     case KB_O: return AlphaKey('O',maxL);
2490     case KB_P: return AlphaKey('P',maxL);
2491     case KB_Q: return AlphaKey('Q',maxL);
2492     case KB_R: return AlphaKey('R',maxL);
2493     case KB_S: return AlphaKey('S',maxL);
2494     case KB_T: return AlphaKey('T',maxL);
2495     case KB_U: return AlphaKey('U',maxL);
2496     case KB_V: return AlphaKey('V',maxL);
2497     case KB_W: return AlphaKey('W',maxL);
2498     case KB_X: return AlphaKey('X',maxL);
2499     case KB_Y: return AlphaKey('Y',maxL);
2500     case KB_Z: return AlphaKey('Z',maxL);
2501     case KB_PLUS: return AlphaKey('+',maxL);
2502     case KB_MINUS: return AlphaKey('-',maxL);
2503     case KB_CTRL_at: return ControlKey('@',maxL);
2504     case KB_CTRL_A: return ControlKey('A',maxL);
2505     case KB_CTRL_B: return ControlKey('B',maxL);
2506     case KB_CTRL_C: return ControlKey('C',maxL);
2507     case KB_CTRL_D: return ControlKey('D',maxL);
2508     case KB_CTRL_E: return ControlKey('E',maxL);
2509     case KB_CTRL_F: return ControlKey('F',maxL);
2510     case KB_CTRL_G: return ControlKey('G',maxL);
2511 #if !defined(dos) && !defined(mac) && !defined(win32)
2512     /**************************************************************************
2513     * Same as DELETE on IBM PC and Macintosh.
2514     **************************************************************************/
2515     case KB_CTRL_H: return ControlKey('H',maxL);
2516 #endif
2517     case KB_TAB:
2518       switch (maxL) {
2519 	case 3: case 4:
2520 	  return "TAB";
2521 	default:
2522 	  return "<Tab>";
2523       }
2524     case KB_CTRL_J: return ControlKey('J',maxL);
2525     case KB_CTRL_K: return ControlKey('K',maxL);
2526     case KB_CTRL_L: return ControlKey('L',maxL);
2527     case KB_RETURN:
2528       switch (maxL) {
2529 	case 3: case 4:
2530 	  return "RET";
2531 	case 5: case 6: case 7:
2532 	  return "<RET>";
2533 	default:
2534 	  return "<Return>";
2535       }
2536     case KB_CTRL_N: return ControlKey('N',maxL);
2537     case KB_CTRL_O: return ControlKey('O',maxL);
2538     case KB_CTRL_P: return ControlKey('P',maxL);
2539     case KB_CTRL_Q: return ControlKey('Q',maxL);
2540     case KB_CTRL_R: return ControlKey('R',maxL);
2541     case KB_CTRL_S: return ControlKey('S',maxL);
2542     case KB_CTRL_T: return ControlKey('T',maxL);
2543     case KB_CTRL_U: return ControlKey('U',maxL);
2544     case KB_CTRL_V: return ControlKey('V',maxL);
2545     case KB_CTRL_W: return ControlKey('W',maxL);
2546     case KB_CTRL_X: return ControlKey('X',maxL);
2547     case KB_CTRL_Y: return ControlKey('Y',maxL);
2548     case KB_CTRL_Z: return ControlKey('Z',maxL);
2549     case KB_ESCAPE:
2550       switch (maxL) {
2551 	case 3: case 4:
2552 	  return "ESC";
2553 	default:
2554 	  return "<Esc>";
2555       }
2556     case KB_DELETE:
2557       switch (maxL) {
2558 	case 3: case 4:
2559 	  return "DEL";
2560 	case 5: case 6: case 7:
2561 	  return "<DEL>";
2562 	default:
2563 	  return "<Delete>";
2564       }
2565     case KB_UPARROW:
2566       switch (maxL) {
2567 	case 2: case 3:
2568 	  return "UP";
2569 	case 4: case 5: case 6:
2570 	  return "<UP>";
2571 	case 7: case 8:
2572 	  return "UpArrow";
2573 	default:
2574 	  return "<UpArrow>";
2575       }
2576     case KB_DOWNARROW:
2577       switch (maxL) {
2578 	case 3:
2579 	  return "DWN";
2580 	case 4: case 5:
2581 	  return "DOWN";
2582 	case 6: case 7: case 8:
2583 	  return "<DOWN>";
2584 	case 9: case 10:
2585 	  return "DownArrow";
2586 	default:
2587 	  return "<DownArrow>";
2588       }
2589     case KB_LEFTARROW:
2590       switch (maxL) {
2591 	case 3:
2592 	  return "LFT";
2593 	case 4: case 5:
2594 	  return "LEFT";
2595 	case 6: case 7: case 8:
2596 	  return "<LEFT>";
2597 	case 9: case 10:
2598 	  return "LeftArrow";
2599 	default:
2600 	  return "<LeftArrow>";
2601       }
2602     case KB_RIGHTARROW:
2603       switch (maxL) {
2604 	case 3:
2605 	  return "RHT";
2606 	case 5: case 6:
2607 	  return "RIGHT";
2608 	case 7: case 8: case 9:
2609 	  return "<RIGHT>";
2610 	case 10: case 11:
2611 	  return "RightArrow";
2612 	default:
2613 	  return "<RightArrow>";
2614       }
2615   }
2616   return "?";
2617 }
2618 
2619 /******************************************************************************
2620 * AlphaKey.
2621 ******************************************************************************/
2622 
AlphaKey(key,maxL)2623 static char *AlphaKey (key, maxL)
2624 int key;
2625 int maxL;
2626 {
2627   static char token[MAX_KEY_TOKEN_LEN+1];
2628   switch (maxL) {
2629     case 1: case 2:
2630       sprintf (token, "%c", key);
2631       break;
2632     default:
2633       sprintf (token, "<%c>", key);
2634       break;
2635   }
2636   return token;
2637 }
2638 
2639 /******************************************************************************
2640 * ControlKey.
2641 ******************************************************************************/
2642 
ControlKey(key,maxL)2643 static char *ControlKey (key, maxL)
2644 int key;
2645 int maxL;
2646 {
2647   static char token[MAX_KEY_TOKEN_LEN+1];
2648   switch (maxL) {
2649     case 3: case 4:
2650       sprintf (token, "C-%c", key);
2651       break;
2652     case 5:
2653       sprintf (token, "CTL-%c", key);
2654       break;
2655     case 6: case 7:
2656       sprintf (token, "Ctrl-%c", key);
2657       break;
2658     default:
2659       sprintf (token, "<Ctrl-%c>", key);
2660       break;
2661   }
2662   return token;
2663 }
2664 
2665 /******************************************************************************
2666 * KeyWaitingAST.
2667 ******************************************************************************/
2668 
2669 #if defined(SMGui)
KeyWaitingAST()2670 void KeyWaitingAST () {
2671   keyWaiting++;
2672   return;
2673 }
2674 #endif
2675