1 /*
2  *	MicroEMACS 4.00 	XVT.C
3  *		written by Daniel M. Lawrence
4  *
5  *	(C)Copyright 1995 by Daniel M. Lawrence
6  *	MicroEMACS 4.00 can be copied and distributed freely for any
7  *	non-commercial purposes. MicroEMACS 4.00 can only be incorporated
8  *	into commercial software with the permission of the current author.
9  *
10  *	The routines in this file provide support for the XVT windowing system
11  *
12  *	Notice that the xvt header files force stdlib.h into the compile
13  *	even though it conflicts with some of our declarations......
14  *	This forced us to use the standard definitions and ditch ours.
15  */
16 
17 #define termdef 1			/* don't define term external */
18 #define XVTDRIVER	1		/* this is the XVT driver */
19 #define DXVT(a) xvt_dbg(a); xvt_dbg(NULL)
20 
21 #include	<stdio.h>
22 #include	<stdlib.h>
23 #include	"estruct.h"
24 #include	"eproto.h"
25 #include	"edef.h"
26 #include	"elang.h"
27 
28 #if	XVT
29 #undef	COLOR
30 
31 #include	<xvt.h>
32 #include	<xvtmenu.h>
33 #include	"uemacs.h"
34 
35 int PASCAL NEAR fnclabel(int f, int n);
36 
37 #define NROW	25			/* Screen size. 		*/
38 #define NCOL	80			/* Edit if you want to. 	*/
39 #define NPAUSE	100			/* # times thru update to pause */
40 #define MARGIN	8			/* size of minimim margin and	*/
41 #define SCRSIZ	64			/* scroll size for extended lines */
42 #define BEL	0x07			/* BEL character.		*/
43 #define ESC	0x1B			/* ESC character.		*/
44 
45 /* Forward references.		*/
46 extern int PASCAL NEAR xvtmove();
47 extern int PASCAL NEAR xvteeol();
48 extern int PASCAL NEAR xvteeop();
49 extern int PASCAL NEAR xvtbeep();
50 extern int PASCAL NEAR xvtopen();
51 extern int PASCAL NEAR xvtrev();
52 extern int PASCAL NEAR xvtclose();
53 extern int PASCAL NEAR xvtkopen();
54 extern int PASCAL NEAR xvtkclose();
55 extern int PASCAL NEAR xvtcres();
56 extern int PASCAL NEAR xvtgetc();
57 extern int PASCAL NEAR xvtputc();
58 extern int PASCAL NEAR xvtflush();
59 extern int PASCAL NEAR xvtfcol();
60 extern int PASCAL NEAR xvtbcol();
61 static int rev_state = FALSE;
62 
63 static int cfcolor = -1;	/* current foreground color */
64 static int cbcolor = -1;	/* current background color */
65 
66 /* mouse status information */
67 static int oldcol;	/* previous x position of mouse */
68 static int oldrow;	/* previous y position of mouse */
69 
70 /* Info held for XVT! */
71 
72 #define	MAXOBUF	256	/* maximum number of output characters buffered */
73 
74 WINDOW xvt_win;		/* current window being displayed by XVT */
75 WINDOW init_win;	/* the initial window we are to toss */
76 int xvt_char_width;	/* width of characters in pixels */
77 int xvt_char_height;	/* height of characters in pixels */
78 int xvt_descent;	/* height of descenders (character offset) */
79 int xvt_row = 0;	/* current output row in window */
80 int xvt_col = 0;	/* current column in window */
81 int xvt_fcolor = COLOR_WHITE;	/* current xvt forground color */
82 int xvt_bcolor = COLOR_BLACK;	/* current xvt background color */
83 COLOR xvt_colors[] = {	/* xvt color translation table */
84 	COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
85 	COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE,
86 	COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
87 	COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
88 };
89 char xvt_obuf[MAXOBUF];		/* output characters buffer */
90 char *xvt_next = xvt_obuf;	/* next output character position */
91 char *xvt_end = &xvt_obuf[MAXOBUF-1];	/* end of the buffer */
92 
93 /*
94  * Standard terminal interface dispatch table. Most of the fields point into
95  * "termio" code.
96  */
97 NOSHARE TERM term = {
98 	NROW-1,
99 	NROW-1,
100 	NCOL,
101 	NCOL,
102 	0, 0,
103 	MARGIN,
104 	SCRSIZ,
105 	NPAUSE,
106 	xvtopen,
107 	xvtclose,
108 	xvtkopen,
109 	xvtkclose,
110 	xvtgetc,
111 	xvtputc,
112 	xvtflush,
113 	xvtmove,
114 	xvteeol,
115 	xvteeop,
116 	xvteeop,
117 	xvtbeep,
118 	xvtrev,
119 	xvtcres,
120 	xvtfcol,
121 	xvtbcol
122 };
123 
124 /*	Some XVT specific globals	*/
125 
126 int xvt_argc;		/* save the command line arguments to */
127 char **xvt_argv;	/* pass to the emacs mainline */
128 
dump_event(char * typ,EVENT * ep)129 dump_event(char *typ, EVENT *ep)
130 
131 {
132 	char m[128];	/* message buffer */
133 
134 	DXVT(typ);
135 	switch (ep->type) {
136 		case E_CREATE:
137 			DXVT("E_CREATE:");
138 			break;
139 		case E_FOCUS:
140 			DXVT("E_FOCUS:");
141 			break;
142 		case E_CLOSE:
143 			DXVT("E_CLOSE:");
144 			break;
145 		case E_DESTROY:
146 			DXVT("E_DESTROY:");
147 			break;
148 		case E_UPDATE:
149 			DXVT("E_UPDATE:");
150 			break;
151 		case E_COMMAND:
152 			DXVT("E_COMMAND:");
153 			break;
154 		case E_SIZE:
155 			DXVT("E_SIZE:");
156 			break;
157 		case E_CHAR:
158 			sprintf(m, "E_CHAR: %d S%d C%d", ep->v.chr.ch,
159 				ep->v.chr.shift, ep->v.chr.control);
160 			DXVT(m);
161 			break;
162 		case E_MOUSE_DOWN:
163 			sprintf(m, "E_MOUSE_DOWN: [%d] %d/%d S%d C%d",
164 				ep->v.mouse.button,
165 				ep->v.mouse.where.v,ep->v.mouse.where.h,
166 				ep->v.mouse.shift, ep->v.mouse.control);
167 			DXVT(m);
168 			break;
169 		case E_MOUSE_UP:
170 			sprintf(m, "E_MOUSE_UP: [%d] %d/%d S%d C%d",
171 				ep->v.mouse.button,
172 				ep->v.mouse.where.v,ep->v.mouse.where.h,
173 				ep->v.mouse.shift, ep->v.mouse.control);
174 			DXVT(m);
175 			break;
176 		case E_MOUSE_MOVE:
177 			sprintf(m, "E_MOUSE_MOVE: [%d] %d/%d S%d C%d",
178 				ep->v.mouse.button,
179 				ep->v.mouse.where.v,ep->v.mouse.where.h,
180 				ep->v.mouse.shift, ep->v.mouse.control);
181 			DXVT(m);
182 			break;
183 		default:
184 			sprintf(m, "E_UNKNOWN: %d", ep->type);
185 			DXVT(m);
186 			break;
187 	}
188 }
189 
windowHandler(WINDOW win,EVENT * ep)190 static long windowHandler(WINDOW win, EVENT *ep)
191 
192 {
193 	register int etype;	/* event type byte */
194 	register int event;	/* encoded mouse event */
195 	int mouserow, mousecol;	/* mouse row/column position */
196 
197 /*dump_event("win", ep);*/
198 
199 	switch (ep->type) {
200 		case E_CREATE:
201 			clear_window(win, COLOR_RED);
202 
203 		case E_CHAR:	/* a character has been typed */
204 
205 			/* if it was a simple one */
206 			if (ep->v.chr.ch < UCHAR_MAX) {
207 				in_put(ep->v.chr.ch);
208 				break;
209 			}
210 
211 			/* otherwise, its a function key! */
212 			in_fkey(ep->v.chr.ch);
213 			break;
214 
215 		case E_FOCUS:
216 			break;
217 		case E_UPDATE:
218 /*			sgarbf = TRUE;*/
219 			break;
220 
221 		case E_MOUSE_MOVE:	/* the mouse has moved */
222 		case E_MOUSE_DOWN:	/* a button has gone down */
223 		case E_MOUSE_UP:	/* a button has been released */
224 
225 			/* locate the new charactor position */
226 			mouserow = ep->v.mouse.where.v / xvt_char_height;
227 			mousecol = ep->v.mouse.where.h / xvt_char_width;
228 
229 			/* if its in the same character cell... ignore it */
230 			if ((ep->type == E_MOUSE_MOVE) &&
231 			    (mouserow == oldrow) && (mousecol == oldcol))
232 				return;
233 
234 			/* get the event type */
235 			etype = MOUS >> 8;
236 			if (ep->v.mouse.shift == TRUE)
237 				etype |= (SHFT >> 8);
238 			if (ep->v.mouse.control == TRUE)
239 				etype |= (CTRL >> 8);
240 
241 			/* no buttons changes */
242 			if (ep->type == E_MOUSE_MOVE) {
243 
244 				/* generate a mouse movement */
245 				if (((mouse_move == 1) && (mmove_flag == TRUE)) ||
246 				    (mouse_move == 2)) {
247 					in_put(0);
248 					in_put(etype);
249 					in_put(mousecol);
250 					in_put(mouserow);
251 					in_put('m');
252 				}
253 
254 				/* save the new mouse location */
255 				oldcol = mousecol;
256 				oldrow = mouserow;
257 				break;
258 			}
259 
260 
261 			/* encode the mouse button press */
262 			in_put(0);
263 			in_put(etype);
264 			in_put(mousecol);
265 			in_put(mouserow);
266 
267 			/* direction of the button press */
268 			event = ((ep->type == E_MOUSE_DOWN) ? 0 : 1);
269 			if (ep->v.mouse.button == 1)	/* right button */
270 				event += 4;
271 			if (ep->v.mouse.button == 2)	/* center button */
272 				event += 2;
273 			event += 'a';
274 			in_put(event);
275 
276 			/* save the new mouse location */
277 			oldcol = mousecol;
278 			oldrow = mouserow;
279 			break;
280 
281 		case E_CLOSE:
282 			xvt_terminate();
283 	}
284 	return(0L);
285 }
286 
in_fkey(xvt_code)287 in_fkey(xvt_code)	/* input an xvt key code into the MicroEMACS
288 			   input stream */
289 
290 int xvt_code;
291 
292 {
293 	unsigned int code;	/* resulting MicroEMACS extended key code */
294 
295 	switch (xvt_code) {
296 		case K_F1:     /* function key 1 */
297 			code = SPEC | '1'; break;
298 		case K_F2:
299 			code = SPEC | '2'; break;
300 		case K_F3:
301 			code = SPEC | '3'; break;
302 		case K_F4:
303 			code = SPEC | '4'; break;
304 		case K_F5:
305 			code = SPEC | '5'; break;
306 		case K_F6:
307 			code = SPEC | '6'; break;
308 		case K_F7:
309 			code = SPEC | '7'; break;
310 		case K_F8:
311 			code = SPEC | '8'; break;
312 		case K_F9:
313 			code = SPEC | '9'; break;
314 		case K_F10:
315 			code = SPEC | '0'; break;
316 		case K_F11:
317 			code = SPEC | '-'; break;
318 		case K_F12:
319 			code = SPEC | '='; break;
320 #if	0
321 		case K_F13:
322 			code = SPEC | ''; break;
323 		case K_F14:
324 			code = SPEC | ''; break;
325 		case K_F15:    /* function key 15 */
326 			code = SPEC | ''; break;
327 #endif
328 		case K_UP:     /* up arrow */
329 			code = SPEC | 'P'; break;
330 		case K_DOWN:   /* down arrow */
331 			code = SPEC | 'N'; break;
332 		case K_RIGHT:  /* right arrow */
333 			code = SPEC | 'F'; break;
334 		case K_LEFT:   /* left arrow */
335 			code = SPEC | 'B'; break;
336 		case K_PREV:   /* previous screen */
337 			code = SPEC | 'Z'; break;
338 		case K_NEXT:   /* next screen */
339 			code = SPEC | 'V'; break;
340 		case K_LHOME:  /* line home */
341 			code = SPEC | '<'; break;
342 		case K_LEND:   /* line end */
343 			code = SPEC | '>'; break;
344 		case K_HOME:   /* home */
345 			code = SPEC | SHFT | 'B'; break;
346 		case K_END:    /* end */
347 			code = SPEC | SHFT | 'F'; break;
348 		case K_INS:    /* insert */
349 			code = SPEC | 'C'; break;
350 		case K_WLEFT:  /* word left */
351 			code = SPEC | CTRL | 'B'; break;
352 		case K_WRIGHT: /* word right */
353 			code = SPEC | CTRL | 'F'; break;
354 		case K_BTAB:   /* back tab */
355 			code = SPEC | CTRL | 'I'; break;
356 		case K_HELP:   /* help */
357 			code = SPEC | CTRL | '>'; break;
358 		case K_CLEAR:  /* clear */
359 			code = SPEC | 'k'; break;
360 	}
361 
362 	/* put the key in the input stream */
363 	in_put(0);
364 	in_put(code >> 8);
365 	in_put(code & 0xFF);
366 
367 }
368 
taskHandler(WINDOW win,EVENT * ep)369 static long taskHandler(WINDOW win, EVENT *ep)
370 {
371 	RCT rct;
372 	char aname[80]; 	/* application name */
373 	DRAW_CTOOLS dtool;
374 	CBRUSH brush;	/* brushed used for the clearing */
375 	FONT fptr;	/* font to select */
376 	int leading, ascent, descent;
377 
378 
379 /* dump_event("tsk", ep); */
380 
381 	switch (ep->type) {
382 		case E_CREATE:
383 
384 			/* set the drawing mode to opaque */
385 			win_get_draw_ctools(win, &dtool);
386 			dtool.opaque_text = TRUE;
387 			win_set_draw_ctools(win, &dtool);
388 
389 			/* select an appropriate non-proportional font */
390 			select_font(FF_FIXED, 0, 10, &fptr);
391 			win_set_font(win, &fptr, FALSE);
392 
393 			/* set the current brush color! */
394 			brush.pat = PAT_SOLID;
395 			brush.color = xvt_colors[cbcolor];
396 			win_set_cbrush(win, &brush);
397 
398 			/* discover the size of the current font */
399 			win_get_font_metrics(win, &leading, &ascent, &descent);
400 			xvt_char_height = leading + ascent + descent;
401 			xvt_descent = descent;
402 			xvt_char_width  = win_get_text_width(win, "M", 1);
403 
404 			/* hide the task window... we aren't going to use it */
405 			show_window(win, FALSE);
406 
407 			/* set up a rect to get an 25 x 80 window */
408 			set_rect(&rct, xvt_char_width * 1, xvt_char_height * 2,
409 				 xvt_char_width * 82, xvt_char_height * 27);
410 			strcpy(aname, PROGNAME);
411 			strcat(aname, " ");
412 			strcat(aname, VERSION);
413 
414 			/* create the first screen window */
415 			xvt_win = create_window(W_DOC, &rct, aname, 0,
416 				SCREEN_WIN, WSF_SIZE|WSF_CLOSE|/*WSF_HSCROLL|
417 				WSF_VSCROLL|*/WSF_NO_MENUBAR,
418 				EM_ALL, windowHandler, 0L);
419 			called_main(xvt_argc, xvt_argv);
420 		case E_CLOSE:
421 			close_window(win);
422 			break;
423 	}
424 	return(0L);
425 }
426 
xvt_main(argc,argv)427 xvt_main(argc, argv)
428 
429 int argc;
430 char **argv;
431 
432 {
433 	XVT_CONFIG config;
434 	char aname[80]; 	/* application name */
435 
436 	/* save the command line arguments to pass to emacs */
437 	xvt_argc = argc;
438 	xvt_argv = argv;
439 
440 	/* set up the structure to let XVT know how to start */
441 	config.menu_bar_ID = MAIN_MENUBAR;
442 	config.about_box_ID = 0;
443 	config.base_appl_name = "uemacs";
444 	strcpy(aname, PROGNAME);
445 	strcat(aname, " ");
446 	strcat(aname, VERSION);
447 	config.appl_name = aname;
448 	config.taskwin_title = aname;
449 
450 	xvt_system(argc, argv, 0L, taskHandler, &config);
451 }
452 
xvtfcol(color)453 PASCAL NEAR xvtfcol(color)		/* set the current output color */
454 
455 int color;	/* color to set */
456 
457 {
458 	if (color == cfcolor)
459 		return;
460 	xvtflush();
461 	win_set_fore_color(xvt_win, xvt_colors[color]);
462 	cfcolor = color;
463 }
464 
xvtbcol(color)465 PASCAL NEAR xvtbcol(color)		/* set the current background color */
466 
467 int color;	/* color to set */
468 
469 {
470 	if (color == cbcolor)
471 		return;
472 	xvtflush();
473 	win_set_back_color(xvt_win, xvt_colors[color]);
474 	cbcolor = color;
475 }
476 
xvtmove(row,col)477 PASCAL NEAR xvtmove(row, col)
478 {
479 	xvtflush();
480 	xvt_row = row;
481 	xvt_col = col;
482 }
483 
xvteeol()484 PASCAL NEAR xvteeol()
485 {
486 	RCT rect;	/* rectangle to use to clear to end of this line */
487 	CBRUSH brush;	/* brushed used for the clearing */
488 
489 	xvtflush();
490 
491 	/* set the rectangles limits */
492 	set_rect(&rect, xvt_col * xvt_char_width,
493 			xvt_row * xvt_char_height - 1,
494 			term.t_ncol * xvt_char_width,
495 			(xvt_row + 1) * xvt_char_height - 1);
496 
497 	/* set the current brush color! */
498 	brush.pat = PAT_SOLID;
499 	brush.color = xvt_colors[cbcolor];
500 	win_set_cbrush(xvt_win, &brush);
501 	win_set_std_cpen(xvt_win, TL_PEN_HOLLOW);
502 
503 	/* and clear it */
504 	win_draw_rect(xvt_win, &rect);
505 }
506 
xvteeop()507 PASCAL NEAR xvteeop()
508 {
509 	RCT rect;	/* rectangle to use to clear to end of this line */
510 	CBRUSH brush;	/* brushed used for the clearing */
511 
512 	xvtflush();
513 
514 	/* set the current brush color! */
515 	brush.pat = PAT_SOLID;
516 	brush.color = xvt_colors[gbcolor];
517 	win_set_cbrush(xvt_win, &brush);
518 	win_set_std_cpen(xvt_win, TL_PEN_HOLLOW);
519 
520 	/* first erase to the end of this line... */
521 	/* set the rectangles limits */
522 	set_rect(&rect, xvt_col * xvt_char_width,
523 			xvt_row * xvt_char_height - 1,
524 			term.t_ncol * xvt_char_width,
525 			(xvt_row + 1) * xvt_char_height + 1);
526 
527 	/* and clear it */
528 	win_draw_rect(xvt_win, &rect);
529 
530 	/* and then the rest of the window downward */
531 	/* set the rectangles limits */
532 	set_rect(&rect, 0,
533 			(xvt_row + 1) * xvt_char_height - 1,
534 			term.t_ncol * xvt_char_width,
535 			term.t_nrow * xvt_char_height);
536 
537 	/* and clear it */
538 	win_draw_rect(xvt_win, &rect);
539 }
540 
xvtrev(state)541 PASCAL NEAR xvtrev(state)		/* change reverse video state */
542 
543 int state;	/* TRUE = reverse, FALSE = normal */
544 
545 {
546 	int ftmp, btmp; 	/* temporaries for colors */
547 
548 	if (state != rev_state) {
549 		ftmp = cfcolor;
550 		btmp = cbcolor;
551 		cfcolor = -1;
552 		cbcolor = -1;
553 		xvtfcol(btmp);
554 		xvtbcol(ftmp);
555 		rev_state = state;
556 	}
557 }
558 
xvtcres()559 PASCAL NEAR xvtcres()	/* change screen resolution */
560 
561 {
562 	return(TRUE);
563 }
564 
spal(char * dummy)565 PASCAL NEAR spal(char *dummy)		/* change pallette settings */
566 
567 {
568 	/* none for now */
569 }
570 
xvtbeep()571 PASCAL NEAR xvtbeep()
572 {
573 	xvt_beep();
574 }
575 
xvtopen()576 PASCAL NEAR xvtopen()
577 
578 {
579 	DRAW_CTOOLS dtool;
580 	CBRUSH brush;	/* brushed used for the clearing */
581 	FONT fptr;	/* font to select */
582 	int leading, ascent, descent;
583 
584 	/* set the drawing mode to opaque */
585 	win_get_draw_ctools(xvt_win, &dtool);
586 	dtool.opaque_text = TRUE;
587 	win_set_draw_ctools(xvt_win, &dtool);
588 
589 	/* select an appropriate non-proportional font */
590 	select_font(FF_FIXED, 0, 10, &fptr);
591 	win_set_font(xvt_win, &fptr, FALSE);
592 
593 	/* set the current brush color! */
594 	brush.pat = PAT_SOLID;
595 	brush.color = xvt_colors[cbcolor];
596 	win_set_cbrush(xvt_win, &brush);
597 
598 	/* discover the size of the current font */
599 	win_get_font_metrics(xvt_win, &leading, &ascent, &descent);
600 	xvt_char_height = leading + ascent + descent;
601 	xvt_descent = descent;
602 	xvt_char_width  = win_get_text_width(xvt_win, "M", 1);
603 
604 	/* initialize the mouse status */
605 	oldcol = -1;
606 	oldrow = -1;
607 
608 	/* initialize the output character queue */
609 	xvt_next = xvt_obuf;
610 
611 	/* let emacs know the screen is open */
612 	strcpy(sres, "XVT");
613 	revexist = TRUE;
614 	ttopen();
615 }
616 
xvtclose()617 PASCAL NEAR xvtclose()
618 
619 {
620 	xvtfcol(7);
621 	xvtbcol(0);
622 	ttclose();
623 }
624 
xvtkopen()625 PASCAL NEAR xvtkopen()	/* open the keyboard (a noop here) */
626 
627 {
628 
629 }
630 
xvtkclose()631 PASCAL NEAR xvtkclose() /* close the keyboard (a noop here) */
632 
633 {
634 	xvtflush();
635 }
636 
637 /*
638  * Read a character from the terminal, performing no editing and doing no echo
639  * at all. Also mouse events are forced into the input stream here.
640  */
xvtgetc()641 int PASCAL NEAR xvtgetc()
642 
643 {
644 	xvtflush();
645 
646 	/* try first.... */
647 	if (in_check())
648 		return(in_get());
649 
650 	/* turn on the text cursor! */
651 	caret_on(xvt_win, xvt_col * xvt_char_width, (xvt_row + 1) * xvt_char_height - 1);
652 
653 	/* loop waiting for something to happen */
654 	while (TRUE) {
655 		process_events();
656 		if (in_check()) {
657 			/* turn off the text cursor */
658 			caret_off(xvt_win);
659 
660 			/* and return the event */
661 			return(in_get());
662 		}
663 	}
664 }
665 
xvtflush()666 int PASCAL NEAR xvtflush()
667 
668 {
669 	/* if there's nothing to flush */
670 	if (xvt_next == xvt_obuf)
671 		return;
672 
673 	/* draw the characters out */
674 	win_draw_text(xvt_win, xvt_col * xvt_char_width,
675 			(xvt_row + 1) * xvt_char_height - 1 - xvt_descent,
676 			&xvt_obuf[0], (xvt_next - xvt_obuf));
677 
678 	xvt_col += (xvt_next - xvt_obuf);
679 	xvt_next = xvt_obuf;
680 }
681 
xvtputc(c)682 int PASCAL NEAR xvtputc(c)
683 
684 char c;	/* character to write to the current xvt window */
685 
686 {
687 	/* backspaces just backup the pointers */
688 	if (c == '\b') {
689 		xvtflush();
690 		xvt_col--;
691 		if (xvt_col < 0)
692 			xvt_col = 0;
693 		return;
694 	}
695 
696 	/* don't go too far! */
697 	if (xvt_next == xvt_end)
698 		xvtflush();
699 
700 	*xvt_next++ = c;
701 }
702 
703 #if	FLABEL
fnclabel(f,n)704 int PASCAL NEAR fnclabel(f, n)		/* label a function key */
705 
706 int f,n;	/* default flag, numeric argument [unused] */
707 
708 {
709 	/* on machines with no function keys...don't bother */
710 	return(TRUE);
711 }
712 #endif
713 #else
xvthello()714 xvthello()
715 {
716 }
717 #endif
718