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