1 #include <string.h>
2 #include <stdlib.h>
3 #include <errno.h>
4 #include <signal.h>
5 #include <stdio.h> /* for reading stdout.tmp etc. */
6 #include "../config.h"
7 #include <allegro.h>
8 #ifdef UNIX
9 #include <xalleg.h> /* _xwin.application_name,
10 _xwin.application_class */
11 #endif
12 #include "textgfx.h"
13 #include "alleg.h"
14 #include "../options.h"
15 #include "../lang.h"
16 #include "../version.h"
17 #include "../input/keyboard.h"
18
19 #if defined ALLEGRO_WITH_XWINDOWS && defined ALLEGRO_USE_CONSTRUCTOR
20 #include "allegro_icon.h"
21 extern void *allegro_icon;
22 CONSTRUCTOR_FUNCTION(static void _set_allegro_icon());
_set_allegro_icon()23 static void _set_allegro_icon()
24 {
25 allegro_icon = icon_xpm;
26 }
27 #endif
28
29 void blockstyle_from_option(const struct option *o);
30 int ibmgfx(int ch);
31
32 unsigned textgfx_flags = HEIGHT_24L;
33
34 char term_width = 80;
35 char term_height = 25;
36
37 static char curs_x = 0;
38 static char curs_y = 0;
39 char margin_x = 0;
40
41 int win_x = 0;
42 int win_y = 0;
43
44 BITMAP *virt_screen = NULL;
45 int refresh_needed = 0;
46 char blit_rect[4] = {0};
47
48 int close_button_pressed = 0;
49
50 static FONT *font8x16;
51 static int vgacolors[16];
52 static unsigned char bg_color;
53 static unsigned char fg_color;
54
55 #ifdef UNIX
56 static struct sigaction allegro_sigint_handler;
57 #endif
58
gettermsize()59 void gettermsize() {}
settermwidth(int w)60 void settermwidth(int w) {}
settermheight(int h)61 void settermheight(int h) {}
62
gettermoptions()63 void gettermoptions()
64 {
65 struct option *o = getoptions("term");
66 for (; o; o = o->next) {
67 if (!strcmp(opt_key(o), "drawing")) {
68 if (o->val.integ)
69 textgfx_flags |= ASCII;
70 } else if (!strcmp(opt_key(o), "color")) {
71 if (!o->val.integ)
72 textgfx_flags |= MONOCHROME;
73 } else
74 blockstyle_from_option(o);
75 }
76 reset_block_chars();
77 }
78
79 #ifdef UNIX
sigint_handler(int sig)80 static void sigint_handler(int sig)
81 {
82 textgfx_end();
83 allegro_sigint_handler.sa_handler(sig);
84 }
85 #endif
86
load_pc8x16_font()87 static void load_pc8x16_font()
88 {
89 char fname[256];
90 int n;
91 char *p;
92 get_executable_name(fname, sizeof(fname));
93 n = strlen(fname);
94 do n--;
95 while (fname[n] !='\\' && fname[n] !='/');
96 fname[n] = '\0';
97 append_filename(fname, fname, "pc8x16.fnt", sizeof(fname));
98 font8x16 = load_font(fname, NULL, NULL);
99 if (font8x16)
100 return;
101 p = getenv("ALLEGRO");
102 if (p) {
103 strncpy(fname, p, sizeof(fname));
104 append_filename(fname, fname, "vitetris", sizeof(fname));
105 set_allegro_resource_path(5, fname);
106 }
107 #ifdef UNIX
108 set_allegro_resource_path(4, "/usr/share/allegro/vitetris");
109 set_allegro_resource_path(3, "/usr/share/allegro");
110 set_allegro_resource_path(2, "/usr/local/share/allegro/vitetris");
111 set_allegro_resource_path(1, "/usr/local/share/allegro");
112 #endif
113 if (find_allegro_resource(fname, "pc8x16.fnt", 0,0,0,0,0,
114 sizeof(fname)) == 0)
115 font8x16 = load_font(fname, NULL, NULL);
116 }
117
close_btn()118 static void close_btn()
119 {
120 close_button_pressed = 1;
121 }
122
lost_focus()123 static void lost_focus()
124 {
125 textgfx_flags |= LOST_FOCUS;
126 clear_keybuf();
127 }
128
got_focus_back()129 static void got_focus_back()
130 {
131 textgfx_flags &= ~LOST_FOCUS;
132 kb_flushinp();
133 refresh_needed = 1;
134 refreshscreen();
135 }
136
setgfxmode(int fullscreen)137 static int setgfxmode(int fullscreen)
138 {
139 if (!fullscreen &&
140 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 512, 400, 0, 0) == 0) {
141 term_width = 64;
142 set_display_switch_mode(SWITCH_BACKGROUND);
143 set_display_switch_callback(SWITCH_OUT, lost_focus);
144 return 1;
145 }
146 if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) == 0) {
147 term_width = 80;
148 set_display_switch_mode(SWITCH_PAUSE);
149 return 1;
150 }
151 if (get_color_depth() != 8) {
152 set_color_depth(8);
153 return setgfxmode(fullscreen);
154 }
155 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
156 allegro_message("Unable to set any graphics mode:\n"
157 "%s\n", allegro_error);
158 return 0;
159 }
160
set_screen(int fullscreen)161 BITMAP *set_screen(int fullscreen)
162 {
163 const unsigned char
164 vgargb[16][3] = {
165 0, 0, 0, /* 0 black */
166 170, 0, 0, /* 1 red */
167 0,170, 0, /* 2 green */
168 170, 85, 0, /* 3 yellow */
169 0, 0,170, /* 4 blue */
170 170, 0,170, /* 5 magenta */
171 0,170,170, /* 6 cyan */
172 170,170,170, /* 7 white */
173 85, 85, 85,
174 255, 85, 85,
175 85,255, 85,
176 255,255, 85,
177 85, 85,255,
178 255, 85,255,
179 85,255,255,
180 255,255,255
181 };
182 const unsigned char *rgb;
183 if (!setgfxmode(fullscreen))
184 exit(1);
185 clear_bitmap(screen);
186 if (set_display_switch_callback(SWITCH_IN, got_focus_back) == -1)
187 set_display_switch_mode(SWITCH_PAUSE);
188 BITMAP *bmp = create_bitmap(8 * term_width, 400);
189 clear_bitmap(bmp);
190 set_clip_state(bmp, 0);
191 set_clip_state(screen, 0);
192 int i;
193 for (i=0; i<16; i++) {
194 rgb = &vgargb[i][0];
195 vgacolors[i] = makecol(rgb[0], rgb[1], rgb[2]);
196 }
197 return bmp;
198 }
199
200 #if WIN32 && !ALLEGRO_USE_CONSOLE
printline(char * line)201 static int printline(char *line)
202 {
203 int n = strlen(line);
204 int c = 0;
205 if (line[n-1] == '\n')
206 line[--n] = '\0';
207 if (n > 64 && is_windowed_mode()) {
208 c = line[64];
209 line[64] = '\0';
210 }
211 printstr(line);
212 if (!c || curs_y == 24)
213 return 0;
214 line[64] = c;
215 curs_y++;
216 printstr(line + 64);
217 return 1;
218 }
219 #endif
220
textgfx_init()221 void textgfx_init()
222 {
223 #ifdef UNIX
224 strcpy(_xwin.application_name, "vitetris");
225 strcpy(_xwin.application_class, "Vitetris");
226 #endif
227 if (install_allegro(SYSTEM_AUTODETECT, &errno, NULL) != 0)
228 exit(1);
229 #ifdef UNIX
230 sigaction(SIGINT, NULL, &allegro_sigint_handler);
231 signal(SIGINT, sigint_handler);
232 #endif
233 load_pc8x16_font();
234 set_window_title(VITETRIS_VER);
235 set_close_button_callback(close_btn);
236 #ifndef UNIX
237 /* Seems to cause seg fault later quite randomly on Linux */
238 int depth = desktop_color_depth();
239 if (depth != 0)
240 set_color_depth(depth);
241 #endif
242 virt_screen = set_screen(getopt_int("", "fullscreen"));
243 lang |= LATIN1;
244 if (!font8x16) {
245 font8x16 = font;
246 textgfx_flags |= ASCII;
247 }
248 setattr_normal();
249 #if WIN32 && !ALLEGRO_USE_CONSOLE
250 if (exists("stdout.tmp")) {
251 FILE *fp;
252 freopen("stdout2.tmp", "w", stdout);
253 fp = fopen("stdout.tmp", "r");
254 if (fp) {
255 char line[80];
256 int i;
257 for (i=0; i < 25 && fgets(line, 80, fp); i++) {
258 setcurs(0, i);
259 i += printline(line);
260 }
261 fclose(fp);
262 if (i) {
263 refreshscreen();
264 if (!strncmp(line, "Press ", 6)) {
265 install_keyboard();
266 clear_keybuf();
267 readkey();
268 remove_keyboard();
269 }
270 }
271 }
272 freopen("stdout.tmp", "w", stdout);
273 delete_file("stdout2.tmp");
274 }
275 #endif
276 }
277
textgfx_end()278 void textgfx_end()
279 {
280 if (!virt_screen)
281 return;
282 destroy_bitmap(virt_screen);
283 virt_screen = NULL;
284 if (font8x16 != font)
285 destroy_font(font8x16);
286 allegro_exit();
287 }
288
toggle_fullscreen()289 void toggle_fullscreen()
290 {
291 BITMAP *bmp = set_screen(is_windowed_mode());
292 if (bmp->w == virt_screen->w)
293 destroy_bitmap(bmp);
294 else {
295 if (bmp->w > virt_screen->w) {
296 int h = 400;
297 if (in_menu) {
298 blit(virt_screen, screen, 0, 384, 0, 464,
299 512, 16);
300 h = 384;
301 }
302 blit(virt_screen, bmp, 0, 0, 64, 0, 512, h);
303 curs_x += 8;
304 } else {
305 blit(virt_screen, bmp, 64, 0, 0, 0, 512, 400);
306 curs_x -= 8;
307 }
308 margin_x = getmargin_x();
309 destroy_bitmap(virt_screen);
310 virt_screen = bmp;
311 }
312 refresh_needed = 1;
313 refreshscreen();
314 }
315
setcurs(int x,int y)316 void setcurs(int x, int y)
317 {
318 x += win_x + margin_x;
319 y += win_y;
320 curs_x = x;
321 curs_y = y;
322 }
323
movefwd(int n)324 void movefwd(int n)
325 {
326 curs_x += n;
327 }
328
newln(int x)329 void newln(int x)
330 {
331 x += win_x + margin_x;
332 curs_x = x;
333 curs_y++;
334 }
335
setcurs_end()336 void setcurs_end()
337 {
338 curs_x = 0;
339 curs_y = 24;
340 }
341
is_outside_screen(int x,int y)342 int is_outside_screen(int x, int y)
343 {
344 return x + win_x + margin_x >= term_width ||
345 y + win_y >= 25;
346 }
347
get_xy(int * x,int * y)348 void get_xy(int *x, int *y)
349 {
350 *x = curs_x - win_x - margin_x;
351 *y = curs_y - win_y;
352 }
353
refreshscreen()354 void refreshscreen()
355 {
356 int y = 0;
357 if (!refresh_needed)
358 return;
359 if (!is_windowed_mode())
360 y = 40;
361 acquire_screen();
362 blit(virt_screen, screen, 0, 0, 0, y, 8*term_width, 400);
363 release_screen();
364 refresh_needed = 0;
365 memset(blit_rect, 0, 4);
366 }
367
update_blit_rect(char x,char y,char x2)368 static void update_blit_rect(char x, char y, char x2)
369 {
370 if (x < blit_rect[0] || !blit_rect[0])
371 blit_rect[0] = x;
372 if (y < blit_rect[1] || !blit_rect[1])
373 blit_rect[1] = y;
374 if (x2 > blit_rect[2])
375 blit_rect[2] = x2;
376 if (y > blit_rect[3])
377 blit_rect[3] = y;
378 }
379
cleartoeol()380 void cleartoeol()
381 {
382 int y = 16*curs_y;
383 int maxx = term_width-1;
384 rectfill(virt_screen, 8*curs_x, y, 8*maxx, y+15, 0);
385 refresh_needed = 1;
386 update_blit_rect(curs_x, curs_y, maxx);
387 }
388
set_color_pair(int clr)389 void set_color_pair(int clr)
390 {
391 int bg = 0;
392 int bold = 1;
393 if (_MONOCHROME) {
394 if (clr == MAGENTA_FG)
395 setattr_bold();
396 return;
397 }
398 if (clr & 64) {
399 bg = clr & 7;
400 clr = clr>>3 & 7;
401 } else
402 switch (clr) {
403 case MAGENTA_FG:
404 clr = 5;
405 break;
406 case WHITE_ON_BLUE:
407 clr = 7;
408 bg = 4;
409 break;
410 case BOARD_BG_COLOR:
411 clr = 4;
412 bold = 0;
413 break;
414 case BOARD_FRAME_COLOR:
415 clr = 4;
416 bold = 0;
417 break;
418 case RED_FG:
419 clr = 1;
420 break;
421 case YELLOW_ON_BLUE:
422 clr = 3;
423 bg = 4;
424 break;
425 case YELLOW_ON_GREEN:
426 clr = 3;
427 bg = 2;
428 break;
429 default:
430 if (clr & 16)
431 clr &= 7;
432 else
433 bg = clr;
434 }
435 if (textgfx_flags & BLACK_BRACKETS && bg == clr) {
436 clr = 0;
437 bold = 0;
438 }
439 if (!_TT_BLOCKS)
440 bg_color = bg;
441 if (bold)
442 clr |= 8;
443 fg_color = clr;
444 }
445
setattr_normal()446 void setattr_normal()
447 {
448 bg_color = 0;
449 fg_color = 7;
450 }
451
setattr_standout()452 void setattr_standout()
453 {
454 bg_color = fg_color;
455 fg_color = 0;
456 }
457
setattr_bold()458 void setattr_bold()
459 {
460 if ((textgfx_flags & TT_MONO) != TT_MONO && fg_color < 8)
461 fg_color |= 8;
462 }
463
setattr_underline()464 void setattr_underline() {}
465
to_cp437(int ch)466 static int to_cp437(int ch)
467 {
468 const char *latin1 = "��������";
469 const char *cp437 = "\x8F\x8E\x99\x9A\x86\x84\x94\x82";
470 const char *p;
471 p = strchr(latin1, ch);
472 if (p)
473 return (unsigned char) cp437[p-latin1];
474 return '?';
475 }
476
text_out(const char * s,int n)477 static void text_out(const char *s, int n)
478 {
479 int x = 8 *curs_x;
480 int y = 16*curs_y;
481 int bg = vgacolors[bg_color];
482 int fg = vgacolors[fg_color];
483
484 if (*s == '|' && n == 1) {
485 rectfill(virt_screen, x, y, x+7, y+15, bg);
486 rectfill(virt_screen, x+3, y, x+4, y+12, fg);
487 } else {
488 if (font == font8x16) {
489 rectfill(virt_screen, x, y, x+(8*n)-1, y+15, bg);
490 y += 4;
491 }
492 textout_ex(virt_screen, font8x16, s, x, y, fg, bg);
493 }
494 refresh_needed = 1;
495 update_blit_rect(curs_x, curs_y, curs_x+n-1);
496 curs_x += n;
497 }
498
put_ch(int ch)499 void put_ch(int ch)
500 {
501 char s[2] = "";
502 int trans = 0;
503 if (ch == '\b') {
504 curs_x--;
505 return;
506 }
507 if (ch < 0)
508 ch = (unsigned char) ch;
509 if (ch & 0x80)
510 ch = to_cp437(ch);
511 if (ch == TEXTURE2 && textgfx_flags & (TT_BLOCKS | BLACK_BRACKETS))
512 ch = ' ';
513 if (ch & 0x100) {
514 if (_ASCII) {
515 putch_ascii(ch);
516 return;
517 }
518 ch = (unsigned char) ibmgfx(ch);
519 if (ch < 32)
520 trans = 32;
521 }
522 if (ch == 0xFA)
523 trans = -0x80;
524 else if (ch >= 0x80)
525 trans = -0x60;
526 if (trans) {
527 transpose_font(font8x16, trans);
528 s[0] = ch + trans;
529 text_out(s, 1);
530 transpose_font(font8x16, -trans);
531 } else {
532 s[0] = ch;
533 text_out(s, 1);
534 }
535 }
536
printstr(const char * str)537 int printstr(const char *str)
538 {
539 if (!str[0])
540 return 0;
541 while (str[0] && curs_x < term_width) {
542 putch(str[0]);
543 str++;
544 }
545 return 1;
546 }
547
printint(const char * fmt,int d)548 void printint(const char *fmt, int d)
549 {
550 char buf[80];
551 int n = usprintf(buf, fmt, d);
552 text_out(buf, n);
553 }
554
printlong(const char * fmt,long d)555 void printlong(const char *fmt, long d)
556 {
557 char buf[80];
558 int n = usprintf(buf, fmt, d);
559 text_out(buf, n);
560 }
561
default_bgdot()562 int default_bgdot()
563 {
564 return BULLET;
565 }
566