OSDN Git Service

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