1 /* term_curses.c - Terminal screen update code; based on term_x11.c
2
3 Copyright (c) 1997-2003, Sidik Isani (xhomer@isani.org)
4
5 This file is part of Xhomer.
6
7 Xhomer is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 Xhomer is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Xhomer; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 *
21 * TODO:
22 * - Simh terminal settings are still trapping ^E.
23 * - Suspend curses control if at the simh> prompt (see man
24 * page for an example of how to do this.)
25 * - Check all keyboard mappings.
26 * - Assign alternate to CONTROL-F1 since not all text
27 * terminals may have such a key combination (linux console is
28 * one, for example, which cannot distinguish control-f1 and f1.)
29 * - Suppress error messages from xhomer itself which
30 * can corrupt the curses window.
31 * - Implement Control-L to force a refresh in case screen
32 * gets messed up anyway.
33 * - Warn if terminal window is smaller than 80x24.
34 * - Implement overlay so that underlying characters show even
35 * if the menu is up (right now, entire screen is replaced.)
36 * - Colors?
37 * - Search up/down by scanlines so that Synergy works.
38 * - ifdef-out some of the special KEY_ definitions which might
39 * be ncurses-specific (i.e., use them only if defined, otherwise
40 * this may fail to compile with older curses libraries.)
41 */
42
43 #ifdef PRO
44
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48
49 #include <curses.h>
50
51 #include "pro_defs.h"
52 #include "pro_lk201.h"
53
54 #define PRO_KEYBOARD_FIFO_DEPTH 1024
55
56 #define PRO_FONT_SCANLINES 10
57
58 /*
59 * Special key codes not defined by curses.
60 */
61 #define ESCAPE (27)
62 #define CNTR(c) (1-'A'+c)
63 #define CNTR_F1 03776 /* Any unused keycode will do. */
64
65
66 /* Dummy values copied from term_x11.c - required so xhomer can compile. */
67 int pro_nine_workaround = 0; /* workaround for #9 Xserver bugs */
68 int pro_libc_workaround = 0; /* workaround for pre-glibc-2.0 bug */
69 int pro_window_x = 0; /* window x position */
70 int pro_window_y = 0; /* window y position */
71 int pro_screen_full = 0; /* 0 = window, 1 = full-screen */
72 int pro_screen_window_scale = 2; /* vertical window scale factor */
73 int pro_screen_full_scale = 2; /* vertical DGA scale factor */
74 int pro_screen_gamma = 10; /* 10x gamma correction factor */
75 int pro_screen_pcm = 1; /* 0 = don't use PCM, 1 = use PCM (private color map) */
76 int pro_screen_framebuffers = 1; /* number of DGA framebuffers (1..3)
77 */
78
79 int pro_mouse_x = 0; /* mouse x */
80 int pro_mouse_y = 0; /* mouse y */
81 int pro_mouse_l = 0; /* left mouse button */
82 int pro_mouse_m = 0; /* middle mouse button */
83 int pro_mouse_r = 0; /* right mouse button */
84 int pro_mouse_in = 0; /* mouse in window */
85
86 LOCAL int pro_screen_blank = 0; /* indicates whether screen is blanked */
87
88 LOCAL WINDOW* main_window = 0;
89 LOCAL WINDOW* overlay_window = 0;
90
91 LOCAL int titlebar_ok = 0;
92
93 /* Temporary hack for terminal types which have no "control-F1" (linux) */
94
95 LOCAL int f1_equals_control_f1 = 0;
96
97 /* Put a title on the display window */
98
pro_screen_title(char * title)99 void pro_screen_title (char *title)
100 {
101 if (titlebar_ok)
102 fprintf(stderr, "\033]2;%s\a", title);
103 }
104
update()105 LOCAL void update ()
106 {
107 wnoutrefresh(main_window);
108 if (overlay_window)
109 {
110 touchwin(overlay_window);
111 wnoutrefresh(overlay_window);
112 }
113 doupdate();
114 }
115
pro_screen_clear()116 void pro_screen_clear ()
117 {
118 wclear(main_window);
119 update();
120 }
121
122 /* External keyboard polling routine */
123
keyboard_get()124 LOCAL int keyboard_get ()
125 {
126 static int shift = 0;
127 static int ctrl = 0;
128 static int ch = ERR;
129 int shift_wanted;
130 int ctrl_wanted;
131 int c;
132
133 while (ch==ERR)
134 {
135 static int escape = 0; /* >0 if reading an escape sequence */
136 static char escape_seq[1024];
137
138 wnoutrefresh(main_window);
139 ch = wgetch(main_window);
140 if (f1_equals_control_f1 && ch == KEY_F(1))
141 ch = CNTR_F1;
142 if (escape)
143 {
144 escape_seq[escape-1] = ch;
145 if (!(('0'<=ch && ch<=';') ||
146 ch=='(' || ch=='[' || ch=='O' || ch==ESCAPE))
147 /* filter out escape sequences not handled by curses */
148 {
149 if (ch == ERR) escape--;
150 escape_seq[escape]='\0';
151 escape=0;
152 if (!strcmp(escape_seq, ""))
153 ch = ESCAPE;
154 else if (!strcmp(escape_seq, "[11^")) /* rxvt */
155 ch = CNTR_F1;
156 else if (!strcmp(escape_seq, "O5P")) /* xterm */
157 ch = CNTR_F1;
158 else if (!strcmp(escape_seq, "[[A")) /* linux, F1 */
159 ch = CNTR_F1;
160 else if (!strcmp(escape_seq, "[5~"))
161 ch = KEY_PPAGE;
162 else if (!strcmp(escape_seq, "[6~"))
163 ch = KEY_NPAGE;
164 else if (!strcmp(escape_seq, "[3~"))
165 ch = KEY_DC;
166 else if (!strcmp(escape_seq, "Ot"))
167 ch = KEY_LEFT;
168 else if (!strcmp(escape_seq, "Ov"))
169 ch = KEY_RIGHT;
170 else if (!strcmp(escape_seq, "Ox"))
171 ch = KEY_UP;
172 else if (!strcmp(escape_seq, "Or"))
173 ch = KEY_DOWN;
174 else
175 {
176 beep();
177 /* DEBUG:
178 fprintf(stderr, "Unrecognized escape sequence: `%.900s'", escape_seq);
179 */
180 ch = ERR;
181 }
182 }
183 else
184 {
185 if (escape<1022) escape++;
186 }
187 }
188 else if (ch == ESCAPE) escape = 1;
189
190 if (ch == ERR) return PRO_NOCHAR;
191 if (escape) { ch = ERR; continue; }
192 }
193
194 /*
195 * Check proper state of the control key
196 */
197 if (ch < ' ' || ch == CNTR_F1)
198 ctrl_wanted = 1; else ctrl_wanted = 0;
199
200 if (ctrl_wanted && !ctrl)
201 {
202 ctrl = 1;
203 return PRO_LK201_CTRL;
204 }
205
206 /*
207 * Check proper state of the shift key
208 */
209 if (strchr("~!@#$%^&*()_+ABCDEFGHIJKLMNOPQRSTUVWXYZ{}|:\"<>?", ch))
210 shift_wanted = 1; else shift_wanted = 0;
211
212 if (shift_wanted && !shift)
213 {
214 shift = 1;
215 return PRO_LK201_SHIFT;
216 }
217
218 if (shift != shift_wanted || ctrl != ctrl_wanted)
219 {
220 ctrl = 0; shift = 0;
221 return PRO_LK201_ALLUPS;
222 }
223
224 c = ch;
225 ch = ERR;
226
227 /* DEBUG:
228 fprintf(stderr, "\r\nctrl=%d shift=%d key=%d\r\n", ctrl, shift, c);
229 */
230
231 switch (c)
232 {
233 case CNTR('I'): case KEY_BTAB: return PRO_LK201_TAB;
234 case CNTR('M'): return PRO_LK201_RETURN;
235 case ' ': return PRO_LK201_SPACE;
236 case 'a': case 'A': case CNTR('A'): return PRO_LK201_A;
237 case 'b': case 'B': case CNTR('B'): return PRO_LK201_B;
238 case 'c': case 'C': case CNTR('C'): return PRO_LK201_C;
239 case 'd': case 'D': case CNTR('D'): return PRO_LK201_D;
240 case 'e': case 'E': case CNTR('E'): return PRO_LK201_E;
241 case 'f': case 'F': case CNTR('F'): return PRO_LK201_F;
242 case 'g': case 'G': case CNTR('G'): return PRO_LK201_G;
243 case 'h': case 'H': case CNTR('H'): return PRO_LK201_H;
244 case 'i': case 'I': /* CNTR('I') */ return PRO_LK201_I;
245 case 'j': case 'J': case CNTR('J'): return PRO_LK201_J;
246 case 'k': case 'K': case CNTR('K'): return PRO_LK201_K;
247 case 'l': case 'L': case CNTR('L'): return PRO_LK201_L;
248 case 'm': case 'M': /* CNTR('M') */ return PRO_LK201_M;
249 case 'n': case 'N': case CNTR('N'): return PRO_LK201_N;
250 case 'o': case 'O': case CNTR('O'): return PRO_LK201_O;
251 case 'p': case 'P': case CNTR('P'): return PRO_LK201_P;
252 case 'q': case 'Q': case CNTR('Q'): return PRO_LK201_Q;
253 case 'r': case 'R': case CNTR('R'): return PRO_LK201_R;
254 case 's': case 'S': case CNTR('S'): return PRO_LK201_S;
255 case 't': case 'T': case CNTR('T'): return PRO_LK201_T;
256 case 'u': case 'U': case CNTR('U'): return PRO_LK201_U;
257 case 'v': case 'V': case CNTR('V'): return PRO_LK201_V;
258 case 'w': case 'W': case CNTR('W'): return PRO_LK201_W;
259 case 'x': case 'X': case CNTR('X'): return PRO_LK201_X;
260 case 'y': case 'Y': case CNTR('Y'): return PRO_LK201_Y;
261 case 'z': case 'Z': case CNTR('Z'): return PRO_LK201_Z;
262 case '`': case '~': return PRO_LK201_TICK;
263 case '1': case '!': return PRO_LK201_1;
264 case '2': case '@': return PRO_LK201_2;
265 case '3': case '#': return PRO_LK201_3;
266 case '4': case '$': return PRO_LK201_4;
267 case '5': case '%': return PRO_LK201_5;
268 case '6': case '^': case CNTR('^'): return PRO_LK201_6;
269 case '7': case '&': return PRO_LK201_7;
270 case '8': case '*': return PRO_LK201_8;
271 case '9': case '(': return PRO_LK201_9;
272 case '0': case ')': return PRO_LK201_0;
273 case '-': case '_': case CNTR('_'): return PRO_LK201_MINUS;
274 case '=': case '+': return PRO_LK201_EQUAL;
275 case '[': case '{': /* CNTR('[') */ return PRO_LK201_LEFTB;
276 case ']': case '}': case CNTR(']'): return PRO_LK201_RIGHTB;
277 case '\\':case '|': case CNTR('\\'):return PRO_LK201_BACKSL;
278 case ';': case ':': return PRO_LK201_SEMI;
279 case '\'':case '"': return PRO_LK201_QUOTE;
280 case ',': case '<': return PRO_LK201_COMMA;
281 case '.': case '>': return PRO_LK201_PERIOD;
282 case '/': case '?': return PRO_LK201_SLASH;
283 case KEY_BREAK: return PRO_LK201_DO; /* %%% */
284 case KEY_DOWN: return PRO_LK201_DOWN;
285 case KEY_UP: return PRO_LK201_UP;
286 case KEY_LEFT: case KEY_SLEFT: return PRO_LK201_LEFT;
287 case KEY_RIGHT: case KEY_SRIGHT: return PRO_LK201_RIGHT;
288 case KEY_HOME: case KEY_SHOME: return PRO_LK201_SELECT; /* %%% */
289 case KEY_BACKSPACE: return PRO_LK201_DEL;
290 case ESCAPE: return PRO_LK201_HOLD;
291 case CNTR_F1:
292 case KEY_F(1): return PRO_LK201_PRINT;
293 case KEY_F(2): return PRO_LK201_SETUP;
294 case KEY_F(3): return PRO_LK201_FFOUR;
295 case KEY_F(4): return PRO_LK201_BREAK;
296 case KEY_F(5): return PRO_LK201_INT;
297 case KEY_F(6): return PRO_LK201_RESUME;
298 case KEY_F(7): return PRO_LK201_CANCEL;
299 case KEY_F(8): return PRO_LK201_MAIN;
300 case KEY_F(9): return PRO_LK201_EXIT;
301 case KEY_F(10): return PRO_LK201_ESC;
302 case KEY_F(11): return PRO_LK201_BS;
303 case KEY_F(12): return PRO_LK201_LF;
304 /* %%% ADDOP, HELP, and DO! */
305 case KEY_DL: case KEY_SDL:
306 case KEY_IL:
307 case KEY_DC: case KEY_SDC:
308 case KEY_IC: case KEY_SIC:
309 case KEY_EIC:
310 case KEY_CLEAR:
311 case KEY_EOS:
312 case KEY_EOL: case KEY_SEOL:
313 case KEY_SF:
314 case KEY_SR:
315 case KEY_NPAGE: return PRO_LK201_NEXT;
316 case KEY_PPAGE: return PRO_LK201_PREV;
317 case KEY_STAB:
318 case KEY_CTAB:
319 case KEY_CATAB:
320 case KEY_ENTER:
321 case KEY_SRESET:
322 case KEY_RESET:
323 case KEY_PRINT:
324 case KEY_LL:
325 case KEY_A1:
326 case KEY_A3:
327 case KEY_B2:
328 case KEY_C1:
329 case KEY_C3:
330 case KEY_BEG: case KEY_SBEG:
331 case KEY_CANCEL: case KEY_SCANCEL:
332 case KEY_CLOSE:
333 case KEY_COMMAND: case KEY_SCOMMAND:
334 case KEY_COPY: case KEY_SCOPY:
335 case KEY_CREATE: case KEY_SCREATE:
336 case KEY_END:
337 case KEY_EXIT: case KEY_SEXIT:
338 case KEY_FIND: case KEY_SFIND:
339 case KEY_HELP: case KEY_SHELP:
340 case KEY_MARK:
341 case KEY_MESSAGE: case KEY_SMESSAGE:
342 case KEY_MOVE: case KEY_SMOVE:
343 case KEY_NEXT: case KEY_SNEXT:
344 case KEY_OPEN:
345 case KEY_OPTIONS: case KEY_SOPTIONS:
346 case KEY_PREVIOUS: case KEY_SPREVIOUS:
347 case KEY_REDO: case KEY_SREDO:
348 case KEY_REFERENCE:
349 case KEY_REFRESH:
350 case KEY_REPLACE: case KEY_SREPLACE:
351 case KEY_RESTART:
352 case KEY_RESUME: case KEY_SRSUME:
353 case KEY_SAVE: case KEY_SSAVE:
354 case KEY_SELECT:
355 case KEY_SEND:
356 case KEY_SUSPEND: case KEY_SSUSPEND:
357 case KEY_UNDO: case KEY_SUNDO:
358 default:
359 return PRO_NOCHAR;
360 }
361 }
362
pro_keyboard_get()363 int pro_keyboard_get ()
364 {
365 return pro_menu(keyboard_get());
366 }
367
368 /* Initialize the display */
369
pro_screen_init_curses()370 LOCAL int pro_screen_init_curses ()
371 {
372 static int initialized = 0;
373
374 if (!initialized)
375 {
376 initialized = 1;
377
378 initscr(); cbreak(); noecho(); nonl(); start_color();
379 if ((main_window = newwin(0, 0, 0, 0))==0)
380 return PRO_FAIL;
381 }
382 else
383 {
384 /* === TODO: Window resize stuff goes here? */
385 /* Window resize really shouldn't be allowed (texthomer requires
386 * 80x24 to work properly.)
387 */
388 }
389 leaveok(main_window, TRUE); /* Ok to leave cursor when redrawing screen */
390 nodelay(main_window, TRUE); /* wgetch() returns ERR if no chars */
391 intrflush(main_window, TRUE); /* flush input if ^C is hit */
392 keypad(main_window, TRUE); /* enable numeric keypad codes */
393 curs_set(1); /* Select small cursor */
394 curs_set(0); /* Or better still, no cursor */
395 return PRO_SUCCESS;
396 }
397
pro_screen_init()398 int pro_screen_init ()
399 {
400 const char* term;
401 static char termvar[256];
402
403 if (!(term=getenv("COLORTERM")) || !*term)
404 if (!(term=getenv("TERM")) || !*term)
405 term = "vt100";
406
407 sprintf(termvar, "TERM=%.240s", term);
408 putenv(termvar);
409
410 if (!strncmp(term, "xterm", 5) ||
411 !strncmp(term, "rxvt", 4))
412 titlebar_ok = 1;
413 else
414 titlebar_ok = 0;
415
416 if (getenv("TERM") && !strncmp(getenv("TERM"), "linux", 5))
417 f1_equals_control_f1 = 1;
418
419 if (pro_screen_init_curses()==PRO_FAIL)
420 {
421 fprintf(stderr, "pro_curses: trouble initializing ncurses.\n");
422 return PRO_FAIL;
423 }
424
425 /* Clear image buffer */
426
427 pro_screen_clear();
428
429 /* Invalidate display cache */
430
431 pro_clear_mvalid();
432
433 return PRO_SUCCESS;
434 }
435
436
pro_screen_close()437 void pro_screen_close ()
438 {
439 endwin();
440 }
441
442 /* Reset routine (called only once) */
443
pro_screen_reset()444 void pro_screen_reset ()
445 {
446 /* %%% */
447 }
448
449
450 /* This function is called whenever the colormap mode changes.
451 A new X11 colormap is loaded for private colormap modes,
452 mvalid is cleared otherwise */
453
pro_mapchange()454 void pro_mapchange ()
455 {
456 /* === TODO: Support colors with ncurses? */
457 }
458
pro_colormap_write(int index,int rgb)459 void pro_colormap_write (int index, int rgb)
460 {
461 /* === TODO: Support colors with ncurses? */
462 }
463
464
465 /* This is called whenever the scroll register changes */
466
pro_scroll()467 void pro_scroll ()
468 {
469 /* Clear entire display cache for now %%% */
470 pro_clear_mvalid();
471 }
472
473
474 /* This called every emulated vertical retrace */
475
476 #include "term_fonthash_curses.c"
477
pro_screen_update()478 void pro_screen_update ()
479 {
480 int x, y, i;
481 int vindex = vmem(0);
482 int need_update = 0;
483
484 /* Check whether screen has been blanked */
485
486 if ((pro_vid_p1c & PRO_VID_P1_HRS) == PRO_VID_P1_OFF)
487 {
488 if (pro_screen_blank == 0)
489 {
490 /* Blank the screen */
491 /* %%% */
492 pro_screen_clear();
493 pro_screen_blank = 1;
494 }
495 }
496 else
497 {
498 if (pro_screen_blank == 1)
499 {
500 /* Unblank the screen */
501
502 pro_clear_mvalid();
503 pro_screen_blank = 0;
504 }
505 }
506
507 /* Redraw portions of screen that have changed */
508 #ifdef TEXT_PIXEL_ZOOM
509 /* Experimental mode with 1-character per pixel */
510 for (y=0; y<PRO_VID_SCRHEIGHT; y++)
511 {
512 int invalid = 0;
513
514 if (pro_vid_mvalid[cmem(vindex)] == 0)
515 {
516 pro_vid_mvalid[cmem(vindex)] = 1;
517 invalid = 1; /* If any row has a change, redo this line of text */
518 }
519 if (invalid)
520 {
521 need_update = 1;
522 for(i=0; i<(PRO_VID_SCRWIDTH/16); i++)
523 {
524 int vpix;
525 int vpixs = i * 16;
526 int vpixe = vpixs + 16;
527
528 int vdata0 = PRO_VRAM[0][vindex+i];
529 int vdata1 = PRO_VRAM[1][vindex+i] << 1;
530 int vdata2 = PRO_VRAM[2][vindex+i] << 2;
531
532 for(vpix=vpixs; vpix<vpixe; vpix++)
533 {
534 int cindex = (vdata2 & 04) | (vdata1 & 02) | (vdata0 & 01);
535 int color = cindex; /* pro_lut[cindex]; === */
536
537 mvwaddch(main_window, y, vpix-8-2*12, color>0?'*':' ');
538
539 vdata0 = vdata0 >> 1;
540 vdata1 = vdata1 >> 1;
541 vdata2 = vdata2 >> 1;
542 }
543 }
544 }
545 vindex = (vindex + (PRO_VID_SCRWIDTH/16)) & PRO_VID_VADDR_MASK;
546 }
547 #else
548 for (y=0; y<PRO_VID_SCRHEIGHT/PRO_FONT_SCANLINES; y++)
549 {
550 int vlist[PRO_FONT_SCANLINES];
551 int invalid = 0;
552
553 for (i=0; i<10; i++) /* 10 pixel rows in each font cell */
554 {
555 vlist[i] = vindex;
556 if (!pro_vid_mvalid[cmem(vindex)])
557 {
558 pro_vid_mvalid[cmem(vindex)] = 1;
559 invalid = 1; /* If any row has a change, redo this line of text */
560 }
561 vindex = (vindex + (PRO_VID_SCRWIDTH/16)) & PRO_VID_VADDR_MASK;
562 }
563
564 /* Update screen segment only if display cache is invalid */
565 /* %%% Check that PRO_VID_SCRWIDTH == PRO_VID_CLS_PIX */
566
567 if (invalid) for (x=0; x<80; x++)
568 {
569 char fontcell[PRO_FONT_SCANLINES*2 + 1];
570 register unsigned short tmp;
571 int ofs;
572
573 need_update = 1;
574
575 /* [00000000 00001111] [11111111 22222222] [22223333 33333333] */
576 /* [11110000 00000000] [22222222 11111111] [33333333 33332222] */
577 #define OFS 2
578 fontcell[PRO_FONT_SCANLINES*2] = '\0';
579 switch (x % 4)
580 {
581 case 0:
582 {
583 for (i=0; i<PRO_FONT_SCANLINES; i++)
584 {
585 ofs = vlist[i] + OFS + (x/4)*3;
586 tmp = PRO_VRAM[0][ofs];
587 fontcell[i*2] = '0' + ((tmp) & 0x3F);
588 fontcell[i*2+1] = '0' + ((tmp >> 6) & 0x3F);
589 }
590 break;
591 }
592 case 1:
593 {
594 for (i=0; i<PRO_FONT_SCANLINES; i++)
595 {
596 ofs = vlist[i] + OFS + (x/4)*3;
597 tmp = PRO_VRAM[0][ofs+1];
598 fontcell[i*2+1] = '0' + ((tmp >> 2) & 0x3F);
599 tmp <<= 4;
600 tmp |= (PRO_VRAM[0][ofs]>>12);
601 fontcell[i*2] = '0' + ((tmp) & 0x3F);
602 }
603 break;
604 }
605 case 2:
606 {
607 for (i=0; i<PRO_FONT_SCANLINES; i++)
608 {
609 ofs = vlist[i] + OFS + (x/4)*3;
610 tmp = PRO_VRAM[0][ofs+1];
611 fontcell[i*2] = '0' + ((tmp >> 8) & 0x3F);
612 tmp >>= 14;
613 tmp |= (PRO_VRAM[0][ofs+2]<<2);
614 fontcell[i*2+1] = '0' + ((tmp) & 0x3F);
615 }
616 break;
617 }
618 case 3:
619 {
620 for (i=0; i<PRO_FONT_SCANLINES; i++)
621 {
622 ofs = vlist[i] + OFS + (x/4)*3;
623 tmp = PRO_VRAM[0][ofs+2];
624 fontcell[i*2] = '0' + ((tmp >> 4) & 0x3F);
625 fontcell[i*2+1] = '0' + ((tmp >> 10) & 0x3F);
626 }
627 break;
628 }
629 }
630 {
631 int hashed = hash(fontcell);
632 int bold = 0, reverse = 0;
633
634 if (hashed > 511) { hashed -= 512; reverse=1; }
635 if (hashed > 255) { hashed -= 256; bold=1; }
636 switch (hashed)
637 {
638 case 0: hashed = ' '; break;
639 case 30: hashed = ACS_BLOCK; break;
640 case 128: hashed = ACS_DIAMOND; break;
641 case 129: hashed = ACS_CKBOARD; break;
642 case 134: hashed = ACS_DEGREE; break;
643 case 135: hashed = ACS_PLMINUS; break;
644 case 138: hashed = ACS_LRCORNER; break;
645 case 139: hashed = ACS_URCORNER; break;
646 case 140: hashed = ACS_ULCORNER; break;
647 case 141: hashed = ACS_LLCORNER; break;
648 case 142: hashed = ACS_PLUS; break;
649 case 143: hashed = ACS_S1; break;
650 #ifdef ACS_S3
651 case 144: hashed = ACS_S3; break;
652 #endif
653 case 145: hashed = ACS_HLINE; break;
654 #ifdef ACS_S7
655 case 146: hashed = ACS_S7; break;
656 #endif
657 case 147: hashed = ACS_S9; break;
658 case 148: hashed = ACS_LTEE; break;
659 case 149: hashed = ACS_RTEE; break;
660 case 150: hashed = ACS_BTEE; break;
661 case 151: hashed = ACS_TTEE; break;
662 case 152: hashed = ACS_VLINE; break;
663 #ifdef ACS_LEQUAL
664 case 153: hashed = ACS_LEQUAL; break;
665 #endif
666 #ifdef ACS_GEQUAL
667 case 154: hashed = ACS_GEQUAL; break;
668 #endif
669 #ifdef ACS_PI
670 case 155: hashed = ACS_PI; break;
671 #endif
672 #ifdef ACS_NEQUAL
673 case 156: hashed = ACS_NEQUAL; break;
674 #endif
675 #ifdef ACS_STERLING
676 case 157: hashed = ACS_STERLING; break;
677 #endif
678 case 158: hashed = ACS_BULLET; break;
679 default: if (hashed < ' ' || hashed > '~') hashed = '#';
680 }
681 mvwaddch(main_window, y, x, hashed|(bold?A_BOLD:0)|(reverse?A_REVERSE:0));
682 }
683 }
684 }
685 #endif
686
687 /* Flush the changes to the screen */
688
689 if (need_update) update();
690 }
691
692
693 /* Set keyboard bell volume */
694
pro_keyboard_bell_vol(int vol)695 void pro_keyboard_bell_vol (int vol)
696 {
697 /* Not implemented for curses */
698 }
699
700
701 /* Sound keyboard bell */
702
pro_keyboard_bell()703 void pro_keyboard_bell ()
704 {
705 fputc('\a', stderr);
706 }
707
708
709 /* Turn off auto-repeat */
710
pro_keyboard_auto_off()711 void pro_keyboard_auto_off ()
712 {
713 /* Not implemented for curses */
714 }
715
716
717 /* Turn on auto-repeat */
718
pro_keyboard_auto_on()719 void pro_keyboard_auto_on ()
720 {
721 /* Not implemented for curses */
722 }
723
724
725 /* Turn off keyclick */
726
pro_keyboard_click_off()727 void pro_keyboard_click_off ()
728 {
729 /* Not implemented for curses */
730 }
731
732
733 /* Turn on keyclick */
734
pro_keyboard_click_on()735 void pro_keyboard_click_on ()
736 {
737 /* Not implemented for curses */
738 }
739
pro_overlay_print(int x,int y,int xnor,int font,char * text)740 void pro_overlay_print(int x, int y, int xnor, int font, char *text)
741 {
742 if (!overlay_window) return;
743 if (font) wattron(overlay_window, A_BOLD);
744 wmove(overlay_window, y, x);
745 for (; *text; text++)
746 {
747 if (*text == ' ' && xnor==1)
748 {
749 chtype ch = winch(overlay_window);
750 waddch(overlay_window, ch^A_REVERSE);
751 }
752 else if (' ' <= *text && *text <= '~')
753 {
754 waddch(overlay_window, *text);
755 }
756 else switch (*text)
757 {
758 case 24: waddch(overlay_window, ACS_ULCORNER); break;
759 case 25:
760 case 29: waddch(overlay_window, ACS_HLINE); break;
761 case 26: waddch(overlay_window, ACS_URCORNER); break;
762 case 27:
763 case 31: waddch(overlay_window, ACS_VLINE); break;
764 case 30: waddch(overlay_window, ACS_LLCORNER); break;
765 case 28: waddch(overlay_window, ACS_LRCORNER); break;
766 default: waddch(overlay_window, ACS_BLOCK);
767 }
768 }
769 if (font) wattroff(overlay_window, A_BOLD);
770 update();
771 return;
772 }
773
pro_overlay_disable()774 void pro_overlay_disable ()
775 {
776 if (!overlay_window) return;
777 delwin(overlay_window);
778 overlay_window = 0;
779 touchwin(main_window);
780 update();
781 }
782
pro_overlay_enable()783 void pro_overlay_enable ()
784 {
785 pro_overlay_disable();
786 overlay_window = newwin(0, 0, 0, 0);
787 }
788
789 #endif
790