NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / mac / mttymain.c
blob0f85ab03eb0b026745709d82249deb0da5d56543
1 /* aNetHack 0.0.1 mttymain.c $ANH-Date: 1432512797 2015/05/25 00:13:17 $ $ANH-Branch: master $:$ANH-Revision: 1.12 $ */
2 /* Copyright (c) Jon W{tte, 1993 */
3 /* aNetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #include "macwin.h"
7 #include "mttypriv.h"
8 #include "mactty.h"
9 #include "wintty.h"
11 #if !TARGET_API_MAC_CARBON
12 #include <Palettes.h>
13 #endif
14 #include <Gestalt.h>
16 #define MT_WINDOW 135
17 #define MT_WIDTH 80
18 #define MT_HEIGHT 24
21 * Names:
23 * Statics are prefixed _
24 * Mac-tty becomes mt_
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 */
35 static char _attrs_inverse[5] = {
36 0, 0, 0, 0, 0,
39 /* see color.h */
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 */
60 static char _colors_inverse[CLR_MAX] = {
61 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 #ifdef CHANGE_COLOR
66 #define POWER_LIMIT 22
67 #define SECONDARY_POWER_LIMIT 16
68 #define CHANNEL_LIMIT 14
69 #define SECONDARY_CHANNEL_LIMIT 12
71 void
72 tty_change_color(int color, long rgb, int reverse)
74 long inverse, working_rgb = rgb;
75 int total_power = 0, max_channel = 0;
76 int cnt = 3;
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;
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;
93 if (reverse) {
94 working_rgb = rgb;
95 rgb = inverse;
96 inverse = working_rgb;
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;
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");
115 void
116 tty_change_background(int white_or_black)
118 register int i;
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 */
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;
150 char *
151 tty_get_color_string(void)
153 char *ptr;
154 int count;
155 static char color_buf[5 * (CLR_MAX + 5) + 1];
157 color_buf[0] = 0;
158 ptr = color_buf;
160 for (count = 0; count < CLR_MAX; count++) {
161 int flag = _colors_inverse[count] ? 1 : 0;
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);
169 for (count = 0; count < 5; count++) {
170 int flag = _attrs_inverse[count] ? 1 : 0;
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);
179 return color_buf;
181 #endif
183 extern struct DisplayDesc *ttyDisplay; /* the tty display descriptor */
185 char kill_char = CHAR_ESC;
186 char erase_char = CHAR_BS;
188 WindowRef _mt_window = (WindowRef) 0;
189 static Boolean _mt_in_color = 0;
190 extern short win_fonts[NHW_TEXT + 1];
192 static void
193 _mt_init_stuff(void)
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;
200 LI = MT_HEIGHT;
201 CO = MT_WIDTH;
203 if (!strcmp(windowprocs.name, "mac")) {
204 dprintf("Mac Windows");
205 LI -= 1;
206 } else {
207 dprintf("TTY Windows");
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
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;
225 gdh = GetNextDevice(gdh);
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);
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.");
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.");
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);
254 ShowWindow(_mt_window);
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);
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);
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);
271 InitMenuRes();
275 tgetch(void)
277 EventRecord event;
278 long sleepTime = 0;
279 int ret = 0;
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;
290 ret = GetFromKeyQueue();
291 if (ret == CHAR_CR)
292 ret = CHAR_LF;
294 return ret;
297 void
298 getreturn(char *str)
300 FlushEvents(-1, 0);
301 msmsg("Press space %s", str);
302 (void) tgetch();
306 has_color(int color)
308 #if defined(__SC__) || defined(__MRC__)
309 #pragma unused(color)
310 #endif
311 Rect r;
312 // Point p = {0, 0};
313 GDHandle gh;
315 if (!_mt_in_color)
316 return 0;
318 GetWindowBounds(_mt_window, kWindowContentRgn, &r);
319 // SetPortWindowPort(_mt_window);
320 // LocalToGlobal (&p);
321 // OffsetRect (&r, p.h, p.v);
323 gh = GetMaxDevice(&r);
324 if (!gh) {
325 return 0;
328 return (*((*gh)->gdPMap))->pixelSize > 4; /* > 4 bpp */
331 void
332 tty_delay_output(void)
334 EventRecord event;
335 long toWhen = TickCount() + 3;
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);
346 void
347 cmov(int x, int y)
349 move_tty_cursor(_mt_window, x, y);
350 ttyDisplay->cury = y;
351 ttyDisplay->curx = x;
354 void
355 nocmov(int x, int y)
357 cmov(x, y);
360 static void
361 _mt_set_colors(long *colors)
363 short err;
365 if (!_mt_in_color) {
366 return;
368 err = set_tty_attrib(_mt_window, TTY_ATTRIB_FOREGROUND, colors[0]);
369 err = set_tty_attrib(_mt_window, TTY_ATTRIB_BACKGROUND, colors[1]);
372 void
373 term_end_attr(int attr)
375 #if defined(__SC__) || defined(__MRC__)
376 #pragma unused(attr)
377 #endif
378 _mt_set_colors(_mt_attrs[0]);
381 void
382 term_start_attr(int attr)
384 switch (attr) {
385 case ATR_ULINE:
386 _mt_set_colors(_mt_attrs[1]);
387 break;
388 case ATR_BOLD:
389 _mt_set_colors(_mt_attrs[2]);
390 break;
391 case ATR_BLINK:
392 _mt_set_colors(_mt_attrs[3]);
393 break;
394 case ATR_INVERSE:
395 _mt_set_colors(_mt_attrs[4]);
396 break;
397 default:
398 _mt_set_colors(_mt_attrs[0]);
399 break;
403 void
404 standoutend(void)
406 term_end_attr(ATR_INVERSE);
409 void
410 standoutbeg(void)
412 term_start_attr(ATR_INVERSE);
415 void
416 term_end_color(void)
418 _mt_set_colors(_mt_colors[NO_COLOR]);
421 void
422 cl_end(void)
424 _mt_set_colors(_mt_attrs[0]);
425 clear_tty_window(_mt_window, ttyDisplay->curx, ttyDisplay->cury, CO - 1,
426 ttyDisplay->cury);
429 void
430 clear_screen(void)
432 _mt_set_colors(_mt_attrs[0]);
433 clear_tty(_mt_window);
436 void
437 cl_eos(void)
439 _mt_set_colors(_mt_attrs[0]);
440 clear_tty_window(_mt_window, ttyDisplay->curx, ttyDisplay->cury, CO - 1,
441 LI - 1);
444 void
445 home(void)
447 cmov(0, 0);
450 void
451 backsp(void)
453 char eraser[] = { CHAR_BS, CHAR_BLANK, CHAR_BS, 0 };
454 short err;
456 err = add_tty_string(_mt_window, eraser);
457 err = update_tty(_mt_window);
460 void
461 msmsg(const char *str, ...)
463 va_list args;
464 char buf[1000];
466 va_start(args, str);
467 vsprintf(buf, str, args);
468 va_end(args);
470 xputs(buf);
473 void
474 term_end_raw_bold(void)
476 term_end_attr(ATR_INVERSE);
479 void
480 term_start_raw_bold(void)
482 term_start_attr(ATR_INVERSE);
485 void
486 term_start_color(int color)
488 if (color >= 0 && color < CLR_MAX) {
489 _mt_set_colors(_mt_colors[color]);
493 void
494 setftty(void)
496 long flag;
498 /* Buffered output for the game */
499 get_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, &flag);
500 flag &= ~TA_ALWAYS_REFRESH;
501 flag |= TA_INHIBIT_VERT_SCROLL; /* don't scroll */
502 set_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, flag);
503 iflags.cbreak = 1;
506 void
507 tty_startup(int *width, int *height)
509 _mt_init_stuff();
510 *width = CO;
511 *height = LI;
514 void
515 gettty(void)
519 void
520 settty(const char *str)
522 long flag;
524 update_tty(_mt_window);
526 /* Buffered output for the game, raw in "raw" mode */
527 get_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, &flag);
528 flag &= ~TA_INHIBIT_VERT_SCROLL; /* scroll */
529 flag |= TA_ALWAYS_REFRESH;
530 set_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, flag);
532 tty_raw_print("\n");
533 if (str) {
534 tty_raw_print(str);
538 void
539 tty_number_pad(int arg)
541 #if defined(__SC__) || defined(__MRC__)
542 #pragma unused(arg)
543 #endif
546 void
547 tty_start_screen(void)
549 iflags.cbreak = 1;
552 void
553 tty_end_screen(void)
557 void
558 xputs(const char *str)
560 add_tty_string(_mt_window, str);
564 term_puts(const char *str)
566 xputs(str);
567 return strlen(str);
571 term_putc(int c)
573 short err;
575 err = add_tty_char(_mt_window, c);
576 return err ? EOF : c;
580 term_flush(void *desc)
582 if (desc == stdout || desc == stderr) {
583 update_tty(_mt_window);
584 } else {
585 impossible("Substituted flush for file");
586 return fflush(desc);
588 return 0;