/* Hello, Emacs, this is -*-C-*- * $Id: atariaes.trm,v 1.19 2006/07/21 02:35:45 sfeam Exp $ * */ /* GNUPLOT - atari.trm */ /*[ * Copyright 1992, 1993, 1998, 2004 * * Permission to use, copy, and distribute this software and its * documentation for any purpose with or without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. * * Permission to modify the software is granted, but not the right to * distribute the complete modified source code. Modifications are to * be distributed as patches to the released version. Permission to * distribute binaries produced by compiling modified sources is granted, * provided you * 1. distribute the corresponding source modifications from the * released version in the form of a patch file along with the binaries, * 2. add special version identification to distinguish your version * in addition to the base release version number, * 3. provide your name and address as the primary contact for the * support of your modified version, and * 4. retain our contact information in regard to use of the base * software. * Permission to distribute the released version of the source code along * with corresponding source modifications in the form of a patch file is * granted with same provisions 2 through 4 for binary distributions. * * This software is provided "as is" without express or implied warranty * to the extent permitted by applicable law. ]*/ /* * This file is included by ../term.c. * * This terminal driver supports: * Atari Screens working with the normal VDI * (this should include TT and big screens) * * AUTHORS * Alexander Lehmann * HE Koechling * * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net). * * ATARI-related comments please to alexlehm@iti.informatik.th-darmstadt.de * */ #include "driver.h" #ifdef TERM_REGISTER register_term(atari) #endif #ifdef TERM_PROTO /* function-prototypes */ TERM_PUBLIC void ATARI_options __PROTO((void)); TERM_PUBLIC void ATARI_init __PROTO((void)); TERM_PUBLIC void ATARI_reset __PROTO((void)); TERM_PUBLIC void ATARI_graphics __PROTO((void)); TERM_PUBLIC void ATARI_text __PROTO((void)); TERM_PUBLIC void ATARI_move __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC void ATARI_vector __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC void ATARI_linetype __PROTO((int lt)); TERM_PUBLIC void ATARI_put_text __PROTO((unsigned int x, unsigned int y, const char *str)); TERM_PUBLIC int ATARI_text_angle __PROTO((int ang)); TERM_PUBLIC int ATARI_justify_text __PROTO((enum JUSTIFY mode)); TERM_PUBLIC void ATARI_point __PROTO((unsigned int x, unsigned int y, int number)); /* default to hi-res */ #define ATARI_XMAX 640 #define ATARI_YMAX 400 #define ATARI_VCHAR 16 #define ATARI_HCHAR 8 #define ATARI_HTIC (ATARI_XMAX/100) #define ATARI_VTIC ATARI_HTIC #endif /* TERM_PROTO */ #ifndef TERM_PROTO_ONLY #ifdef TERM_BODY #ifdef __PUREC__ /* why did they have to change these names ??? */ # include # include # include #else /* !__PUREC__ i.e. __GNUC__, maybe others */ # include # include # include extern short _global[]; #endif #include static void open_window __PROTO((void)); static void close_window __PROTO((void)); static void text_mode __PROTO((void)); static void mouse_mode __PROTO((void)); static void application_exit __PROTO((void)); void application_init __PROTO((void)); static int intersect __PROTO((int *x1, int *y1, int *w1, int *h1, int x2, int y2, int w2, int h2)); static void walk_rects __PROTO((void (*draw) (int, int, int, int), int x1, int y1, int w1, int h1)); static void clear __PROTO((int x, int y, int w, int h)); static void process_message __PROTO((int *msg)); long poll_events __PROTO((int waitkey)); static void f_line __PROTO((int x, int y, int w, int h)); static void flush_line __PROTO((void)); static void put_text __PROTO((int x, int y, int w, int h)); static int multi_aes; static int window_id = -1; static int vdi_handle = -1; static int win_xpos, win_ypos; static int win_xsize, win_ysize; #define ATARI_yc(y) (ATARI_maxycoord-(y)) static int ATARI_linetypes[] = { 0xffff, 0x1111, 0xffff, 0x5555, 0x3333, 0x7777, 0x3f3f, 0x0f0f, 0x5f5f, 0xe4e4, 0x55f5 }; #define ATARI_LINETYPES_MAX (sizeof(ATARI_linetypes)/sizeof(int)) static int ATARI_lt; static int ATARI_maxycoord; static int ATARI_rotation; static int ATARI_numcolors; static int pxy[128]; /* Maximum of 64 pixels per v_pline */ static int pxy_index; static int ATARI_colors[16]; static int ATARI_savecolors[16][3]; static int ATARI_numpalette; #define ATARI_c_height_default 6 /* well, well ... */ static int ATARI_c_height = ATARI_c_height_default; static int cursor_is_on = FALSE; static int put_text_x; static int put_text_y; static char *put_text_str; /* don't change this without changing process_message() below */ #define WINTYPE (NAME|CLOSER|FULLER|MOVER|SIZER) static void open_window() { int x, y, w, h; if (window_id == -1) { wind_calc(WC_BORDER, WINTYPE, win_xpos, win_ypos, win_xsize, win_ysize, &x, &y, &w, &h); window_id = wind_create(WINTYPE, x, y, w, h); if (window_id < 0) { window_id = -1; int_error(NO_CARET, "Can't create window"); } wind_set(window_id, WF_NAME, "gnuplot output"); wind_open(window_id, x, y, w, h); } } static void close_window() { if (window_id != -1) { wind_close(window_id); wind_delete(window_id); window_id = -1; } } static void text_mode() { if (!multi_aes) { if (!cursor_is_on) { cursor_is_on = TRUE; graf_mouse(M_OFF, NULL); fputs("\033e", stderr); } fputs("\033E", stderr); } } static void mouse_mode() { if (!multi_aes) { if (cursor_is_on) { cursor_is_on = FALSE; graf_mouse(M_ON, NULL); fputs("\033f", stderr); } } } static void application_exit() { close_window(); if (vdi_handle != -1) { v_clsvwk(vdi_handle); } mouse_mode(); } void application_init() { if (aesid < 0) { if ((aesid = appl_init()) < 0) int_error(NO_CARET, "APPL_INIT failed !"); } #ifdef __PUREC__ multi_aes = _GemParBlk.global[1] == -1; #else /* tested with gcc only */ multi_aes = _global[1] == -1; #endif if (!multi_aes) graf_mouse(ARROW, NULL); else menu_register(aesid, " Terminal: atari"); text_mode(); atexit(application_exit); } static int intersect(int *x1, int *y1, int *w1, int *h1, int x2, int y2, int w2, int h2) { if (*x1 > x2) { w2 -= *x1 - x2; x2 = *x1; } else { (*w1) -= x2 - *x1; *x1 = x2; } if (*y1 > y2) { h2 -= *y1 - y2; y2 = *y1; } else { (*h1) -= y2 - *y1; *y1 = y2; } if (*w1 > w2) { *w1 = w2; } else { w2 = *w1; } if (*h1 > h2) { *h1 = h2; } else { h2 = *h1; } return (*w1) > 0 && (*h1) > 0; } static void walk_rects(void (*draw) (int, int, int, int), int x1, int y1, int w1, int h1) { int x, y, w, h; int pxy[4]; wind_update(BEG_UPDATE); graf_mouse(M_OFF, NULL); wind_get(window_id, WF_FIRSTXYWH, &x, &y, &w, &h); while (w > 0 && h > 0) { if (intersect(&x, &y, &w, &h, x1, y1, w1, h1)) { pxy[0] = x; pxy[1] = y; pxy[2] = x + w - 1; pxy[3] = y + h - 1; vs_clip(vdi_handle, 1, pxy); (*draw) (x, y, w, h); } wind_get(window_id, WF_NEXTXYWH, &x, &y, &w, &h); } vs_clip(vdi_handle, 0, pxy); graf_mouse(M_ON, NULL); wind_update(END_UPDATE); } static void clear(int x, int y, int w, int h) { static MFDB mfdb = { NULL }; int pxy[8]; pxy[0] = pxy[4] = x; pxy[1] = pxy[5] = y; pxy[2] = pxy[6] = x + w - 1; pxy[3] = pxy[7] = y + h - 1; vro_cpyfm(vdi_handle, ALL_WHITE /*0 */ , pxy, &mfdb, &mfdb); } static void process_message(int *msg) { static int is_fulled = FALSE; static int small_xpos, small_ypos, small_xsize, small_ysize; int x, y, w, h; if (window_id == -1 || msg[3] != window_id) return; switch (msg[0]) { case WM_REDRAW: walk_rects(clear, msg[4], msg[5], msg[6], msg[7]); break; case WM_CLOSED: close_window(); break; case WM_TOPPED: wind_set(window_id, WF_TOP, window_id); break; case WM_MOVED: case WM_SIZED: is_fulled = 0; wind_calc(WC_WORK, WINTYPE, msg[4], msg[5], msg[6], msg[7], &win_xpos, &win_ypos, &win_xsize, &win_ysize); wind_set(window_id, WF_CURRXYWH, msg[4], msg[5], msg[6], msg[7]); break; case WM_FULLED: if (!is_fulled) { is_fulled = TRUE; small_xpos = win_xpos; small_ypos = win_ypos; small_xsize = win_xsize; small_ysize = win_ysize; wind_get(0, WF_WORKXYWH, &x, &y, &w, &h); wind_calc(WC_WORK, WINTYPE, x, y, w, h, &win_xpos, &win_ypos, &win_xsize, &win_ysize); } else { is_fulled = FALSE; win_xpos = small_xpos; win_ypos = small_ypos; win_xsize = small_xsize; win_ysize = small_ysize; } wind_calc(WC_BORDER, WINTYPE, win_xpos, win_ypos, win_xsize, win_ysize, &x, &y, &w, &h); wind_set(window_id, WF_CURRXYWH, x, y, w, h); break; } } long poll_events(int waitkey) { int msg[8]; int dummy; int which; int key = 0; /* 1/10th second when waiting for key, poll otherwise */ unsigned long time = (waitkey ? 100L : 1L); do { which = evnt_multi( (waitkey ? (MU_MESAG | MU_KEYBD | MU_TIMER) : (MU_MESAG | MU_TIMER)), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, msg, #ifdef __PUREC__ time, 0, #else time, #endif &dummy, &dummy, &dummy, &dummy, &key, &dummy); if (which & MU_MESAG) { process_message(msg); } } while (which & MU_MESAG); if (which & MU_KEYBD) { return ((Kbshift(-1) & 7) << 24) | ((long) (key & 0xff00) << 8) | (key & 0xff); } else { return 0; } } static void f_line(int x, int y, int w, int h) { v_pline(vdi_handle, pxy_index, pxy); } static void flush_line() { int line_type; int color_index; int i; if (pxy_index >= 2) { if (ATARI_numcolors == 2) { /* Monochrome */ color_index = 1; line_type = ATARI_lt; if (line_type >= 0) line_type %= (ATARI_LINETYPES_MAX - 2); } else { /* Color */ if (ATARI_lt < 0) { color_index = 1; line_type = ATARI_lt; } else { color_index = 2 + ATARI_lt % (ATARI_numcolors - 2); line_type = (ATARI_lt / (ATARI_numcolors - 2)) % (ATARI_LINETYPES_MAX - 2); } } vswr_mode(vdi_handle, MD_TRANS); vsl_color(vdi_handle, color_index); vsl_type(vdi_handle, 7); vsl_udsty(vdi_handle, ATARI_linetypes[line_type + 2]); walk_rects(f_line, win_xpos, win_ypos, win_xsize, win_ysize); } if (pxy_index >= 1) { pxy[0] = pxy[2 * (pxy_index - 1)]; pxy[1] = pxy[2 * (pxy_index - 1) + 1]; pxy_index = 1; } } static void put_text(int x, int y, int w, int h) { v_gtext(vdi_handle, put_text_x, put_text_y, put_text_str); } TERM_PUBLIC void ATARI_options() { #define ATARIHEXERROR "palette values 3 hex digits, please" #define ATARIHEIGHTERROR "expecting a character height" char opt[6]; /* maximum: 'fff'\0 */ int i; char *tok_end; term_options[0] = NUL; ATARI_c_height = ATARI_c_height_default; for (i = 0; i < 17; i++) { if (END_OF_COMMAND) break; if (token[c_token].length > 5) { ATARI_numpalette = 0; ATARI_c_height = ATARI_c_height_default; term_options[0] = NUL; int_error(c_token, ATARIHEXERROR); } capture(opt, c_token, c_token, 6); if (!i) { ATARI_c_height = strtoul(opt, &tok_end, 10); if (*tok_end != NUL) { ATARI_numpalette = 0; ATARI_c_height = ATARI_c_height_default; term_options[0] = NUL; int_error(c_token, ATARIHEIGHTERROR); } if (ATARI_c_height > 999) ATARI_c_height = 999; /* avoid opt length overflow */ sprintf(opt, "%d ", ATARI_c_height); } else { if (*opt == '"' || *opt == '\'') { opt[strlen(opt) - 1] = NUL; strcpy(opt, opt + 1); } ATARI_colors[i - 1] = strtoul(opt, &tok_end, 16); if (*tok_end != NUL) { ATARI_numpalette = 0; ATARI_c_height = ATARI_c_height_default; term_options[0] = NUL; int_error(c_token, ATARIHEXERROR); } sprintf(opt, "%X ", ATARI_colors[i - 1]); /* do we need to quote? */ if (isdigit((unsigned char) *opt) && strpbrk(opt, "ABCDEF")) { sprintf(opt, "\"%X\" ", ATARI_colors[i - 1]); } } strcat(term_options, opt); c_token++; } ATARI_numpalette = (i == 0 ? 0 : i - 1); /* printf("Number of linetypes:%d\n", ATARI_LINETYPES_MAX); */ } TERM_PUBLIC void ATARI_init() { int work_in[11]; int work_out[57]; int i; int hchar, wchar, dummy; int rgb[3]; int num_save; char *colors, *tok_end; int x, y, w, h; static int have_win_size = 0; application_init(); if (ATARI_numpalette == 0 && (colors = getenv("GNUCOLORS")) && *colors) { for (i = 0; i < 17; i++) { if (!i) { ATARI_c_height = strtoul(colors, &tok_end, 10); if (colors == tok_end) { i = 0; ATARI_c_height = ATARI_c_height_default; break; } } else { if (*colors == '\0') break; ATARI_colors[i] = strtoul(colors, &tok_end, 16); if (colors == tok_end || (unsigned) ATARI_colors[i] > 0xfff) { i = 0; break; } } colors = tok_end; while (*colors == ' ') colors++; } ATARI_numpalette = (i == 0 ? 0 : i - 1); } vdi_handle = graf_handle(&dummy, &dummy, &dummy, &dummy); if (!vdi_handle) int_error(NO_CARET, "Fatal error opening virtual workstation"); for (i = 0; i < 10; work_in[i++] = 1); work_in[10] = 2; /* use raster coordinates */ v_opnvwk(work_in, &vdi_handle, work_out); if (!vdi_handle) int_error(NO_CARET, "Fatal error opening virtual workstation"); if (!have_win_size) { wind_get(0, WF_WORKXYWH, &x, &y, &w, &h); wind_calc(WC_WORK, WINTYPE, x, y, w, h, &win_xpos, &win_ypos, &win_xsize, &win_ysize); have_win_size = 1; } term->xmax = win_xsize; term->ymax = win_ysize; vst_height(vdi_handle, ATARI_c_height, &dummy, &dummy, &wchar, &hchar); term->h_char = wchar; term->v_char = hchar; /* hchar stands for height this time */ term->h_tic = win_xsize / 100; term->v_tic = term->h_tic; ATARI_maxycoord = win_ysize - 1; ATARI_numcolors = work_out[13]; for (i = 0; i < ATARI_numpalette; i++) { vq_color(vdi_handle, i, 1, ATARI_savecolors[i]); rgb[0] = 1000 * (ATARI_colors[i] >> 8); rgb[0] /= 15; rgb[1] = 1000 * ((ATARI_colors[i] >> 4) & 15); rgb[1] /= 15; rgb[2] = 1000 * (ATARI_colors[i] & 15); rgb[2] /= 15; vs_color(vdi_handle, i, rgb); } pxy_index = 0; } TERM_PUBLIC void ATARI_reset() { int i; close_window(); if (vdi_handle != -1) { for (i = 0; i < ATARI_numpalette; i++) { vs_color(vdi_handle, i, ATARI_savecolors[i]); } v_clsvwk(vdi_handle); vdi_handle = -1; } } TERM_PUBLIC void ATARI_graphics() { ATARI_maxycoord = win_ysize - 1; term->xmax = win_xsize; term->ymax = win_ysize; mouse_mode(); open_window(); poll_events(0); walk_rects(clear, win_xpos, win_ypos, win_xsize, win_ysize); pxy_index = 0; } TERM_PUBLIC void ATARI_text() { flush_line(); if (!multi_aes) { while (window_id != -1 && !poll_events(1)); close_window(); } text_mode(); } TERM_PUBLIC void ATARI_move(unsigned int x, unsigned int y) { flush_line(); pxy[0] = x + win_xpos; pxy[1] = ATARI_yc(y) + win_ypos; pxy_index = 1; } TERM_PUBLIC void ATARI_vector(unsigned int x, unsigned int y) { pxy[2 * pxy_index] = x + win_xpos; pxy[2 * pxy_index + 1] = ATARI_yc(y) + win_ypos; pxy_index++; if (pxy_index == 64) { /* we're all full */ flush_line(); } } TERM_PUBLIC void ATARI_linetype(int lt) { flush_line(); ATARI_lt = lt; } TERM_PUBLIC void ATARI_put_text(unsigned int x, unsigned int y, const char *str) { int vchar = term->v_char; int dummy; if (!strlen(str)) return; if (x < 0) x = 0; if (y < 0) y = 0; /* align text left and to middle of char height */ vst_alignment(vdi_handle, 0, 5, &dummy, &dummy); vst_rotation(vdi_handle, (ATARI_rotation ? 900 : 0)); if (ATARI_rotation) { put_text_x = x - vchar / 2 + 1 + win_xpos; put_text_y = ATARI_yc(y) - 1 + win_ypos; put_text_str = str; } else { put_text_x = x + 1 + win_xpos; put_text_y = ATARI_yc(y) - vchar / 2 + 1 + win_ypos; put_text_str = str; } walk_rects(put_text, win_xpos, win_ypos, win_xsize, win_ysize); } TERM_PUBLIC int ATARI_text_angle(int ang) { ATARI_rotation = ang; return TRUE; } TERM_PUBLIC int ATARI_justify_text(enum JUSTIFY mode) { return FALSE; } TERM_PUBLIC void ATARI_point(unsigned int x, unsigned int y, int number) { int old_linetype; if (ATARI_numcolors == 2) { line_and_point(x, y, number); /* monochrome */ } else { /* we map colors that exceed our limit to dotted lines, but we can't do that with the markers (sortof a generalized line_and_point) */ old_linetype = ATARI_lt; if (ATARI_lt > ATARI_numcolors - 2) ATARI_linetype(ATARI_lt % (ATARI_numcolors - 2)); /* same color, but no dots */ do_point(x, y, number); ATARI_linetype(old_linetype); } } #endif /* TERM_BODY */ #ifdef TERM_TABLE TERM_TABLE_START(atari_driver) "atari", "Atari AES-Terminal", ATARI_XMAX, ATARI_YMAX, ATARI_VCHAR, ATARI_HCHAR, ATARI_VTIC, ATARI_HTIC, ATARI_options, ATARI_init, ATARI_reset, ATARI_text, null_scale, ATARI_graphics, ATARI_move, ATARI_vector, ATARI_linetype, ATARI_put_text, ATARI_text_angle, ATARI_justify_text, ATARI_point, do_arrow, set_font_null, 0, TERM_CAN_MULTIPLOT, 0, 0 TERM_TABLE_END(atari_driver) #undef LAST_TERM #define LAST_TERM atari_driver #endif /* TERM_TABLE */ #endif /* TERM_PROTO_ONLY */ #ifdef TERM_HELP START_HELP(atari) "1 atari ST (via AES)", "?commands set terminal atari", "?set terminal atari", "?set term atari", "?terminal atari", "?term atari", "?atari", " The `atari` terminal has options to set the character size and the screen", " colors.", "", " Syntax:", " set terminal atari {} { ... }", "", " The character size must appear if any colors are to be specified. Each of", " the (up to 16) colors is given as a three-digit hex number, where the digits", " represent RED, GREEN and BLUE (in that order). The range of 0--15 is scaled", " to whatever color range the screen actually has. On a normal ST screen, odd", " and even intensities are the same.", "", " Examples:", " set terminal atari 4 # use small (6x6) font", " set terminal atari 6 0 # set monochrome screen to white on black", " set terminal atari 13 0 fff f00 f0 f ff f0f", " # set first seven colors to black, white, red, green,", " # blue, cyan, and purple and use large font (8x16).", "", " Additionally, if an environment variable GNUCOLORS exists, its contents are", " interpreted as an options string, but an explicit terminal option takes", " precedence." END_HELP(atari) #endif /* TERM_HELP */