1 /*	ST52.C:	Atari ST1040/520 screen support functions
2 		written by lots of people (see below)
3 
4 		Daniel Lawrence
5 		James Turner
6 		Jeff Lomicka
7 		J. C. Benoist
8 
9 	Modification History:
10 	31-dec-87	Jeff Lomicka
11 	- massive changes/additions for accessories and mouse
12 	20-jan-87	Daniel Lawrence
13 	- changed code in domousekey() to pass five bytes, two zeros
14 	  (to tell input.c that this is a mouse event), x/ypos
15 	  and the mouse event type.
16 	may 88		Jeff Lomicka and Dan Lawrence
17 	- a lot of changes.  Through out aline.h, use the MWC and
18 	  ATARI names for things now.
19 	- moving the mouse to the extreme upper left brings up
20 	  the desk accessory menu.  EMACS won't replot on the
21 	  way out yet.
22 	- cleaned up behavior of the mouse and the cursor on exit
23 	26-feb-89	Daniel Lawrence
24 	- rewote input layer to conform to new specs in input.c
25 	01-may-91	Daniel Lawrence/Suggested by Allan Pratt
26 	- renamed atari source files to TOS.C and ST52.c
27 	- changed symbols ATARI => ST52 and ST520 => TOS
28 */
29 
30 #define termdef 1		/* don't define "term" external */
31 
32 #include	<stdio.h>
33 #include	"estruct.h"
34 #include	"eproto.h"
35 #include	"edef.h"
36 #include	"elang.h"
37 
38 #if	ST52
39 
40 /*
41 	These routines provide support for the ATARI 1040ST and 520ST
42 using the virtual VT52 Emulator
43 
44 */
45 
46 #include	<aesbind.h>
47 #include	<gemdefs.h>
48 #include	<obdefs.h>
49 #include	<osbind.h>
50 #include	<xbios.h>
51 #include	<linea.h>
52 
53 #define NROW	50	/* Screen size. 		*/
54 #define NCOL	80	/* Edit if you want to. 	*/
55 #define MARGIN	8	/* size of minimim margin and	*/
56 #define SCRSIZ	64	/* scroll size for extended lines */
57 #define NPAUSE	300	/* # times thru update to pause */
58 #define BIAS	0x20	/* Origin 0 coordinate bias.	*/
59 #define ESC	0x1B	/* ESC character.		*/
60 #define SCRFONT 2	/* index of 8x16 monochrome system default font */
61 #define DENSIZE 50	/* # of lines in a dense screen */
62 
63 /****	ST Internals definitions		*****/
64 
65 /*	BIOS calls */
66 
67 #define BCONSTAT	1	/* return input device status */
68 #define CONIN		2	/* read character from device */
69 #define BCONOUT 	3	/* write character to device */
70 
71 /*	XBIOS calls */
72 
73 #define INITMOUS	0	/* initialize the mouse 	*/
74 #define GETREZ		4	/* get current resolution	*/
75 #define SETSCREEN	5	/* set screen resolution	*/
76 #define SETPALETTE	6	/* set the color pallette	*/
77 #define SETCOLOR	7	/* set or read a color		*/
78 #define CURSCONF	21	/* set cursor configuration	*/
79 #define IKBDWS		25	/* intelligent keyboard send command */
80 #define KBDVBASE	34	/* get keyboard table base	*/
81 
82 /*	GEMDOS calls */
83 
84 #define EXEC		0x4b	/* Exec off a process */
85 #define CON		2	/* CON: Keyboard and screen device */
86 
87 /*	Palette color definitions	*/
88 
89 #define LOWPAL	"000700070770007707077777333733373773337737377777"
90 #define MEDPAL	"000700007777"
91 #define HIGHPAL "111000"
92 
93 /*	ST Global definitions		*/
94 
95 int initrez;			/* initial screen resolution */
96 int currez;			/* current screen resolution */
97 int gemflag;			/* were we called from the desktop? */
98 int mouseon;			/* True if mouse is on */
99 char resname[][8] = {		/* screen resolution names */
100 	"LOW", "MEDIUM", "HIGH", "DENSE"
101 };
102 short spalette[16];		/* original color palette settings */
103 short palette[16];		/* current palette settings */
104 static short scursor;		/* original text cursor mode */
105 
106 struct la_data *aline;		/* Line A data structure */
107 
108 struct la_ext *naline;		/* extended Line A data structure */
109 
110 struct la_font **fonts;	/* Array of pointers to the three system
111  			 font headers returned by init (in register A1) */
112 
113 struct la_font *system_font;	/* pointer to default system font */
114 struct la_font *small_font;	/* pointer to small font */
115 
116 /*
117 	These are needed to make GEM happy
118 */
119 int contrl[ 11], intin[ 128], intout[ 128], ptsin[ 256], ptsout[ 12];
120 static int worki[ 11] = {1,1,1,1,1,1,1,1,1,1,2}, worko[ 57];
121 
122 /*
123 	Some useful information about our environment
124 */
125 static int
126 	g_wchar, g_hchar,	/* VDI's idea of current font size */
127 	junk, gid, wkid;	/* Graphics ID, workstation ID */
128 
129 static int oldbut = 0;		/* Previous state of mouse buttons */
130 static int mctrl;		/* current BEG_MOUSE state */
131 static struct { char *norm, *shift, *caps;} *kt;	/* Keyboard mapping */
132 
133 /*
134 	This object tree is for displaying the desk accessory menu.
135 	Actual positions are written into this structure when the
136 	screen size is known.
137 */
138 OBJECT menu[] =
139     {
140     -1, 1, 4,	G_IBOX,   NONE,  NORMAL, 0x0L,	    0 , 0,   0,   0,/* Root */
141      4, 2, 2,	 G_BOX,   NONE,  NORMAL, 0x10F0L,   0,	0,   1,   1,/* BAR */
142      1, 3, 3,	G_IBOX,   NONE,  NORMAL, 0x0L,	    0,	0,   1,   1,/* Active */
143      2,-1,-1,  G_TITLE,   NONE,  NORMAL,  "",	    0,	0,   1,   1,/* title */
144      0, 5, 5,	G_IBOX,   NONE,  NORMAL, 0x0L,	    0,	0,   0,   0,/* screen */
145      4, 6,13,	 G_BOX,   NONE,  NORMAL, 0xFF1100L, 0,	0,   0,   0,/* box */
146      7,-1,-1, G_STRING,   NONE,  NORMAL, TEXT179,0,0,168,	16,
147 /*                                       "  About MicroEmacs" */
148      8,-1,-1, G_STRING,   NONE,DISABLED, "---------------------",
149 						    0, 16, 168,  16,
150      9,-1,-1, G_STRING,   NONE,  NORMAL, "",	    0, 32, 168,  16,
151     10,-1,-1, G_STRING,   NONE,  NORMAL, "",	    0, 48, 168,  16,
152     11,-1,-1, G_STRING,   NONE,  NORMAL, "",	    0, 64, 168,  16,
153     12,-1,-1, G_STRING,   NONE,  NORMAL, "",	    0, 80, 168,  16,
154     13,-1,-1, G_STRING,   NONE,  NORMAL, "",	    0, 96, 168,  16,
155      5,-1,-1, G_STRING, LASTOB,  NORMAL, "",	    0,112, 168,  16
156     };
157 
158 extern mymouse();		/* .s file for calling two mouse handlers */
159 int (*first_mhandler)();	/* Address of first handler */
160 int (*second_mhandler)();	/* Address of second handler */
161 struct kbdvbase *kv;		/* Keyboard vector table */
162 static int msevntsiz = 0;	/* Events in private mouse event queue */
163 static unsigned short msevntq[16];/* State of mouse keys at event */
164 static int msevntin = 0;	/* Queue input ptr */
165 static int msevntout = 0;	/* Queue output ptr */
166 static int mousekeys1 = 0;	/* Last mouse key event */
167 static int mousecol = HUGE;	/* current mouse column */
168 static int mouserow = HUGE;	/* current mouse row */
169 
170 extern	int	ttopen();		/* Forward references.		*/
171 extern	int	ttgetc();
172 extern	int	ttputc();
173 extern	int	ttflush();
174 extern	int	ttclose();
175 extern	int	stmove();
176 extern	int	steeol();
177 extern	int	steeop();
178 extern	int	stbeep();
179 extern	int	stopen();
180 extern	int	stclose();
181 extern	int	stgetc();
182 extern	int	stputc();
183 extern	int	strev();
184 extern	int	strez();
185 extern	int	stkopen();
186 extern	int	stkclose();
187 
188 #if	COLOR
189 extern	int	stfcol();
190 extern	int	stbcol();
191 #endif
192 
193 /*
194  * Dispatch table. All the
195  * hard fields just point into the
196  * terminal I/O code.
197  */
198 TERM	term	= {
199 	NROW-1,
200 	NROW-1,
201 	NCOL,
202 	NCOL,
203 	0, 0,
204 	MARGIN,
205 	SCRSIZ,
206 	NPAUSE,
207 	&stopen,
208 	&stclose,
209 	&stkopen,
210 	&stkclose,
211 	&stgetc,
212 	&stputc,
213 	&ttflush,
214 	&stmove,
215 	&steeol,
216 	&steeop,
217 	&steeop,
218 	&stbeep,
219 	&strev,
220 	&strez
221 #if	COLOR
222 	, &stfcol,
223 	&stbcol
224 #endif
225 };
226 
227 /*	input buffers and pointers	*/
228 
229 #define	IBUFSIZE	64	/* this must be a power of 2 */
230 
231 unsigned char in_buf[IBUFSIZE];	/* input character buffer */
232 int in_next = 0;		/* pos to retrieve next input character */
233 int in_last = 0;		/* pos to place most recent input character */
234 
in_init()235 in_init()	/* initialize the input buffer */
236 
237 {
238 	in_next = in_last = 0;
239 }
240 
in_check()241 in_check()	/* is the input buffer non-empty? */
242 
243 {
244 	if (in_next == in_last)
245 		return(FALSE);
246 	else
247 		return(TRUE);
248 }
249 
in_put(event)250 in_put(event)
251 
252 int event;	/* event to enter into the input buffer */
253 
254 {
255 	in_buf[in_last++] = event;
256 	in_last &= (IBUFSIZE - 1);
257 }
258 
in_get()259 int in_get()	/* get an event from the input buffer */
260 
261 {
262 	register int event;	/* event to return */
263 
264 	event = in_buf[in_next++];
265 	in_next &= (IBUFSIZE - 1);
266 	return(event);
267 }
268 
init_aline()269 void init_aline()
270 
271 {
272 	int *ld_contrl;
273 	int *ld_intin;
274 
275 	linea0();
276 
277 	/* save if the current mouse is hidden (ie we are not in GEM) */
278 	gemflag = (mousehidden == 0);
279 	while (mousehidden) {
280 		showmouse();
281 		}
282 	aline = (struct la_data *)(la_init.li_a0);
283 	fonts = (struct la_font **)(la_init.li_a1);
284 	naline = ((struct la_ext *)aline) - 1;
285 	scursor = naline->ld_status;		/* State of text cursor */
286 	ld_contrl = aline->ld_contrl;		/* -> control junk	*/
287 	ld_intin  = aline->ld_intin;		/* -> intin junk	*/
288 }
289 
init()290 init()
291 
292 {
293 	init_aline();
294 	system_font = fonts[SCRFONT];	    /* save it */
295 	small_font = fonts[1];
296 }
297 
298 
299 switch_font(fp)
300 
301 struct la_font *fp;
302 
303 {
304        /* See linea.h for description of fields */
305 
306        V_CEL_HT = fp->font_height;
307        V_CEL_WR = aline->ld_vwrap * fp->font_height;
308        V_CEL_MY = (naline->ld_y_max / fp->font_height) - 1;
309        V_CEL_MX = (naline->ld_x_max / fp->font_fat_cell) - 1;
310        V_FNT_WR = fp->font_width;
311        V_FNT_ST = fp->font_low_ade;
312        V_FNT_ND = fp->font_hi_ade;
313        V_OFF_AD = (long) fp->font_char_off;
314        V_FNT_AD = (long) fp->font_data;
315 }
316 
stmove(row,col)317 stmove(row, col)
318 
319 {
320 	stputc(ESC);
321 	stputc('Y');
322 	stputc(row+BIAS);
323 	stputc(col+BIAS);
324 }
325 
steeol()326 steeol()
327 
328 {
329 	stputc(ESC);
330 	stputc('K');
331 }
332 
steeop()333 steeop()
334 
335 {
336 #if	COLOR
337 	stfcol(gfcolor);
338 	stbcol(gbcolor);
339 #endif
340 	stputc(ESC);
341 	stputc('J');
342 }
343 
strev(status)344 strev(status)	/* set the reverse video state */
345 
346 int status;	/* TRUE = reverse video, FALSE = normal video */
347 
348 {
349 	if (currez > 1) {
350 		stputc(ESC);
351 		stputc(status ? 'p' : 'q');
352 	}
353 }
354 
355 #if	COLOR
mapcol(clr)356 mapcol(clr)	/* medium rez color translation */
357 
358 int clr;	/* emacs color number to translate */
359 
360 {
361 	static int mctable[] = {0, 1, 2, 3, 2, 1, 2, 3};
362 
363 	if (currez != 1)
364 		return(clr);
365 	else
366 		return(mctable[clr]);
367 }
368 
stfcol(color)369 stfcol(color)	/* set the forground color */
370 
371 int color;	/* color to set forground to */
372 
373 {
374 	if (currez < 2) {
375 		stputc(ESC);
376 		stputc('b');
377 		stputc(mapcol(color));
378 	}
379 }
380 
stbcol(color)381 stbcol(color)	/* set the background color */
382 
383 int color;	/* color to set background to */
384 
385 {
386 	if (currez < 2) {
387 		stputc(ESC);
388 		stputc('c');
389 		stputc(mapcol(color));
390 	}
391 }
392 #endif
393 
394 static char beep[] = {
395 	0x00, 0x00,
396 	0x01, 0x01,
397 	0x02, 0x01,
398 	0x03, 0x01,
399 	0x04, 0x02,
400 	0x05, 0x01,
401 	0x07, 0x38,
402 	0x08, 0x10,
403 	0x09, 0x10,
404 	0x0A, 0x10,
405 	0x0B, 0x00,
406 	0x0C, 0x30,
407 	0x0D, 0x03,
408 	0xFF, 100,
409 	0x09, 0x00,
410 	0x0A, 0x00,
411 	0xFF, 0x00
412 };
413 
stbeep()414 stbeep()
415 
416 {
417 	Dosound(beep);
418 }
419 
mouse_on()420 mouse_on()	/* turn the gem mouse ON */
421 
422 {
423 	if (!mouseon) {
424 	    graf_mouse( M_ON, 0L);
425 	    graf_mouse(ARROW, 0L);
426 	    mouseon = 1;
427 	}
428 }
429 
mouse_off()430 mouse_off()	/* turn the gem mouse OFF */
431 
432 {
433 	if (mouseon) {
434 	    graf_mouse( M_OFF, 0L);
435 	    mouseon = 0;
436 	}
437 	if( !mousehidden) stbeep();
438 }
439 
440 /*
441 	me_mh - MicroEmacs Mouse interrupt Handler.  This handler is called,
442 	in addition to the regular mouse handler, in order for microemacs
443 	to have access to some more information about the mouse events.
444 
445 	What it does is:
446 
447 	- Queue a copy of the mouse button state at the actual moment of
448 	the event, rather than after GEM is finished playing with timers.
449 
450 	- Convert all right-mouse-button events into left-mouse-button
451 	events BEFORE GEM's mouse interrupt handler, so that GEM will generate
452 	a left-mouse-button event.
453 */
me_mh(a)454 me_mh(a)
455 
456 char *a;
457 {
458 	register unsigned mousekeys;
459 
460 	mousekeys = a[0] & 7;
461 	if (mousekeys != 0)
462 		a[0] = 0xFA;	 /* Any key down means button 1 down */
463 	else
464 		a[0] = 0xf8;	/* Otherwise button 1 up */
465 	if (msevntsiz < 16) {
466 		/* Previous event was processed, look for next one */
467 		if (mousekeys != mousekeys1) {
468 			/* A button change is detected, insert it in queue */
469 			msevntq[msevntin++] = mousekeys;
470 			msevntin &= 15;
471 			msevntsiz++;
472 			mousekeys1 = mousekeys;
473 		}
474 	}
475 }
476 
477 
stkopen()478 stkopen()	/* open the keyboard (and mouse) */
479 {
480 }
481 
stopen()482 stopen()	/* open the screen */
483 
484 {
485 	register int i;
486 
487 	init();
488 	strcpy(os, "TOS");
489 
490 /*
491 	Set up an interrupt handler for the mouse that performs both
492 	me_mh() and the default mouse handling.  The .s file "stmouse.s"
493 	contains some special code for this purpose.
494 */
495 	first_mhandler = me_mh;
496 	kv = Kbdvbase();
497 	second_mhandler = kv->kb_mousevec;
498 	kv->kb_mousevec = mymouse;
499 /*
500 	In order to have both the mouse cursor and the text cursor on the
501 	screen at the same time, we have to flash it ourselves, turning
502 	the mouse cursor on and off for each flash.
503 
504 	The cursors are both off whenever we are not in an input wait.
505 */
506 	Cursconf(3, 0);	/* Stop text cursor from flashing */
507 	Cursconf(0, 0);	/* Turn text cursor off */
508 /*
509 	Wake up GEM and the VDI
510 */
511 	appl_init();
512 	gid = graf_handle(&g_wchar, &g_hchar, &junk, &junk);
513 #if	0
514 	/* We never use the VDI, but if you do, turn this back on */
515 	v_opnvwk(worki, &wkid, worko);
516 #endif
517 	graf_mouse( M_OFF, 0L);
518 	mouseon = 0;
519 /*
520 	Set up the menu bar's coordinates to match the font and screen size
521 	for this screen resolution
522 */
523 	wind_get(0, WF_CURRXYWH,	/* Fetch actual screen size for menu */
524 		&menu[0].ob_x, &menu[0].ob_y,
525 		&menu[0].ob_width, &menu[0].ob_height);
526 	menu[1].ob_x = menu[0].ob_width - 1;	/* Locate "desk" box */
527 	menu[4].ob_width = menu[0].ob_width;
528 	menu[4].ob_height = 8*g_hchar;
529 	menu[5].ob_width = 21*g_wchar;
530 	menu[5].ob_height = 8*g_hchar;
531 	menu[5].ob_x = menu[0].ob_width - menu[5].ob_width;
532 	for(i=6; i<14; i++) {
533 		/* Desk accessory items */
534 		menu[i].ob_y = (i-6)*g_hchar;
535 		menu[i].ob_width = menu[5].ob_width;
536 		menu[i].ob_height = g_hchar;
537 	}
538 	menu_bar(menu, 1);
539 /*
540 	Shut off GEM's user interface until we enter an input wait.
541 	Note that unless we claim the mouse with BEG_MCTRL, we will not
542 	get scheduled to run any time the left mouse button goes down while
543 	the mouse is on the top 16 pixels of the screen.  We keep Emacs
544 	"hung" whenever MCTRL is given to desk accessories or GEM, and keep
545 	GEM hung whenever we have control.
546 */
547 	wind_update(BEG_UPDATE);	/* Shuts off GEM drawing */
548 	wind_update(BEG_MCTRL);		/* Shuts off GEM use of mouse */
549 
550 	mctrl = 0;			/* Flag that we have mouse control */
551 	kt = Keytbl( -1L, -1L, -1L);
552 
553 	ttopen();
554 	eolexist = TRUE;
555 
556 	/* save the current color palette */
557 	for (i=0; i<16; i++)
558 		spalette[i] = xbios(SETCOLOR, i, -1);
559 
560 	/* and find the current resolution */
561 	initrez = currez = xbios(GETREZ);
562 	strcpy(sres, resname[currez]);
563 
564 	/* set up the screen size and palette */
565 	switch (currez) {
566 		case 0: term.t_mrow = 25 - 1;
567 			term.t_nrow = 25 - 1;
568 			term.t_ncol = 40;
569 			strcpy(palstr, LOWPAL);
570 			break;
571 
572 		case 1: term.t_mrow = 25 - 1;
573 			term.t_nrow = 25 - 1;
574 			strcpy(palstr, MEDPAL);
575 			break;
576 
577 		case 2: term.t_mrow = DENSIZE - 1;
578 			term.t_nrow = 25 - 1;
579 			strcpy(palstr, HIGHPAL);
580 	}
581 
582 	/* and set up the default palette */
583 	spal(palstr);
584 
585 	stputc(ESC);	/* automatic overflow off */
586 	stputc('w');
587 
588 	/* initialize the input buffer */
589 	in_init();
590 }
591 
stkclose()592 stkclose()	/* close the keyboard (and mouse) */
593 {
594 }
595 
stclose()596 stclose()
597 
598 {
599 	stputc(ESC);	/* auto overflow on */
600 	stputc('v');
601 
602 	/* restore the original screen resolution */
603 	if (currez == 3)
604 		switch_font(system_font);
605 	strez(resname[initrez]);
606 
607 	/* restore the original palette settings */
608 	xbios(SETPALETTE, spalette);
609 
610 	ttclose();
611 
612 	kv->kb_mousevec = second_mhandler;	/* Restore original handler */
613 
614 	mouse_on();		/* turn the mouse on */
615 	if (gemflag != 0) {
616 		/* coming from gem..... we */
617 		Cursconf(0, 0);		/* turn the cursor off */
618 	} else {
619 		/* coming from a shell, we */
620 		Cursconf(1, 0);		/* turn the cursor on */
621 		Cursconf(2, 0);		/* Turn text cursor blinking */
622 		hidemouse();		/* Turn mouse off for shell */
623 	}
624 
625 	wind_update(END_MCTRL);		/* Return GEM's control of screen */
626 	wind_update(END_UPDATE);
627 #if	0
628 	v_clsvwk(wkid);			/* Clean up GEM */
629 #endif
630 	appl_exit();
631 }
632 
633 /*	spal(pstr):	reset the current palette according to a
634 			"palette string" of the form
635 
636 	000111222333444555666777
637 
638 	which contains the octal values for the palette registers
639 */
640 
spal(pstr)641 spal(pstr)
642 
643 char *pstr;	/* palette string */
644 
645 {
646 	int pal;	/* current palette position */
647 	int clr;	/* current color value */
648 	int i;
649 
650 	for (pal = 0; pal < 16; pal++) {
651 		if (*pstr== 0)
652 			break;
653 
654 		/* parse off a color */
655 		clr = 0;
656 		for (i = 0; i < 3; i++)
657 			if (*pstr)
658 				clr = clr * 16 + (*pstr++ - '0');
659 		palette[pal] = clr;
660 	};
661 
662 	/* and now set it */
663 	xbios(SETPALETTE, palette);
664 }
665 
domousekey(newbut,sk)666 static domousekey(newbut, sk)
667 
668 int sk;
669 
670 {
671 	register int k;
672 
673 	for(k=1; k!=4; k = k<<1) {	/* J is butnum, k is bit num */
674 		/* For each button on the mouse */
675 		if ((oldbut&k) != (newbut&k)) {
676 			/* This button changed, generate an event */
677 			in_put(0);		/* escape indicator */
678 			in_put(MOUS >> 8);	/* mouse event */
679 			in_put(mousecol);	/* x-position */
680 			in_put(mouserow);	/* y-position */
681 			in_put(((newbut&k) ? 0 : 1)
682 				+ (k==1 ? 4 : 0)
683 				+ ((sk&3) ? 'A' : 'a'));
684 		}
685 	}
686 	oldbut = newbut;
687 }
688 
stgetc()689 stgetc()	/* get a char from the keyboard */
690 
691 {
692 	register int flashcounter;	/* Counter for flashing cursor */
693 	register int ev_which;		/* Event returned */
694 	register int sc;		/* Keyboard scan code */
695 	static int bexpected = 1;	/* Expected next mouse state */
696 	int mx, my, bstate, sk, key, mc;/* Event parameters */
697 	int mes[8];
698 
699 	/* Working out a multi-byte input sequence */
700 	if (in_check())
701 		return(in_get());
702 
703 	Cursconf(1, 0);		/* Turn text cursor on */
704 	mouse_on();		/* Let mouse work */
705 	wind_update(END_UPDATE);
706 	if (mctrl)
707 		wind_update(END_MCTRL);
708 	flashcounter = 0;
709 	for(;;) {
710 		if (!mctrl) {
711 			/* We have control, so it is okay to flash cursor */
712 			if (flashcounter == 6) {
713 				mouse_off();
714 				Cursconf(0, 0); /* After 60ms, turn it off */
715 				mouse_on();
716 			} else if (flashcounter == 10) {
717 				/* Wrapped around one cycle of cursor flashing,
718 				   turn it on */
719 				mouse_off();
720 				Cursconf(1, 0);
721 				mouse_on();
722 				flashcounter = 0;
723 			}
724 		}
725 
726 		/* do the event-multi thing */
727 		ev_which = evnt_multi(
728 			MU_TIMER | MU_MESAG | MU_KEYBD | MU_BUTTON | MU_M1,
729 			1,		/* Maximum clicks to wait for */
730 			1,		/* Buttons that generate events */
731 			bexpected,	/* Button states that generate events */
732 			0, menu[1].ob_x, menu[1].ob_y,
733 			menu[1].ob_width, menu[1].ob_height,
734 			0, 0, 0, 0, 0,	/* enter/exit, x, y, w, h for rect 2 */
735 			mes,		/* Buffer to receive mesasge */
736 			/* Low and high order miliseconds of counter */
737 			100, 0,
738 			&mx, &my,	/* Mouse location */
739 			&bstate,	/* State of the mouse buttons */
740 			&sk,		/* State of the shift keys */
741 			&key,		/* Key pressed */
742 			&mc);		/* Actual number of clicks */
743 
744 		if (ev_which & MU_KEYBD) {
745 			/* Keyboard events cause keystrokes, add SPC prefix to fn keys */
746 			if (mctrl)
747 				wind_update(BEG_MCTRL);
748 			Giaccess(0, 9+128);
749 			Giaccess(0, 10+128);
750 
751 			/* Cancel any double-clicking */
752 			nclicks = 0;
753 			mctrl = 0;
754 
755 	 	        sc = key>>8;
756 		        key &= 0xff;
757 			extcode( sk, sc, key);
758 		} else if (ev_which & MU_BUTTON) {
759 			/* Mouse event, look at our actual mouse event */
760 			int top, junk;
761 			wind_get(0, WF_TOP, &top, &junk, &junk, &junk);
762 			if (top == 0) {
763 				/* Desktop is top window,
764 				   allow Emacs to continue */
765 				bexpected = (~bstate)&1;
766 				mousecol = mx/g_wchar;
767 				mouserow = my/g_hchar;
768 				while(msevntsiz > 0) {
769 					/* Process each queued event */
770 					domousekey(msevntq[msevntout++], sk);
771 					msevntout &= 15;
772 					msevntsiz--;
773 					}
774 				if (mctrl) wind_update(BEG_MCTRL);
775 				mctrl = 0;
776 			}
777 		} else if (ev_which & MU_M1) {
778 			/* Mouse entered desk menu, allow it to appear */
779 			if (!mctrl) wind_update(END_MCTRL);
780 			mctrl = 1;
781 			sgarbf = TRUE;
782 		} else if (ev_which & MU_TIMER) {
783 			flashcounter++;
784 		} else {
785 			/* Most likely is the about message */
786 		}
787 
788 		/* is there now a pending event? */
789 		if (in_check()) {
790 			key = in_get();
791 			break;
792 		}
793 	}
794 
795 	if (mctrl)
796 		wind_update(BEG_MCTRL);
797 	wind_update(BEG_UPDATE);
798 	mouse_off();
799 	Cursconf(0, 0);			/* Turn text cursor off */
800 	return(key & 0xFF);
801 }
802 
stputc(c)803 stputc(c)	/* output char c to the screen */
804 
805 char c; 	/* character to print out */
806 
807 {
808 	bios(BCONOUT, CON, c);
809 }
810 
strez(newrez)811 strez(newrez)	/* change screen resolution */
812 
813 char *newrez;	/* requested resolution */
814 
815 {
816 	int nrez;	/* requested new resolution */
817 
818 	/* first, decode the resolution name */
819 	for (nrez = 0; nrez < 4; nrez++)
820 		if (strcmp(newrez, resname[nrez]) == 0)
821 			break;
822 	if (nrez == 4) {
823 		mlwrite(TEXT180);
824 /*                      "%%No such resolution" */
825 		return(FALSE);
826 	}
827 
828 	/* next, make sure this resolution is legal for this monitor */
829 	if ((currez < 2 && nrez > 1) || (currez > 1 && nrez < 2)) {
830 		mlwrite(TEXT181);
831 /*                      "%%Resolution illegal for this monitor" */
832 		return(FALSE);
833 	}
834 
835 	/* eliminate non-changes */
836 	if (currez == nrez)
837 		return(TRUE);
838 
839 	/* finally, make the change */
840 	switch (nrez) {
841 		case 0: /* low resolution - 16 colors */
842 			newwidth(TRUE, 40);
843 			strcpy(palstr, LOWPAL);
844 			xbios(SETSCREEN, -1L, -1L, 0);
845 			g_wchar = g_hchar = 8;
846 			break;
847 
848 		case 1: /* medium resolution - 4 colors */
849 			newwidth(TRUE, 80);
850 			strcpy(palstr, MEDPAL);
851 			xbios(SETSCREEN, -1L, -1L, 1);
852 			g_wchar = g_hchar = 8;
853 			break;
854 
855 		case 2: /* High resolution - 2 colors - 25 lines */
856 			newsize(TRUE, 25);
857 			strcpy(palstr, HIGHPAL);
858 			switch_font(system_font);
859 			g_wchar = g_hchar = 16;
860 			break;
861 
862 		case 3: /* Dense resolution - 2 colors - 40 lines */
863 			newsize(TRUE, DENSIZE);
864 			strcpy(palstr, HIGHPAL);
865 			switch_font(small_font);
866 			g_wchar = g_hchar = 8;
867 			break;
868 	}
869 
870 	/* and set up the default palette */
871 	spal(palstr);
872 	currez = nrez;
873 	strcpy(sres, resname[currez]);
874 
875 	stputc(ESC);	/* automatic overflow off */
876 	stputc('w');
877 	return(TRUE);
878 }
879 
880 /*	extcode:	resolve Atari-ST extended character codes
881 			encoding the proper sequences into emacs
882 			printable character specifications
883 */
884 
extcode(sk,sc,key)885 int extcode( sk, sc, key)
886 unsigned sk;	/* Shift keys from event */
887 unsigned sc;	/* ST scancode */
888 unsigned key;	/* GEMDOS translation of the key */
889     {
890     int shift;	/* CAPS LOCK flag doesn't come from EVENT_MULTI */
891     unsigned code;	/* Build up special function code */
892 /*
893 	Identify any shit-key codes associated with this keystorke
894 */
895     code = 0;
896 /*
897 	I don't know why, but for some reason the codes for ALT of top row and
898 	for CTRL of left, right and HOME come up wrong, and this fixes them.
899 */
900     if( sc == 0x77) sc = 0x47;
901     else if( sc == 0x73) sc = 0x4b;
902     else if( sc == 0x74) sc = 0x4d;
903     else if( sc > 0x76) sc -= 0x76;
904 /*
905 	Bring the shifted function key scan codes back into regular range
906 */
907     if( sc >= 0x54 && sc <= 0x5d) sc -= (0x54-0x3B);
908     if( sk & K_ALT)
909 	{ /* ALT shift requires special handling */
910 	code |= ALTD;
911 /*
912 	ALT of ordinary keys always returns '0' for the key.  Look up
913 	the actual key as if ALT weren't there.
914 */
915 	shift = Getshift(-1);	/* Get state of shift keys (CAPS lock) */
916 /*
917 	Map the key to a normal keystroke.  Keypad keys are treated special,
918 	everyone else is mapped using the installed keytables.  This
919 	means it will work right on German and other keyboards.
920 */
921 	if( sk & K_CTRL) { code |= CTRL; key = kt->caps[ sc];}
922 	else if( sk & 3) key = kt->shift[ sc];	/* shift */
923 	else if( shift & 16) key = kt->caps[ sc];	/* Caps lock */
924 	else key = kt->norm[ sc];
925 	}
926 /*
927 	Peel of the numeric keypad keys
928 */
929     if( sc == 0x72) key = 'E';
930     if( sc >= 0x63 || sc == 0x4A || sc == 0x4E)
931 	{ /* Keypad keys are SPEC or CTRL of what's on the key */
932 	code |= SPEC | CTRL;
933 	}
934 /*
935 	translate function keys into digits
936 */
937     if( sc >= 0x3b && sc <= 0x5d)
938 	{ /* This is a F1 thry F9 */
939 	code |= SPEC;
940 	key = sc - 0x3b + '1';
941 	if( key == '9'+1) key = '0';
942 	}
943     if( sc == 0x62) { code |= SPEC; key = 'H';}
944     if( sc == 0x61) { code |= SPEC; key = 'X';}
945     if( sc == 0x52) { code |= SPEC; key = 'C';}
946     if( sc == 0x47) { code |= SPEC; key = 'D';}
947     if( sc == 0x48) { code |= SPEC; key = 'P';}
948     if( sc == 0x4b) { code |= SPEC; key = 'B';}
949     if( sc == 0x50) { code |= SPEC; key = 'N';}
950     if( sc == 0x4d) { code |= SPEC; key = 'F';}
951 /*
952 	translate CTRL-shifted of keys that don't usually CTRL
953 */
954     if((sk & K_CTRL) && (sc <= 0x0D || key == 0))
955 	{ /* Control of a non-usually-control key */
956 	shift = Getshift(-1);	/* Get state of CAPS lock */
957 	code |= CTRL;
958 	if( sk & 3) key = kt->shift[ sc];		/* shift */
959 	else if( shift & 16) key = kt->caps[ sc];	/* Caps lock */
960 	else key = kt->norm[ sc];
961 	}
962     if( key == 0) key = '@';				/* Catch junk */
963     if( code != 0)
964 	{ /* This is a special key */
965 	if( code & SPEC)
966 	    { /* Get shift and ctrl of function keys */
967 	    if( sk & 3) code |= SHFT;
968 	    if( sk & K_CTRL) code |= CTRL;
969 	    }
970 	in_put( 0);
971 	in_put( code>>8);
972 	in_put( key);
973 	}
974     else in_put( key);
975     }
976 
977 #if	FLABEL
fnclabel(f,n)978 fnclabel(f, n)		/* label a function key */
979 
980 int f,n;	/* default flag, numeric argument [unused] */
981 
982 {
983 	/* on machines with no function keys...don't bother */
984 	return(TRUE);
985 }
986 #endif
987 #else
sthello()988 sthello()
989 {
990 }
991 #endif
992