1 /*	SCCS Id: @(#)mttymain.c	3.1	93/02/26			*/
2 /* Copyright (c) Jon W{tte, 1993					*/
3 /* NetHack may be freely redistributed.  See license for details.	*/
4 
5 #include "hack.h"
6 #include "macwin.h"
7 #include "mttypriv.h"
8 #include "mactty.h"
9 #include "wintty.h"
10 
11 #include <Palettes.h>
12 
13 #define MT_WINDOW 135
14 #define MT_WIDTH 80
15 #define MT_HEIGHT 24
16 
17 
18 /*
19  * Names:
20  *
21  * Statics are prefixed _
22  * Mac-tty becomes mt_
23  */
24 
25 static long _mt_attrs [5] [2] = {
26 	{ 0x000000, 0xffffff }, /* Normal */
27 	{ 0xff8080, 0xffffff }, /* Underline */
28 	{ 0x40c020, 0xe0e0e0 }, /* Bold */
29 	{ 0x003030, 0xff0060 }, /* Blink */
30 	{ 0xff8888, 0x000000 }, /* Inverse */
31 };
32 
33 
34 static char _attrs_inverse [5] = {
35 	0, 0, 0, 0, 0 ,
36 };
37 
38 
39 /* see color.h */
40 
41 static long _mt_colors [CLR_MAX] [2] = {
42 	{ 0x000000, 0x808080 }, /* Black */
43 	{ 0x880000, 0xffffff }, /* Red */
44 	{ 0x008800, 0xffffff }, /* Green */
45 	{ 0x553300, 0xffffff }, /* Brown */
46 	{ 0x000088, 0xffffff }, /* Blue */
47 	{ 0x880088, 0xffffff }, /* Magenta */
48 	{ 0x008888, 0xffffff }, /* Cyan */
49 	{ 0x888888, 0xffffff }, /* Gray */
50 	{ 0x000000, 0xffffff }, /* No Color */
51 	{ 0xff4400, 0xffffff }, /* Orange */
52 	{ 0x00ff00, 0xffffff }, /* Bright Green */
53 	{ 0xffff00, 0x606060 }, /* Yellow */
54 	{ 0x0033ff, 0xffffff }, /* Bright Blue */
55 	{ 0xff00ff, 0xffffff }, /* Bright Magenta */
56 	{ 0x00ffff, 0xffffff }, /* Bright Cyan */
57 	{ 0xffffff, 0x505050 }, /* White */
58 };
59 
60 static char _colors_inverse [CLR_MAX] = {
61 	1, 0, 0, 0 ,
62 	0, 0, 0, 0 ,
63 	0, 0, 0, 0 ,
64 	0, 0, 0, 0 ,
65 };
66 
67 
68 #ifdef CHANGE_COLOR
69 
70 #define POWER_LIMIT 22
71 #define SECONDARY_POWER_LIMIT 16
72 #define CHANNEL_LIMIT 14
73 #define SECONDARY_CHANNEL_LIMIT 12
74 
75 void
tty_change_color(int color,long rgb,int reverse)76 tty_change_color (int color, long rgb, int reverse) {
77 long inverse, working_rgb = rgb;
78 int total_power = 0, max_channel = 0;
79 int cnt = 3;
80 
81 	working_rgb >>= 4;
82 	while (cnt -- > 0) {
83 		total_power += working_rgb & 0xf;
84 		max_channel = max (max_channel, working_rgb & 0xf);
85 		working_rgb >>= 8;
86 	}
87 
88 	if (total_power >= POWER_LIMIT ||
89 		(total_power >= SECONDARY_POWER_LIMIT &&
90 			max_channel >= SECONDARY_CHANNEL_LIMIT) ||
91 			max_channel >= CHANNEL_LIMIT)
92 		inverse = 0x000000;
93 	else
94 		inverse = 0xffffff;
95 
96 	if (reverse) {
97 		working_rgb = rgb;
98 		rgb = inverse;
99 		inverse = working_rgb;
100 	}
101 
102 	if (color >= CLR_MAX) {
103 		if (color - CLR_MAX >= 5)
104 			impossible ("Changing too many colors");
105 		else {
106 			_mt_attrs [color - CLR_MAX] [0] = rgb;
107 			_mt_attrs [color - CLR_MAX] [1] = inverse;
108 			_attrs_inverse [color - CLR_MAX] = reverse;
109 		}
110 	} else if (color >= 0) {
111 		_mt_colors [color] [0] = rgb;
112 		_mt_colors [color] [1] = inverse;
113 		_colors_inverse [color] = reverse;
114 	} else
115 		impossible ("Changing negative color");
116 }
117 
tty_change_background(int white_or_black)118 void tty_change_background (int white_or_black) {
119 	register int i;
120 
121 	for (i = 0; i < CLR_MAX; i++) {
122 		if (white_or_black)
123 			_mt_colors [i] [1] = 0xffffff;	/* white */
124 		else
125 			_mt_colors [i] [1] = 0x000000;	/* black */
126 	}
127 
128 	/* special cases */
129 	if (white_or_black) {
130 		_mt_colors [CLR_BLACK] [1] = 0x808080;	/* differentiate black from no color */
131 		_mt_colors [CLR_WHITE] [1] = 0x505050;	/* highlight white with grey background */
132 		_mt_colors [CLR_YELLOW] [1] = 0x606060;	/* highlight yellow with grey background */
133 		_mt_colors [CLR_BLUE] [0] = 0x000088;	/* make pure blue */
134 		_mt_colors [NO_COLOR] [0] = 0x000000; /* make no_color black on white */
135 		_mt_attrs [0] [0] = 0x000000;		/* "normal" is black on white */
136 		_mt_attrs [0] [1] = 0xffffff;
137 	} else {
138 		_mt_colors [NO_COLOR] [0] = 0xffffff; /* make no_color white on black */
139 		_mt_colors [CLR_BLACK] [1] = 0x808080;	/* differentiate black from no color */
140 		_mt_colors [CLR_BLUE] [0] = 0x222288;	/* lighten blue - it's too dark on black */
141 		_mt_attrs [0] [0] = 0xffffff;		/* "normal" is white on black */
142 		_mt_attrs [0] [1] = 0x000000;
143 	}
144 }
145 
146 char *
tty_get_color_string(void)147 tty_get_color_string (void) {
148 char *ptr;
149 int count;
150 static char color_buf [5 * (CLR_MAX + 5) + 1];
151 
152 	color_buf [0] = 0;
153 	ptr = color_buf;
154 
155 	for (count = 0; count < CLR_MAX; count ++) {
156 	int flag = _colors_inverse [count] ? 1 : 0;
157 
158 		sprintf (ptr, "%s%s%x%x%x", count ? "/" : "" ,
159 			flag ? "-" : "" ,
160 			(_mt_colors [count] [flag] >> 20) & 0xf ,
161 			(_mt_colors [count] [flag] >> 12) & 0xf ,
162 			(_mt_colors [count] [flag] >> 4) & 0xf);
163 		ptr += strlen (ptr);
164 	}
165 	for (count = 0; count < 5; count ++) {
166 	int flag = _attrs_inverse [count] ? 1 : 0;
167 
168 		sprintf (ptr, "/%s%x%x%x" ,
169 			flag ? "-" : "" ,
170 			(_mt_attrs [count] [flag] >> 20) & 0xf ,
171 			(_mt_attrs [count] [flag] >> 12) & 0xf ,
172 			(_mt_attrs [count] [flag] >> 4) & 0xf);
173 		ptr += strlen (ptr);
174 	}
175 
176 	return color_buf;
177 }
178 #endif
179 
180 
181 extern struct DisplayDesc *ttyDisplay;	/* the tty display descriptor */
182 
183 char kill_char = CHAR_ESC;
184 char erase_char = CHAR_BS;
185 
186 WindowPtr _mt_window = (WindowPtr) 0;
187 static Boolean _mt_in_color = 0;
188 extern short win_fonts [NHW_TEXT + 1];
189 
190 static void
_mt_init_stuff(void)191 _mt_init_stuff (void) {
192 long resp, flag;
193 short num_cols, num_rows, win_width, win_height, font_num, font_size;
194 short char_width, row_height;
195 short hor, vert;
196 
197 	LI = MT_HEIGHT;
198 	CO = MT_WIDTH;
199 
200 	if (!strcmp(windowprocs.name, "mac")) {
201 		dprintf ("Mac Windows");
202 		LI -= 1;
203 	} else {
204 		dprintf ("TTY Windows");
205 	}
206 
207 	/*
208 	 * If there is at least one screen CAPABLE of color, and if
209 	 * 32-bit QD is there, we use color. 32-bit QD is needed for the
210 	 * offscreen GWorld
211 	 */
212 	if (!Gestalt (gestaltQuickdrawVersion, &resp) && resp > 0x1ff) {
213 		GDHandle gdh = GetDeviceList ();
214 		while (gdh) {
215 			if (TestDeviceAttribute (gdh, screenDevice)) {
216 				if (HasDepth (gdh, 4, 1, 1) ||
217 					HasDepth (gdh, 8, 1, 1) ||
218 					HasDepth (gdh, 16, 1, 1) ||
219 					HasDepth (gdh, 32, 1, 1)) {
220 					_mt_in_color = 1;
221 					break;
222 				}
223 			}
224 			gdh = GetNextDevice (gdh);
225 		}
226 	}
227 
228 	mustwork (create_tty (&_mt_window, WIN_BASE_KIND + NHW_MAP, _mt_in_color));
229 	((WindowPeek) _mt_window)->windowKind = (WIN_BASE_KIND + NHW_MAP);
230 	SelectWindow (_mt_window);
231 	SetPort (_mt_window);
232 	SetOrigin (-1, -1);
233 
234 	font_size = (iflags.large_font && !small_screen) ? 12 : 9;
235 	mustwork (init_tty_number (_mt_window, win_fonts [NHW_MAP], font_size, CO, LI));
236 
237 	mustwork (get_tty_metrics (_mt_window, &num_cols, &num_rows, &win_width ,
238 		&win_height, &font_num, &font_size, &char_width, &row_height));
239 
240 	SizeWindow (_mt_window, win_width + 2, win_height + 2, 1);
241 	if (RetrievePosition (kMapWindow, &vert, &hor)) {
242 		dprintf ("Moving window to (%d,%d)", hor, vert);
243 		MoveWindow (_mt_window, hor, vert, 1);
244 	}
245 	ShowWindow (_mt_window);
246 
247 	/* Start in raw, always flushing mode */
248 	mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, &flag));
249 	flag |= TA_ALWAYS_REFRESH | TA_WRAP_AROUND;
250 	mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, flag));
251 
252 	mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_CURSOR, &flag));
253 	flag |= (TA_BLINKING_CURSOR | TA_NL_ADD_CR);
254 	mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_CURSOR, flag));
255 
256 	mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FOREGROUND, _mt_colors [NO_COLOR] [0]));
257 	mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_BACKGROUND, _mt_colors [NO_COLOR] [1]));
258 	clear_tty (_mt_window);//
259 
260 	InitMenuRes ();
261 }
262 
263 
264 int
tgetch(void)265 tgetch (void) {
266 EventRecord event;
267 long sleepTime = 0;
268 int ret = 0;
269 
270 	for (;!ret;) {
271 		WaitNextEvent (-1, &event, sleepTime, 0);
272 		HandleEvent (&event);
273 		blink_cursor (_mt_window, event.when);
274 		if (event.what == nullEvent) {
275 			sleepTime = GetCaretTime ();
276 		} else {
277 			sleepTime = 0;
278 		}
279 		ret = GetFromKeyQueue ();
280 		if (ret == CHAR_CR) ret = CHAR_LF;
281 	}
282 	return ret;
283 }
284 
285 
286 void
getreturn(char * str)287 getreturn (char *str) {
288 	FlushEvents (-1, 0);
289 	msmsg ("Press space %s", str);
290 	(void) tgetch ();
291 }
292 
293 
294 int
has_color(int color)295 has_color (int color) {
296 #if defined(applec) || defined(__MWERKS__)
297 # pragma unused(color)
298 #endif
299 Rect r;
300 Point p = {0, 0};
301 GDHandle gh;
302 
303 	if (!_mt_in_color) {
304 		return 0;
305 	}
306 
307 	r = _mt_window->portRect;
308 	SetPort (_mt_window);
309 	LocalToGlobal (&p);
310 	OffsetRect (&r, p.h, p.v);
311 
312 	gh = GetMaxDevice (&r);
313 	if (!gh) {
314 		return 0;
315 	}
316 
317 	return (*((*gh)->gdPMap))->pixelSize > 4; /* > 4 bpp */
318 }
319 
320 
321 void
tty_delay_output(void)322 tty_delay_output (void) {
323 EventRecord event;
324 long toWhen = TickCount () + 3;
325 
326 	while (TickCount () < toWhen) {
327 		WaitNextEvent (updateMask, &event, 3L, 0);
328 		if (event.what == updateEvt) {
329 			HandleEvent (&event);
330 			blink_cursor (_mt_window, event.when);
331 		}
332 	}
333 }
334 
335 
336 void
cmov(int x,int y)337 cmov (int x, int y) {
338 	move_tty_cursor (_mt_window, x, y);
339 	ttyDisplay->cury = y;
340 	ttyDisplay->curx = x;
341 }
342 
343 
344 void
nocmov(int x,int y)345 nocmov (int x, int y) {
346 	cmov (x, y);
347 }
348 
349 
350 static void
_mt_set_colors(long * colors)351 _mt_set_colors (long *colors) {
352 short err;
353 
354 	if (!_mt_in_color) {
355 		return;
356 	}
357 	err = set_tty_attrib (_mt_window, TTY_ATTRIB_FOREGROUND, colors [0]);
358 	err = set_tty_attrib (_mt_window, TTY_ATTRIB_BACKGROUND, colors [1]);
359 }
360 
361 
362 void
term_end_attr(int attr)363 term_end_attr (int attr) {
364 #if defined(applec) || defined(__MWERKS__)
365 # pragma unused (attr)
366 #endif
367 	_mt_set_colors (_mt_attrs [0]);
368 }
369 
370 
371 void
term_start_attr(int attr)372 term_start_attr (int attr) {
373 	switch (attr) {
374 		case ATR_ULINE:
375 			_mt_set_colors (_mt_attrs [1]);
376 			break;
377 		case ATR_BOLD:
378 			_mt_set_colors (_mt_attrs [2]);
379 			break;
380 		case ATR_BLINK:
381 			_mt_set_colors (_mt_attrs [3]);
382 			break;
383 		case ATR_INVERSE:
384 			_mt_set_colors (_mt_attrs [4]);
385 			break;
386 		default:
387 			_mt_set_colors (_mt_attrs [0]);
388 			break;
389 	}
390 }
391 
392 
393 void
standoutend(void)394 standoutend (void) {
395 	term_end_attr (ATR_INVERSE);
396 }
397 
398 
399 void
standoutbeg(void)400 standoutbeg (void) {
401 	term_start_attr (ATR_INVERSE);
402 }
403 
404 
405 void
term_end_color(void)406 term_end_color (void) {
407 	_mt_set_colors (_mt_colors [NO_COLOR]);
408 }
409 
410 
411 void
cl_end(void)412 cl_end (void) {
413 	_mt_set_colors (_mt_attrs [0]);
414 	clear_tty_window (_mt_window, ttyDisplay->curx, ttyDisplay->cury,
415 		CO - 1, ttyDisplay->cury);
416 }
417 
418 
419 void
clear_screen(void)420 clear_screen (void) {
421 	_mt_set_colors (_mt_attrs [0]);
422 	clear_tty (_mt_window);
423 }
424 
425 
426 void
cl_eos(void)427 cl_eos (void) {
428 	_mt_set_colors (_mt_attrs [0]);
429 	clear_tty_window (_mt_window, ttyDisplay->curx, ttyDisplay->cury, CO - 1,
430 		LI - 1);
431 }
432 
433 
434 void
home(void)435 home (void) {
436 	cmov (0,0);
437 }
438 
439 
440 void
backsp(void)441 backsp (void) {
442 char eraser [] = { CHAR_BS, CHAR_BLANK, CHAR_BS, 0 };
443 short err;
444 
445 	err = add_tty_string (_mt_window, eraser);
446 	err = update_tty (_mt_window);
447 }
448 
449 
450 void
msmsg(const char * str,...)451 msmsg (const char *str, ...) {
452 va_list args;
453 char buf [1000];
454 
455 	va_start (args, str);
456 	vsprintf (buf, str, args);
457 	va_end (args);
458 
459 	xputs (buf);
460 }
461 
462 
463 void
term_end_raw_bold(void)464 term_end_raw_bold (void) {
465 	term_end_attr (ATR_INVERSE);
466 }
467 
468 
469 void
term_start_raw_bold(void)470 term_start_raw_bold (void) {
471 	term_start_attr (ATR_INVERSE);
472 }
473 
474 
475 void
term_start_color(int color)476 term_start_color (int color) {
477 	if (color >= 0 && color < CLR_MAX) {
478 		_mt_set_colors (_mt_colors [color]);
479 	}
480 }
481 
482 
483 void
setftty(void)484 setftty (void) {
485 long flag;
486 
487 	mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, &flag));
488 /* Buffered output in the game */
489 	flag &= ~ TA_ALWAYS_REFRESH;
490 	flag |= TA_INHIBIT_VERT_SCROLL; /* don't scroll */
491 	mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, flag));
492 
493 	iflags.cbreak = 1;
494 }
495 
496 
497 void
tty_startup(int * width,int * height)498 tty_startup (int *width, int *height ) {
499 	_mt_init_stuff ();
500 	*width = CO;
501 	*height = LI;
502 }
503 
504 
505 void
gettty(void)506 gettty (void) {
507 }
508 
509 
510 void
settty(const char * str)511 settty (const char *str) {
512 long flag;
513 
514 	update_tty (_mt_window);
515 
516 	mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, &flag));
517 /* Buffered output in the game, raw in "raw" mode */
518 	flag &= ~ TA_INHIBIT_VERT_SCROLL; /* scroll */
519 	flag |= TA_ALWAYS_REFRESH;
520 	mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, flag));
521 
522 	tty_raw_print ("\n");
523 	if (str) {
524 		tty_raw_print (str);
525 	}
526 }
527 
528 
529 void
tty_number_pad(int arg)530 tty_number_pad (int arg) {
531 #if defined(applec) || defined(__MWERKS__)
532 # pragma unused(arg)
533 #endif
534 }
535 
536 
537 void
tty_start_screen(void)538 tty_start_screen (void) {
539 	iflags.cbreak = 1;
540 }
541 
542 
543 void
tty_end_screen(void)544 tty_end_screen (void) {
545 }
546 
547 
548 void
xputs(const char * str)549 xputs (const char *str) {
550 	add_tty_string (_mt_window, str);
551 }
552 
553 
554 int
term_puts(const char * str)555 term_puts (const char *str) {
556 	xputs (str);
557 	return strlen (str);
558 }
559 
560 
561 int
term_putc(int c)562 term_putc (int c) {
563 short err;
564 
565 	err = add_tty_char (_mt_window, c);
566 	return err ? EOF : c;
567 }
568 
569 
570 int
term_flush(void * desc)571 term_flush (void *desc) {
572 	if (desc == stdout || desc == stderr) {
573 		update_tty (_mt_window);
574 	} else {
575 		impossible ("Substituted flush for file");
576 		return fflush (desc);
577 	}
578 	return 0;
579 }
580