Initial release of Maemo 5 port of gnuplot
[gnuplot] / term / vgagl.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: vgagl.trm,v 1.20 2006/07/21 02:35:48 sfeam Exp $
3  */
4
5 #if defined(USE_MOUSE)
6 /* GNUPLOT - vgagl.trm */
7
8 /*[
9  * Copyright 1993, 1998, 2004
10  *
11  * Permission to use, copy, and distribute this software and its
12  * documentation for any purpose with or without fee is hereby granted,
13  * provided that the above copyright notice appear in all copies and
14  * that both that copyright notice and this permission notice appear
15  * in supporting documentation.
16  *
17  * Permission to modify the software is granted, but not the right to
18  * distribute the complete modified source code.  Modifications are to
19  * be distributed as patches to the released version.  Permission to
20  * distribute binaries produced by compiling modified sources is granted,
21  * provided you
22  *   1. distribute the corresponding source modifications from the
23  *    released version in the form of a patch file along with the binaries,
24  *   2. add special version identification to distinguish your version
25  *    in addition to the base release version number,
26  *   3. provide your name and address as the primary contact for the
27  *    support of your modified version, and
28  *   4. retain our contact information in regard to use of the base
29  *    software.
30  * Permission to distribute the released version of the source code along
31  * with corresponding source modifications in the form of a patch file is
32  * granted with same provisions 2 through 4 for binary distributions.
33  *
34  * This software is provided "as is" without express or implied warranty
35  * to the extent permitted by applicable law.
36  ]*/
37
38 /*
39  * This file is included by ../term.c.
40  *
41  * This terminal driver supports SVGA in the following modes:
42  *
43  *  G1024x768x256,
44  *  G800x600x256,
45  *  G640x480x256,
46  *  G320x200x256,
47  *  G1280x1024x256,
48  *  G1152x864x256,
49  *  G1360x768x256,
50  *  G1600x1200x256,
51  *
52  *
53  * AUTHOR
54  *  Johannes Zellner <johannes@zellner.org>
55  *  the code is based on the `linux' driver.
56  *  The first version dated January 2000.
57  */
58
59 /*
60  * Compile with -l3kit -lvgagl -lvga
61  */
62
63 #define VGAGL_DEBUGGING
64
65 #ifdef TERM_REGISTER
66 register_term(vgagl)
67 #endif
68
69 #ifdef TERM_PROTO
70
71 #define VGAGL_VCHAR FNT5X9_VCHAR
72 #define VGAGL_HCHAR FNT5X9_HCHAR
73 #define VGAGL_VTIC 5
74 #define VGAGL_HTIC 5
75 #define VGAGL_XMAX 0            /* These two entries are just place holders. */
76 #define VGAGL_YMAX 0            /* The actual values will be filled in init. */
77
78 TERM_PUBLIC void VGAGL_options __PROTO((void));
79 TERM_PUBLIC int VGAGL_get_mode __PROTO((void));
80 TERM_PUBLIC void VGAGL_init __PROTO((void));
81 TERM_PUBLIC void VGAGL_reset __PROTO((void));
82 TERM_PUBLIC void VGAGL_text __PROTO((void));
83 TERM_PUBLIC void VGAGL_graphics __PROTO((void));
84 TERM_PUBLIC void VGAGL_linetype __PROTO((int linetype));
85 TERM_PUBLIC void VGAGL_move __PROTO((unsigned int x, unsigned int y));
86 TERM_PUBLIC void VGAGL_vector __PROTO((unsigned int x, unsigned int y));
87 TERM_PUBLIC int VGAGL_text_angle __PROTO((int ang));
88 TERM_PUBLIC void VGAGL_put_text_with_color __PROTO((unsigned int x, unsigned int y, const char* str, int color));
89 TERM_PUBLIC void VGAGL_put_text __PROTO((unsigned int x, unsigned int y, const char* str));
90 TERM_PUBLIC void VGAGL_suspend __PROTO((void));
91 TERM_PUBLIC void VGAGL_resume __PROTO((void));
92
93
94 void VGAGL_eventually_process_graphics_events __PROTO((void));
95 TERM_PUBLIC void VGAGL_draw_cursor __PROTO((int x, int y));
96 TERM_PUBLIC void VGAGL_set_ruler __PROTO((int, int));
97 TERM_PUBLIC void VGAGL_set_cursor __PROTO((int, int, int));
98 TERM_PUBLIC void VGAGL_put_tmptext __PROTO((int, const char str[]));
99 TERM_PUBLIC void VGAGL_set_clipboard __PROTO((const char[]));
100 TERM_PUBLIC void VGAGL_init_keytable __PROTO((void));
101 TERM_PUBLIC void VGAGL_xor_pixel __PROTO((int x, int y));
102 TERM_PUBLIC void VGAGL_xor_pixel_wrapper __PROTO((int x, int y, int color));
103 TERM_PUBLIC void VGAGL_hline_xor __PROTO((int x1, int x2, int y));
104 TERM_PUBLIC void VGAGL_vline_xor __PROTO((int y1, int y2, int x));
105 #if 0
106 TERM_PUBLIC void VGAGL_line_xor __PROTO((unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2));
107 #endif
108 TERM_PUBLIC void VGAGL_zoombox __PROTO((int x, int y));
109 TERM_PUBLIC void VGAGL_update_zoombox __PROTO((int x, int y));
110 TERM_PUBLIC void VGAGL_update_cursor __PROTO((int x, int y));
111 TERM_PUBLIC void VGAGL_signal_handler __PROTO((int signum));
112 TERM_PUBLIC void VGAGL_setpalettecolor __PROTO((int index, double red, double green, double blue));
113 TERM_PUBLIC void VGAGL_set_black_and_white __PROTO((void));
114 TERM_PUBLIC void VGAGL_set_line_colors __PROTO((void));
115 TERM_PUBLIC void VGAGL_putc __PROTO((unsigned int x, unsigned int y, int c, int ang, int color));
116 void (*VGAGL_old_handler) __PROTO((int));
117 #ifdef VGAGL_DEBUGGING
118 TERM_PUBLIC void VGAGL_write_dump_file __PROTO((void));
119 #endif
120
121 TERM_PUBLIC int VGAGL_make_palette __PROTO((t_sm_palette*));
122 TERM_PUBLIC void VGAGL_set_color __PROTO((t_colorspec *));
123 TERM_PUBLIC void VGAGL_filled_polygon __PROTO((int, gpiPoint*));
124
125 static const int VGAGL_8bit_colors = 240;
126 static const int pm3d_color_offset = 16; /* 0xff - VGAGL_8bit_colors + 1 */
127
128 static int VGAGL_pm3d_colors;
129 static int VGAGL_pm3d_colors_; /* VGAGL_pm3d_colors - 1 */
130 static t_sm_palette VGAGL_save_pal = {
131     -1, -1, -1, -1, -1, -1, -1, -1,
132     (rgb_color*) 0, -1, -1
133 };
134 static double VGAGL_gray = 0;
135
136 #ifdef VGAGL_ENABLE_TRUECOLOR
137 #define VGAGL_tri_colors 4096
138 static TBOOLEAN VGAGL_truecolor = FALSE;
139 static unsigned short VGAGL_line_cmap[0xf];
140 static unsigned short VGAGL_cmap[VGAGL_tri_colors];
141 #endif
142
143 #ifdef VGAGL_DEBUGGING
144 static char* VGAGL_dump_file = (char*) 0;
145 static unsigned char VGAGL_palette[0x100][3];
146 #endif
147
148 #endif /* TERM_PROTO */
149
150 #ifdef TERM_BODY
151
152 #include <signal.h>
153
154 #define _STRING_H_
155 /* according to the vga_waitevent() man page */
156 #include <sys/time.h>
157 #include <sys/types.h>
158 #include <unistd.h>
159 #include <vga.h>
160 #include <vgagl.h>
161 #include <3dkit.h>
162 #include <vgamouse.h>
163 #include <vgakeyboard.h>
164
165 #define VGA_FPRINTF(x) fprintf x
166 #define Y(y) (vgagl_lasty - y)
167
168 static TBOOLEAN VGAGL_processing_graphics_events = FALSE;
169 static TBOOLEAN VGAGL_interpolate = TRUE;
170 static GraphicsContext backscreen;
171 static GraphicsContext physicalscreen;
172 static int current_color = 7;
173 #ifdef SCANCODE_RIGHTWIN
174 #   define KEYTABLE_SIZE (SCANCODE_RIGHTWIN + 1)
175 #else
176 #   define KEYTABLE_SIZE (128) /* should be sufficient (joze) */
177 #endif
178 static int VGAGL_Keytable[KEYTABLE_SIZE];
179 static int VGAGL_modifier_mask = 0;
180 static int VGAGL_last_cursorx = -1;
181 static int VGAGL_last_cursory = -1;
182 static int VGAGL_cursorx;
183 static int VGAGL_cursory;
184 static int VGAGL_ruler_x = -1;
185 static int VGAGL_ruler_y = -1;
186 typedef struct VGAGL_zoom_t {
187     int startx;
188     int starty;
189     int currentx;
190     int currenty;
191     char xstr[2][0xff];
192     char ystr[2][0xff];
193     char current_xstr[2][0xff];
194     char current_ystr[2][0xff];
195 } VGAGL_zoom_t;
196 static VGAGL_zoom_t VGAGL_zoom = {
197     -1, -1, -1, -1,
198     { "", "" },
199     { "", "" },
200     { "", "" },
201     { "", "" }
202 };
203 static TBOOLEAN VGAGL_cursor_drawn = FALSE;
204 static unsigned char VGAGL_bg_red = 0x0;
205 static unsigned char VGAGL_bg_green = 0x0;
206 static unsigned char VGAGL_bg_blue = 0x0;
207 static unsigned char VGAGL_xor_red = 0xff;
208 static unsigned char VGAGL_xor_green = 0xff;
209 static unsigned char VGAGL_xor_blue = 0xff;
210 static TBOOLEAN VGAGL_need_update = TRUE;
211 static char VGAGL_savedstr[0xff] = "";
212
213 static int vgagl_vmode = -1; /* default mode */
214 static TBOOLEAN VGAGL_graphics_on = FALSE;
215 static vga_modeinfo *modeinfo;
216 static int VGAGL_startx, VGAGL_starty, vgagl_lasty, vgagl_lastx;
217 static int VGAGL_angle = 0;
218
219
220 void
221 VGAGL_init_keytable()
222 {
223     int i;
224     for (i = 0; i < KEYTABLE_SIZE; i++) {
225         VGAGL_Keytable[i] = -1;
226     }
227     VGAGL_Keytable[SCANCODE_1] = '1';
228     VGAGL_Keytable[SCANCODE_2] = '2';
229     VGAGL_Keytable[SCANCODE_3] = '3';
230     VGAGL_Keytable[SCANCODE_4] = '4';
231     VGAGL_Keytable[SCANCODE_5] = '5';
232     VGAGL_Keytable[SCANCODE_6] = '6';
233     VGAGL_Keytable[SCANCODE_7] = '7';
234     VGAGL_Keytable[SCANCODE_8] = '8';
235     VGAGL_Keytable[SCANCODE_9] = '9';
236     VGAGL_Keytable[SCANCODE_0] = '0';
237
238     VGAGL_Keytable[SCANCODE_A] = 'a';
239     VGAGL_Keytable[SCANCODE_B] = 'b';
240     VGAGL_Keytable[SCANCODE_C] = 'c';
241     VGAGL_Keytable[SCANCODE_D] = 'd';
242     VGAGL_Keytable[SCANCODE_E] = 'e';
243     VGAGL_Keytable[SCANCODE_F] = 'f';
244     VGAGL_Keytable[SCANCODE_G] = 'g';
245     VGAGL_Keytable[SCANCODE_H] = 'h';
246     VGAGL_Keytable[SCANCODE_I] = 'i';
247     VGAGL_Keytable[SCANCODE_J] = 'j';
248     VGAGL_Keytable[SCANCODE_K] = 'k';
249     VGAGL_Keytable[SCANCODE_L] = 'l';
250     VGAGL_Keytable[SCANCODE_M] = 'm';
251     VGAGL_Keytable[SCANCODE_N] = 'n';
252     VGAGL_Keytable[SCANCODE_O] = 'o';
253     VGAGL_Keytable[SCANCODE_P] = 'p';
254     VGAGL_Keytable[SCANCODE_Q] = 'q';
255     VGAGL_Keytable[SCANCODE_R] = 'r';
256     VGAGL_Keytable[SCANCODE_S] = 's';
257     VGAGL_Keytable[SCANCODE_T] = 't';
258     VGAGL_Keytable[SCANCODE_U] = 'u';
259     VGAGL_Keytable[SCANCODE_V] = 'v';
260     VGAGL_Keytable[SCANCODE_W] = 'w';
261     VGAGL_Keytable[SCANCODE_X] = 'x';
262     VGAGL_Keytable[SCANCODE_Y] = 'y';
263     VGAGL_Keytable[SCANCODE_Z] = 'z';
264
265     VGAGL_Keytable[SCANCODE_BRACKET_LEFT] = '[';
266     VGAGL_Keytable[SCANCODE_BRACKET_RIGHT] = ']';
267     VGAGL_Keytable[SCANCODE_MINUS] = '-';
268     VGAGL_Keytable[SCANCODE_EQUAL] = '=';
269     VGAGL_Keytable[SCANCODE_SEMICOLON] = ';';
270     VGAGL_Keytable[SCANCODE_APOSTROPHE] = '\'';
271     VGAGL_Keytable[SCANCODE_GRAVE] = '^';
272     VGAGL_Keytable[SCANCODE_BACKSLASH] = '\\';
273     VGAGL_Keytable[SCANCODE_COMMA] = ',';
274     VGAGL_Keytable[SCANCODE_PERIOD] = '.';
275     VGAGL_Keytable[SCANCODE_SLASH] = '/';
276     VGAGL_Keytable[SCANCODE_SPACE] = ' ';
277
278     VGAGL_Keytable[SCANCODE_BACKSPACE] = GP_BackSpace;
279     VGAGL_Keytable[SCANCODE_TAB] = GP_Tab;
280     VGAGL_Keytable[SCANCODE_ENTER] = GP_Return;
281     VGAGL_Keytable[SCANCODE_ESCAPE] = GP_Escape;
282
283     /* VGAGL_Keytable[SCANCODE_LEFTCONTROL] */
284     /* VGAGL_Keytable[SCANCODE_RIGHTCONTROL] */
285     /* VGAGL_Keytable[SCANCODE_CONTROL] */
286     /* VGAGL_Keytable[SCANCODE_LEFTSHIFT] */
287     /* VGAGL_Keytable[SCANCODE_RIGHTSHIFT] */
288     /* VGAGL_Keytable[SCANCODE_LEFTALT] */
289     /* VGAGL_Keytable[SCANCODE_RIGHTALT] */
290     /* VGAGL_Keytable[SCANCODE_CAPSLOCK] */
291
292     VGAGL_Keytable[SCANCODE_NUMLOCK] = GP_Scroll_Lock;
293     /* VGAGL_Keytable[SCANCODE_SCROLLLOCK] = GP_Numlock; */
294
295     VGAGL_Keytable[SCANCODE_KEYPADMULTIPLY] = GP_KP_Multiply;
296
297     VGAGL_Keytable[SCANCODE_F1] = GP_F1;
298     VGAGL_Keytable[SCANCODE_F2] = GP_F2;
299     VGAGL_Keytable[SCANCODE_F3] = GP_F3;
300     VGAGL_Keytable[SCANCODE_F4] = GP_F4;
301     VGAGL_Keytable[SCANCODE_F5] = GP_F5;
302     VGAGL_Keytable[SCANCODE_F6] = GP_F6;
303     VGAGL_Keytable[SCANCODE_F7] = GP_F7;
304     VGAGL_Keytable[SCANCODE_F8] = GP_F8;
305     VGAGL_Keytable[SCANCODE_F9] = GP_F9;
306     VGAGL_Keytable[SCANCODE_F10] = GP_F10;
307     VGAGL_Keytable[SCANCODE_F11] = GP_F11;
308     VGAGL_Keytable[SCANCODE_F12] = GP_F12;
309
310     VGAGL_Keytable[SCANCODE_KEYPAD0] = GP_KP_0;
311     VGAGL_Keytable[SCANCODE_KEYPAD1] = GP_KP_1;
312     VGAGL_Keytable[SCANCODE_KEYPAD2] = GP_KP_2;
313     VGAGL_Keytable[SCANCODE_KEYPAD3] = GP_KP_3;
314     VGAGL_Keytable[SCANCODE_KEYPAD4] = GP_KP_4;
315     VGAGL_Keytable[SCANCODE_KEYPAD5] = GP_KP_5;
316     VGAGL_Keytable[SCANCODE_KEYPAD6] = GP_KP_6;
317     VGAGL_Keytable[SCANCODE_KEYPAD7] = GP_KP_7;
318     VGAGL_Keytable[SCANCODE_KEYPAD8] = GP_KP_8;
319     VGAGL_Keytable[SCANCODE_KEYPAD9] = GP_KP_9;
320
321     /* KEYPAD */
322     VGAGL_Keytable[SCANCODE_KEYPADMINUS] = GP_KP_Subtract;
323     VGAGL_Keytable[SCANCODE_KEYPADPLUS] = GP_KP_Add;
324     VGAGL_Keytable[SCANCODE_KEYPADPERIOD] = GP_KP_Delete;
325     VGAGL_Keytable[SCANCODE_KEYPADENTER] = GP_KP_Enter;
326     VGAGL_Keytable[SCANCODE_KEYPADDIVIDE] = GP_KP_Divide;
327
328     VGAGL_Keytable[SCANCODE_CURSORUPLEFT] = GP_KP_Home;
329     VGAGL_Keytable[SCANCODE_CURSORUP] = GP_KP_Up;
330     VGAGL_Keytable[SCANCODE_CURSORUPRIGHT] = GP_KP_Page_Up;
331     VGAGL_Keytable[SCANCODE_CURSORLEFT] = GP_KP_Left;
332     VGAGL_Keytable[SCANCODE_CURSORRIGHT] = GP_KP_Right;
333     VGAGL_Keytable[SCANCODE_CURSORDOWNLEFT] = GP_KP_End;
334     VGAGL_Keytable[SCANCODE_CURSORDOWN] = GP_KP_Down;
335     VGAGL_Keytable[SCANCODE_CURSORDOWNRIGHT] = GP_KP_Page_Down;
336
337     VGAGL_Keytable[SCANCODE_LESS] = GP_KP_Begin;
338
339 #if 0
340     VGAGL_Keytable[SCANCODE_PRINTSCREEN] = GP_Begin;
341     VGAGL_Keytable[SCANCODE_BREAK] = GP_Begin;
342     VGAGL_Keytable[SCANCODE_BREAK_ALTERNATIVE] = GP_Begin;
343 #endif
344
345     /* 3 * 2 block (usually above arrow keys) */
346     VGAGL_Keytable[SCANCODE_INSERT] = GP_Insert;
347     VGAGL_Keytable[SCANCODE_HOME] = GP_Home;
348     VGAGL_Keytable[SCANCODE_PAGEUP] = GP_PageUp;
349
350     VGAGL_Keytable[SCANCODE_REMOVE] = GP_Delete;
351     VGAGL_Keytable[SCANCODE_END] = GP_End;
352     VGAGL_Keytable[SCANCODE_PAGEDOWN] = GP_PageDown;
353
354     /* arrow keys */
355     VGAGL_Keytable[SCANCODE_CURSORBLOCKUP] = GP_Up;
356     VGAGL_Keytable[SCANCODE_CURSORBLOCKLEFT] = GP_Left;
357     VGAGL_Keytable[SCANCODE_CURSORBLOCKRIGHT] = GP_Right;
358     VGAGL_Keytable[SCANCODE_CURSORBLOCKDOWN] = GP_Down;
359
360     /* VGAGL_Keytable[SCANCODE_RIGHTWIN] */
361     /* VGAGL_Keytable[SCANCODE_LEFTWIN] */
362 }
363
364 enum {
365     VGAGL_INVALID = -1,
366     VGAGL_BACKGROUND = 1,
367     VGAGL_UNIFORM,
368     VGAGL_INTERPOLATE,
369     VGAGL_DUMP
370 };
371
372 static struct gen_table VGAGL_opts[] = {
373     { "ba$ckground", VGAGL_BACKGROUND },
374     { "bg", VGAGL_BACKGROUND },
375     { "un$iform", VGAGL_UNIFORM },
376     { "in$terpolate", VGAGL_INTERPOLATE },
377 #ifdef VGAGL_DEBUGGING
378     { "dump", VGAGL_DUMP },
379 #endif
380     { NULL, VGAGL_INVALID }
381 };
382
383 /* parse driver optinos. This is done when the
384  * user types `set term vgagl [options ...]'. */
385 TERM_PUBLIC
386 void VGAGL_options()
387 {
388     if (!LINUX_graphics_allowed) {
389         int_error(NO_CARET, "vgagl terminal driver not available");
390         return;
391     }
392
393 #ifdef VGAGL_DEBUGGING
394 #if 0
395     if (VGAGL_dump_file)
396         free(VGAGL_dump_file);
397     VGAGL_dump_file = (char*) 0;
398 #endif
399 #endif
400
401     if (END_OF_COMMAND) {
402         /* defaults */
403         vgagl_vmode = -1; /* get default mode */
404         VGAGL_bg_red = 0;
405         VGAGL_bg_green = 0;
406         VGAGL_bg_blue = 0;
407         VGAGL_interpolate = TRUE;
408     }
409
410     while (!END_OF_COMMAND) {
411         switch (lookup_table(VGAGL_opts, c_token)) {
412             case VGAGL_BACKGROUND:
413                 {
414                     struct value a;
415                     int i, c[3];
416                     ++c_token;
417                     for (i = 0; i < 3; i++) {
418                         if (END_OF_COMMAND) {
419                             break;
420                         }
421                         c[i] = (int)real(const_express(&a));
422                         if (c[i] < 0 || c[i] > 255) {
423                             fprintf(stderr, "color ranges from 0 to 255\n");
424                             return;
425                         }
426                     }
427                     if (!i) {
428                         fprintf(stderr, "background requires arguments\n");
429                     } else if (i < 3) {
430                         c[1] = c[0];
431                         c[2] = c[0];
432                     }
433                     VGAGL_bg_red = c[0];
434                     VGAGL_bg_green = c[1];
435                     VGAGL_bg_blue = c[2];
436                 }
437                 break;
438             case VGAGL_UNIFORM:
439                 VGAGL_interpolate = FALSE;
440                 ++c_token;
441                 break;
442             case VGAGL_INTERPOLATE:
443                 VGAGL_interpolate = TRUE;
444                 ++c_token;
445                 break;
446 #ifdef VGAGL_DEBUGGING
447             case VGAGL_DUMP:
448                 /* since this is not documented it won't hurt too much to leave it in. */
449                 ++c_token;
450                 if (isstring(c_token)) {
451                     if (VGAGL_dump_file)
452                         free(VGAGL_dump_file);
453                     /* get text */
454                     VGAGL_dump_file = gp_alloc(token_len(c_token), "vgagl->dump_file");
455                     quote_str(VGAGL_dump_file, c_token, token_len(c_token));
456                     ++c_token;
457                 } else {
458                     int_error(NO_CARET, "expecting string value");
459                     return;
460                 }
461                 break;
462 #endif
463             default:
464                 {
465                     /* VGA MODE */
466                     char x[0x40];
467                     int imode;
468                     copy_str(x, c_token, 0x3f);
469                     imode = vga_getmodenumber(x);
470                     if (-1 != imode) {
471                         if (vga_hasmode(imode)) {
472                             vgagl_vmode = imode;
473                         } else {
474                             fprintf(stderr, "mode %s not available\n",
475                                 vga_getmodename(imode));
476                         }
477                     }
478                     c_token++;
479                 }
480                 if (VGAGL_graphics_on) {
481                     VGAGL_processing_graphics_events = FALSE;
482                     VGAGL_reset();
483                 }
484                 break;
485         }
486     }
487     if (VGAGL_graphics_on) {
488         VGAGL_set_black_and_white();
489     }
490     VGAGL_get_mode(); /* check availability of mode */
491     sprintf(term_options, "%s bg %d %d %d %s",
492         vga_getmodename(vgagl_vmode),
493         VGAGL_bg_red, VGAGL_bg_green, VGAGL_bg_blue,
494         TRUE == VGAGL_interpolate ? "interpolate" : "uniform");
495 }
496
497 void
498 VGAGL_setpalettecolor(int index, double red, double green, double blue)
499 {
500 #ifdef VGAGL_DEBUGGING
501     assert(index >= 0 && index < 0x100);
502     assert(red >= 0 && red <= 1);
503     assert(green >= 0 && green <= 1);
504     assert(blue >= 0 && blue <= 1);
505     VGAGL_palette[index][0] = (unsigned char) floor(red * 255.999);
506     VGAGL_palette[index][1] = (unsigned char) floor(green * 255.999);
507     VGAGL_palette[index][2] = (unsigned char) floor(blue * 255.999);
508 #endif
509     gl_setpalettecolor(index, red * 63.999, green * 63.999, blue * 63.999);
510 }
511
512 /* set the background color (default is black) and choose
513  * the primary foreground and xor colors appropriately */
514 TERM_PUBLIC void
515 VGAGL_set_black_and_white()
516 {
517     /* background */
518 #ifdef VGAGL_ENABLE_TRUECOLOR
519     switch (VGAGL_truecolor) {
520         case TRUE:
521             VGAGL_line_cmap[0] = gl_rgbcolor(VGAGL_bg_red, VGAGL_bg_green, VGAGL_bg_blue);
522             break;
523         default:
524 #endif
525             VGAGL_setpalettecolor(0,
526                 (double) VGAGL_bg_red / (double) 0xff,
527                 (double) VGAGL_bg_green / (double) 0xff,
528                 (double) VGAGL_bg_blue / (double) 0xff);
529 #ifdef VGAGL_ENABLE_TRUECOLOR
530     }
531 #endif
532     if (VGAGL_bg_red + VGAGL_bg_green + VGAGL_bg_blue > 0x180) {
533         /* light background */
534 #ifdef VGAGL_ENABLE_TRUECOLOR
535         switch (VGAGL_truecolor) {
536             case TRUE:
537                 VGAGL_line_cmap[1] = gl_rgbcolor(0x00, 0x00, 0x00);
538                 break;
539             default:
540 #endif
541                 VGAGL_setpalettecolor(1, 0, 0, 0); /* black */
542 #ifdef VGAGL_ENABLE_TRUECOLOR
543         }
544 #endif
545         VGAGL_xor_red = 0xa0;
546         VGAGL_xor_green = 0xa0;
547         VGAGL_xor_blue = 0xa0;
548         /* TODO  need to allocate a colormap entry for the xor color ? */
549 #if 0
550         VGAGL_xor_red = ~VGAGL_bg_red;
551         VGAGL_xor_green = ~VGAGL_bg_green;
552         VGAGL_xor_blue = ~VGAGL_bg_blue;
553         fprintf(stderr, "(VGAGL_set_black_and_white) VGAGL_xor_red = %d\n", VGAGL_xor_red);
554         fprintf(stderr, "(VGAGL_set_black_and_white) VGAGL_xor_green = %d\n", VGAGL_xor_green);
555         fprintf(stderr, "(VGAGL_set_black_and_white) VGAGL_xor_blue = %d\n", VGAGL_xor_blue);
556 #endif
557     } else {
558         /* dark background */
559 #ifdef VGAGL_ENABLE_TRUECOLOR
560         switch (VGAGL_truecolor) {
561             case TRUE:
562                 VGAGL_line_cmap[1] = gl_rgbcolor(0xff, 0xff, 0xff);
563                 break;
564             default:
565 #endif
566                 VGAGL_setpalettecolor(1, 1, 1, 1); /* white */
567 #ifdef VGAGL_ENABLE_TRUECOLOR
568         }
569 #endif
570         VGAGL_xor_red = 0xff;
571         VGAGL_xor_green = 0xff;
572         VGAGL_xor_blue = 0xff;
573         /* TODO  need to allocate a colormap entry for the xor color ? */
574     }
575 }
576
577 /* set up line colors */
578 TERM_PUBLIC void
579 VGAGL_set_line_colors()
580 {
581     gl_setrgbpalette();
582     VGAGL_set_black_and_white();
583 #ifdef VGAGL_ENABLE_TRUECOLOR
584     switch (VGAGL_truecolor) {
585         case TRUE:
586             VGAGL_line_cmap[2]  = gl_rgbcolor(0x80, 0x80, 0x80); /* gray */
587             VGAGL_line_cmap[3]  = gl_rgbcolor(0x00, 0xff, 0x00); /* green */
588             VGAGL_line_cmap[4]  = gl_rgbcolor(0x00, 0xff, 0xff); /* cyan */
589             VGAGL_line_cmap[5]  = gl_rgbcolor(0xff, 0x00, 0x00); /* red */
590             VGAGL_line_cmap[6]  = gl_rgbcolor(0xff, 0x00, 0xff); /* magenta */
591             VGAGL_line_cmap[7]  = gl_rgbcolor(0x00, 0x00, 0xff); /* blue */
592             VGAGL_line_cmap[8]  = gl_rgbcolor(0xff, 0xff, 0x00); /* yellow */
593             VGAGL_line_cmap[9]  = gl_rgbcolor(0xff, 0x80, 0x80); /* light red */
594             VGAGL_line_cmap[10] = gl_rgbcolor(0xff, 0xff, 0xff); /* white */
595             VGAGL_line_cmap[11] = gl_rgbcolor(0xff, 0x80, 0xff); /* light magenta */
596             VGAGL_line_cmap[12] = gl_rgbcolor(0x80, 0xff, 0x80); /* light green */
597             VGAGL_line_cmap[13] = gl_rgbcolor(0x80, 0xff, 0xff); /* light cyan */
598             VGAGL_line_cmap[14] = gl_rgbcolor(0x80, 0x80, 0xff); /* light blue */
599             break;
600         default:
601 #endif
602             VGAGL_setpalettecolor(2, 0.5, 0.5, 0.5); /* gray */
603             VGAGL_setpalettecolor(3, 0.0, 1.0, 0.0); /* green */
604             VGAGL_setpalettecolor(4, 0.0, 1.0, 1.0); /* cyan */
605             VGAGL_setpalettecolor(5, 1.0, 0.0, 0.0); /* red */
606             VGAGL_setpalettecolor(6, 1.0, 0.0, 1.0); /* magenta */
607             VGAGL_setpalettecolor(7, 0.0, 0.0, 1.0); /* blue */
608             VGAGL_setpalettecolor(8, 1.0, 1.0, 0.0); /* yellow */
609             VGAGL_setpalettecolor(9, 1.0, 0.5, 0.5); /* light red */
610             VGAGL_setpalettecolor(10, 1.0, 1.0, 1.0); /* white */
611             VGAGL_setpalettecolor(11, 1.0, 0.5, 1.0); /* light magenta */
612             VGAGL_setpalettecolor(12, 0.5, 1.0, 0.5); /* light green */
613             VGAGL_setpalettecolor(13, 0.5, 1.0, 1.0); /* light cyan */
614             VGAGL_setpalettecolor(14, 0.5, 0.5, 1.0); /* light blue */
615 #ifdef VGAGL_ENABLE_TRUECOLOR
616     }
617 #endif
618 }
619
620 TERM_PUBLIC int
621 VGAGL_get_mode()
622 {
623     int *iptr;
624
625     static int default_modes[] = {
626         0, /* to be filled with the user defined mode */
627         0, /* to be filled with the default mode */
628         G1024x768x256, /* hopefully available on all modern graphics boards */
629         G800x600x256,
630         G640x480x256,
631         G320x200x256,
632         G1280x1024x256,
633 #ifdef G1152x864x256
634         G1152x864x256,
635 #endif
636 #ifdef G1360x768x256
637         G1360x768x256,
638 #endif
639 #ifdef G1600x1200x256
640         G1600x1200x256,
641 #endif
642         TEXT
643     };
644
645     if (VGAGL_graphics_on) {
646         return 1; /* success ??? */
647     }
648
649     /* the user supplied mode will be checked first */
650     default_modes[0] = vgagl_vmode;
651
652     /* get the default mode from SVGALIB_DEFAULT_MODE, if available */
653     default_modes[1] = vga_getdefaultmode();
654
655     for (iptr = default_modes; TEXT != *iptr; iptr++) {
656         if (-1 != *iptr && vga_hasmode(*iptr)) {
657             vgagl_vmode = *iptr;
658             break;
659         }
660     }
661
662     if (TEXT == *iptr) {
663         vgagl_vmode = TEXT;
664         int_error(NO_CARET, "vgagl terminal driver not available");
665         return 0;
666     }
667
668     modeinfo = vga_getmodeinfo(vgagl_vmode);
669
670 #ifdef VGAGL_ENABLE_TRUECOLOR
671     VGAGL_truecolor = FALSE;
672 #endif
673     VGAGL_pm3d_colors = VGAGL_8bit_colors;
674     VGAGL_pm3d_colors_ = VGAGL_pm3d_colors - 1;
675
676     if (modeinfo->colors != 256) {
677         int_error(NO_CARET, "Error: need a 256 color mode but got %d colors\n",
678             modeinfo->colors);
679         return 0;
680 #ifdef VGAGL_ENABLE_TRUECOLOR
681     } else if (modeinfo->colors > 256) {
682         VGAGL_truecolor = TRUE;
683         VGAGL_pm3d_colors = VGAGL_tri_colors;
684         VGAGL_pm3d_colors_ = VGAGL_pm3d_colors - 1;
685 #endif
686     }
687     return 1; /* success */
688 }
689
690 TERM_PUBLIC void
691 VGAGL_init()
692 {
693     static TBOOLEAN keytable_initialized = FALSE;
694
695     if (!VGAGL_graphics_on) {
696
697         /* initialize keyboard tranlation table, only done once */
698         if (!keytable_initialized) {
699             VGAGL_init_keytable();
700             keytable_initialized = TRUE;
701         }
702
703         if (!VGAGL_get_mode()) {
704             return;
705         }
706
707     }
708     term->xmax = modeinfo->width;
709     term->ymax = modeinfo->height;
710     vgagl_lasty = modeinfo->height - 1;
711     vgagl_lastx = modeinfo->width - 1;
712 #if 0
713     gl_setfont(8, 8, gl_font8x8);
714     gl_setwritemode(WRITEMODE_MASKED + FONT_COMPRESSED);
715     fprintf(stderr, "(VGAGL_init) width, height = %d, %d\n", term->xmax, term->ymax);
716 #endif
717 }
718
719 TERM_PUBLIC void
720 VGAGL_reset()
721 {
722     if (VGAGL_graphics_on && !VGAGL_processing_graphics_events) {
723         keyboard_close();                  /* switch back to cooked mode          */
724         vga_setmousesupport(0);            /* turn off mouse                      */
725         vga_setmode(TEXT);                 /* switch to text mode                 */
726         VGAGL_save_pal.colorFormulae = -1; /* force later reallocation of palette */
727         VGAGL_graphics_on = FALSE;
728     }
729 }
730
731 /* copy virtual screen to physical screen and process
732    input events until the user leaves the graphics mode */
733 TERM_PUBLIC void
734 VGAGL_text()
735 {
736     if (!VGAGL_cursor_drawn) {
737         VGAGL_draw_cursor(VGAGL_cursorx, VGAGL_cursory); /* actually draws the first time the cursor */
738         VGAGL_cursor_drawn = TRUE;
739         if (VGAGL_ruler_x >= 0) {
740             VGAGL_set_ruler(VGAGL_ruler_x, VGAGL_ruler_y);
741         }
742     }
743
744     gl_copyscreen(&physicalscreen);
745
746     /* this is dirty but should work. The purpose is to force
747      * gnuplot to call VGAGL_graphics() before redrawing. */
748     term_graphics = FALSE;
749
750     if (!VGAGL_graphics_on || VGAGL_processing_graphics_events) {
751         return;
752     }
753
754     /* go to the input event loop */
755     VGAGL_eventually_process_graphics_events();
756
757     /* switch to TEXT mode */
758     VGAGL_reset();
759 }
760
761 TERM_PUBLIC void
762 VGAGL_graphics()
763 {
764     if (!VGAGL_graphics_on) {
765         vga_setmousesupport(1);
766         if (gl_setcontextvgavirtual(vgagl_vmode)) {
767             fprintf(stderr, "(VGAGL_graphics) unable to set virtual context\n");
768         }
769         gl_getcontext(&backscreen);
770         vga_setmode(vgagl_vmode);
771         gl_setcontextvga(vgagl_vmode); /* Physical screen context. */
772         gl_getcontext(&physicalscreen);
773         gl_setcontext(&backscreen);
774         gl_clearscreen(0); /* clear backscreen; we'll draw there */
775         gl_enableclipping();
776         VGAGL_set_line_colors();
777
778         /* center the cursor on startup */
779         VGAGL_cursorx = WIDTH / 2;
780         VGAGL_cursory = HEIGHT / 2;
781
782         VGAGL_graphics_on = TRUE;
783     } else {
784         /* graphics is already on; clear previous plot */
785         gl_clearscreen(0);
786     }
787     supply_extended_color_specs = 1;
788     VGAGL_cursor_drawn = FALSE;
789     VGAGL_savedstr[0] = '\0';
790 #if 0
791     {
792         int avail = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL);
793         fprintf(stderr, "ACCELFLAG_FILLBOX %s\n", (avail & ACCELFLAG_FILLBOX) ? "yes" : "no");
794         fprintf(stderr, "ACCELFLAG_SCREENCOPY %s\n", (avail & ACCELFLAG_SCREENCOPY) ? "yes" : "no");
795         fprintf(stderr, "ACCELFLAG_PUTIMAGE %s\n", (avail & ACCELFLAG_PUTIMAGE) ? "yes" : "no");
796         fprintf(stderr, "ACCELFLAG_DRAWLINE %s\n", (avail & ACCELFLAG_DRAWLINE) ? "yes" : "no");
797         fprintf(stderr, "ACCELFLAG_SETFGCOLOR %s\n", (avail & ACCELFLAG_SETFGCOLOR) ? "yes" : "no");
798         fprintf(stderr, "ACCELFLAG_SETBGCOLOR %s\n", (avail & ACCELFLAG_SETBGCOLOR) ? "yes" : "no");
799         fprintf(stderr, "ACCELFLAG_SETTRANSPARENCY %s\n", (avail & ACCELFLAG_SETTRANSPARENCY) ? "yes" : "no");
800         fprintf(stderr, "ACCELFLAG_SETRASTEROP %s\n", (avail & ACCELFLAG_SETRASTEROP) ? "yes" : "no");
801         fprintf(stderr, "ACCELFLAG_PUTBITMAP %s\n", (avail & ACCELFLAG_PUTBITMAP) ? "yes" : "no");
802         fprintf(stderr, "ACCELFLAG_SCREENCOPYBITMAP %s\n", (avail & ACCELFLAG_SCREENCOPYBITMAP) ? "yes" : "no");
803         fprintf(stderr, "ACCELFLAG_DRAWHLINELIST %s\n", (avail & ACCELFLAG_DRAWHLINELIST) ? "yes" : "no");
804         fprintf(stderr, "ACCELFLAG_SETMODE %s\n", (avail & ACCELFLAG_SETMODE) ? "yes" : "no");
805         fprintf(stderr, "ACCELFLAG_SYNC %s\n", (avail & ACCELFLAG_SYNC) ? "yes" : "no");
806     }
807 #endif
808 }
809
810 TERM_PUBLIC void
811 VGAGL_suspend()
812 {
813 #if 1
814     VGA_FPRINTF((stderr, "(VGAGL_suspend) \n"));
815     keyboard_close();                  /* switch back to cooked mode          */
816     vga_setmousesupport(0);            /* turn off mouse                      */
817     vga_flip();
818 #endif
819 }
820
821 TERM_PUBLIC void
822 VGAGL_resume()
823 {
824 #if 1
825     VGA_FPRINTF((stderr, "(VGAGL_resume) \n"));
826     vga_flip();
827     keyboard_init();                  /* put keyboard to raw mode */
828     vga_setmousesupport(1);           /* turn mouse on            */
829 #endif
830 }
831
832 TERM_PUBLIC void
833 VGAGL_linetype(int linetype)
834 {
835     if (linetype < -3)
836         linetype = LT_NODRAW;
837
838 #ifdef VGAGL_ENABLE_TRUECOLOR
839     switch (VGAGL_truecolor) {
840         case TRUE:
841             current_color = VGAGL_line_cmap[(linetype + 3) % 13];
842             break;
843         default:
844 #endif
845             current_color = (linetype + 3) % 13;
846 #ifdef VGAGL_ENABLE_TRUECOLOR
847     }
848 #endif
849 }
850
851 TERM_PUBLIC void
852 VGAGL_move(unsigned int x, unsigned int y)
853 {
854     VGAGL_startx = x;
855     VGAGL_starty = Y(y);
856 }
857
858 TERM_PUBLIC void
859 VGAGL_vector(unsigned int x, unsigned int y)
860 {
861     /* fprintf(stderr, "(VGAGL_vector) x, y = %d %d\n", x, y); */
862     int sy = Y(y);
863     gl_line(VGAGL_startx, VGAGL_starty, x, sy, current_color);
864     VGAGL_startx = x;
865     VGAGL_starty = sy;
866 }
867
868 TERM_PUBLIC int
869 VGAGL_text_angle(int ang)
870 {
871     VGAGL_angle = (ang ? 1 : 0);
872     return TRUE;
873 }
874
875 /* driver's coordinate system */
876 void
877 VGAGL_xor_pixel_wrapper(int x, int y, int color)
878 {
879     /* discard color */
880     VGAGL_xor_pixel(x, y);
881 }
882
883 /* driver's coordinate system */
884 static void
885 VGAGL_putc(unsigned int x, unsigned int y, int c, int ang, int color)
886 {
887     int i, j, k;
888     void (*pixelfun)(int, int, int);
889
890     i = (int) (c) - 32;
891
892     switch (color) {
893         case -1:
894             pixelfun = VGAGL_xor_pixel_wrapper;
895             break;
896         default:
897             pixelfun = gl_setpixel;
898     }
899
900     switch (ang) {
901         case 0: /* horizontal */
902             for (x++, j = 0; j < FNT5X9_VBITS; j++, y--) {
903                 for (k = 0; k < FNT5X9_HBITS; k++) {
904                     if ((((unsigned int) (fnt5x9[i][j])) >> k & 1)) {
905                         pixelfun(x + k, y, current_color);
906                     }
907                 }
908             }
909             break;
910         case 1: /* vertical */
911             for (y--, j = 0; j < FNT5X9_VBITS; j++, x--) {
912                 for (k = 0; k < FNT5X9_HBITS; k++) {
913                     if ((((unsigned int) (fnt5x9[i][j])) >> k & 1)) {
914                         pixelfun(x, y - k, current_color);
915                     }
916                 }
917             }
918             break;
919         default:
920             fprintf(stderr, "(VGAGL_putc) angle %d not implemented\n",
921                 VGAGL_angle);
922     }
923 }
924
925 /* driver's coordinate system */
926 TERM_PUBLIC void
927 VGAGL_put_text_with_color(
928     unsigned int x, unsigned int y,
929     const char *str,
930     int color)
931 {
932     const char* ptr;
933
934     switch (VGAGL_angle) {
935         case 0:
936             y += VGAGL_VCHAR / 2;
937             break;
938         case 1:
939             x += VGAGL_VCHAR / 2;
940             break;
941     }
942
943     for (ptr = str; *ptr; ptr++) {
944         VGAGL_putc(x, y, *ptr, VGAGL_angle, color);
945         switch (VGAGL_angle) {
946             case 0:
947                 x += VGAGL_HCHAR;
948                 break;
949             case 1:
950                 y -= VGAGL_HCHAR;
951                 break;
952             default:
953                 fprintf(stderr, "(VGAGL_put_text) angle %d not implemented\n",
954                     VGAGL_angle);
955         }
956     }
957     VGAGL_need_update = TRUE;
958 }
959
960 /* gnuplot's coordinate system */
961 TERM_PUBLIC void
962 VGAGL_put_text(unsigned int x, unsigned int y, const char *str)
963 {
964     VGAGL_put_text_with_color(x, Y(y), str, current_color);
965 }
966
967 void
968 VGAGL_xor_pixel(int x, int y)
969 {
970     int r, g, b;
971     gl_getpixelrgb(x, y, &r, &g, &b);
972     r ^= VGAGL_xor_red;
973     g ^= VGAGL_xor_green;
974     b ^= VGAGL_xor_blue;
975 #if 0
976     fprintf(stderr, " xor: %3d %3d %3d\n", r, g, b);
977 #endif
978     gl_setpixelrgb(x, y, r, g, b);
979 }
980 void
981 VGAGL_hline_xor(int x1, int x2, int y)
982 {
983     int i;
984     if (x1 > x2) {
985         int tmp = x1;
986         x1 = x2;
987         x2 = tmp;
988     }
989     for (i = x1; i <= x2; i++) {
990         VGAGL_xor_pixel(i, y);
991     }
992 }
993 void
994 VGAGL_vline_xor(int y1, int y2, int x)
995 {
996     if (y1 > y2) {
997         /* swap */
998         int tmp = y1;
999         y1 = y2;
1000         y2 = tmp;
1001     }
1002     if (-1 == vga_accel(ACCEL_SETRASTEROP, ROP_XOR)) {
1003         /* vga_accel(ACCEL_SETRASTEROP, ROP_XOR) is not available */
1004         int i;
1005         for (i = y1; i <= y2; i++) {
1006             VGAGL_xor_pixel(x, i);
1007         }
1008     } else {
1009         fprintf(stderr, "(VGAGL_vline_xor) accelerated xor was never tested\n");
1010         gl_line(x, y1, x, y2, 1);
1011         vga_accel(ACCEL_SETRASTEROP, ROP_COPY); /* switching back */
1012     }
1013 }
1014
1015 #if 0
1016 void
1017 VGAGL_line_xor(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
1018 {
1019     if (x1 == x2) {
1020         VGAGL_vline_xor(y1, y2, x1);
1021     } else if (y1 == y2) {
1022         VGAGL_hline_xor(x1, x2, y1);
1023     } else {
1024         fprintf(stderr, "(VGAGL_line_xor) vertical lines not implemented\n");
1025     }
1026 }
1027 #endif
1028
1029 TERM_PUBLIC void
1030 VGAGL_draw_cursor(int x, int y)
1031 {
1032     static const int cursorsize = 5;
1033     VGAGL_hline_xor(x - cursorsize, x + cursorsize, y);
1034     VGAGL_vline_xor(y - cursorsize, y + cursorsize, x);
1035     VGAGL_last_cursorx = x;
1036     VGAGL_last_cursory = y;
1037 }
1038
1039 void
1040 VGAGL_zoombox(int x, int y)
1041 {
1042     VGAGL_hline_xor(VGAGL_zoom.startx, x, VGAGL_zoom.starty);
1043     VGAGL_hline_xor(VGAGL_zoom.startx, x, y);
1044     VGAGL_vline_xor(VGAGL_zoom.starty, y, VGAGL_zoom.startx);
1045     VGAGL_vline_xor(VGAGL_zoom.starty, y, x);
1046
1047     if (*VGAGL_zoom.current_xstr && *VGAGL_zoom.current_ystr) {
1048
1049         int ty;
1050
1051         /* first corner (static) */
1052         ty = VGAGL_zoom.starty - VGAGL_VCHAR / 2;
1053         VGAGL_put_text_with_color(VGAGL_zoom.startx, ty, VGAGL_zoom.current_xstr[0], -1);
1054         VGAGL_put_text_with_color(VGAGL_zoom.startx, ty + VGAGL_VCHAR, VGAGL_zoom.current_ystr[0], -1);
1055
1056         /* second corner (at the curser) */
1057         ty = y - VGAGL_VCHAR / 2;
1058         VGAGL_put_text_with_color(x, ty, VGAGL_zoom.current_xstr[1], -1);
1059         VGAGL_put_text_with_color(x, ty + VGAGL_VCHAR, VGAGL_zoom.current_ystr[1], -1);
1060     }
1061
1062     VGAGL_zoom.currentx = x;
1063     VGAGL_zoom.currenty = y;
1064 }
1065
1066 void
1067 VGAGL_update_zoombox(int x, int y)
1068 {
1069     if (VGAGL_zoom.startx >= 0) {
1070         VGAGL_zoombox(VGAGL_zoom.currentx, VGAGL_zoom.currenty); /* erase old box */
1071         strcpy(VGAGL_zoom.current_xstr[0], VGAGL_zoom.xstr[0]);
1072         strcpy(VGAGL_zoom.current_ystr[0], VGAGL_zoom.ystr[0]);
1073         strcpy(VGAGL_zoom.current_xstr[1], VGAGL_zoom.xstr[1]);
1074         strcpy(VGAGL_zoom.current_ystr[1], VGAGL_zoom.ystr[1]);
1075         VGAGL_zoombox(x, y); /* draw new box */
1076         VGAGL_need_update = TRUE;
1077     }
1078 }
1079
1080 void
1081 VGAGL_update_cursor(int x, int y)
1082 {
1083     VGAGL_draw_cursor(VGAGL_last_cursorx, VGAGL_last_cursory); /* erase old cursor */
1084     VGAGL_draw_cursor(x, y); /* draw new cursor */
1085     VGAGL_need_update = TRUE;
1086 }
1087
1088 void
1089 VGAGL_signal_handler(int signum)
1090 {
1091     struct gp_event_t ge = {-1, -1, -1, -1, -1, ""};
1092     ge.type = GE_modifier;
1093     ge.par1 = 0; /* release all modifiers */
1094     do_event(&ge);
1095     VGAGL_processing_graphics_events = FALSE;
1096     signal(SIGINT, VGAGL_old_handler); /* reset signal handler */
1097     VGAGL_reset();
1098 }
1099
1100 void
1101 VGAGL_eventually_process_graphics_events()
1102 {
1103     /*
1104        VGA_FPRINTF((stderr, "(VGAGL_eventually_process_graphics_events) \n"));
1105      */
1106     if (VGAGL_graphics_on && !VGAGL_processing_graphics_events) {
1107
1108         int lastbutton = 0;
1109         struct gp_event_t ge = {-1, -1, -1, -1, -1, ""};
1110         TBOOLEAN loop = TRUE;
1111         int yinv;
1112
1113         VGAGL_processing_graphics_events = TRUE;
1114
1115         /* set up a signal hander, so that SIGINT
1116          * can restore a clean terminal state */
1117         VGAGL_old_handler = signal(SIGINT, VGAGL_signal_handler);
1118
1119         keyboard_init(); /* put keyboard to raw mode */
1120
1121         /* put the mouse pointer to the center */
1122         mouse_setposition(VGAGL_cursorx, VGAGL_cursory);
1123
1124         while (VGAGL_graphics_on && loop) {
1125
1126             int button;
1127             int motion;
1128             int ret;
1129
1130             event_plotdone();
1131             if (VGAGL_need_update) {
1132                 gl_copyscreen(&physicalscreen);
1133                 VGAGL_need_update = FALSE;
1134             }
1135
1136             ret = vga_waitevent(VGA_MOUSEEVENT | VGA_KEYEVENT,
1137                 (fd_set*) 0, (fd_set*) 0, (fd_set*) 0, (struct timeval*) 0);
1138
1139             VGAGL_cursorx = mouse_getx();
1140             VGAGL_cursory = mouse_gety();
1141             yinv = term->ymax - VGAGL_cursory;
1142             button = mouse_getbutton();
1143             motion = (-1 != ge.mx && (VGAGL_cursorx != ge.mx || yinv != ge.my));
1144             ge.mx = VGAGL_cursorx;
1145             ge.my = yinv;
1146
1147             if (ret < 0) {
1148                 /* error */
1149                 loop = FALSE;
1150             }
1151             if ((ret & VGA_MOUSEEVENT)) {
1152
1153                 if (button != lastbutton) {
1154                     /* button changed (either pressed or released */
1155                     int button_changed;
1156                     if (button) {
1157                         /* button press event */
1158                         ge.type = GE_buttonpress;
1159                         button_changed = button;
1160                     } else {
1161                         /* button release event */
1162                         button_changed = lastbutton;
1163                         ge.type = GE_buttonrelease;
1164                     }
1165                     if (button_changed & MOUSE_LEFTBUTTON)
1166                         ge.par1 = 1;
1167                     else if (button_changed & MOUSE_MIDDLEBUTTON)
1168                         ge.par1 = 2;
1169                     else if (button_changed & MOUSE_RIGHTBUTTON)
1170                         ge.par1 = 3;
1171
1172                     do_event(&ge);
1173                     lastbutton = button;
1174                 }
1175
1176                 if (motion) {
1177                     /* fprintf(stderr, "(motion) VGAGL_cursorx, VGAGL_cursory = %d %d\n", VGAGL_cursorx, VGAGL_cursory); */
1178                     ge.type = GE_motion;
1179                     do_event(&ge);
1180                     VGAGL_update_cursor(VGAGL_cursorx, VGAGL_cursory);
1181                     VGAGL_update_zoombox(VGAGL_cursorx, VGAGL_cursory);
1182                 }
1183             }
1184             if (ret & VGA_KEYEVENT) {
1185                 /* int c = vga_getch(); */
1186                 char* state = keyboard_getstate();
1187                 int mask = 0;
1188                 int i;
1189                 /* keyboard_translatekeys() */
1190                 if (state[SCANCODE_LEFTCONTROL] || state[SCANCODE_RIGHTCONTROL]) {
1191                     mask |= Mod_Ctrl;
1192                 }
1193                 if (state[SCANCODE_LEFTALT] || state[SCANCODE_RIGHTALT]) {
1194                     mask |= Mod_Alt;
1195                 }
1196                 if (state[SCANCODE_LEFTSHIFT] || state[SCANCODE_RIGHTSHIFT]) {
1197                     mask |= Mod_Shift;
1198                 }
1199                 if (mask) {
1200                     ge.type = GE_modifier;
1201                     ge.par1 = mask;
1202                     do_event(&ge);
1203                 } else if (VGAGL_modifier_mask) {
1204                     /* modifiers were released */
1205                     ge.type = GE_modifier;
1206                     ge.par1 = 0;
1207                     do_event(&ge);
1208                 }
1209                 VGAGL_modifier_mask = mask;
1210
1211                 for (i = 0; i < KEYTABLE_SIZE; i++) {
1212                     if (state[i] && -1 != VGAGL_Keytable[i]) {
1213                         if (' ' == VGAGL_Keytable[i] || 'q' == VGAGL_Keytable[i]) {
1214                             loop = FALSE;
1215                             break;
1216                         }
1217 #ifdef VGAGL_DEBUGGING
1218                         if (GP_KP_Delete == VGAGL_Keytable[i] && VGAGL_dump_file) {
1219                             VGAGL_draw_cursor(VGAGL_last_cursorx, VGAGL_last_cursory); /* erase cursor */
1220                             VGAGL_write_dump_file();
1221                             VGAGL_draw_cursor(VGAGL_last_cursorx, VGAGL_last_cursory); /* draw cursor */
1222                             break;
1223                         }
1224 #endif
1225                         ge.type = GE_keypress;
1226                         ge.par1 = VGAGL_Keytable[i];
1227                         ge.par2 = 0;
1228                         do_event(&ge);
1229                     }
1230                 }
1231             } /* VGA_KEYEVENT */
1232         } /* while(1) */
1233         VGAGL_processing_graphics_events = FALSE;
1234         signal(SIGINT, VGAGL_old_handler);
1235     } /* VGAGL_graphics_on */
1236 }
1237
1238 TERM_PUBLIC void
1239 VGAGL_put_tmptext(int i, const char str[])
1240 {
1241     int y = 0;
1242     int x;
1243     char* second;
1244
1245     switch (i) {
1246         case 0:
1247             /* erase old text */
1248             for (i = 0, y = 0, x = VGAGL_HCHAR; VGAGL_savedstr[i]; i++) {
1249                 VGAGL_putc(x, Y(y), VGAGL_savedstr[i], 0, -1);
1250                 x += VGAGL_HCHAR;
1251             }
1252             strcpy(VGAGL_savedstr, str);
1253             for (i = 0, y = 0, x = VGAGL_HCHAR; str[i]; i++) {
1254                 VGAGL_putc(x, Y(y), str[i], 0, -1);
1255                 x += VGAGL_HCHAR;
1256             }
1257             VGAGL_need_update = TRUE;
1258             break;
1259         case 1:
1260         case 2:
1261             --i;
1262             second = (char*) strchr(str, '\r');
1263             if (second == NULL) {
1264                 VGAGL_zoom.xstr[i][0] = '\0';
1265                 VGAGL_zoom.ystr[i][0] = '\0';
1266                 break;
1267             }
1268             *second = '\0'; /* XXX this assumes that str is writable XXX */
1269             second++;
1270             /* if (VGAGL_zoombox_on) DrawBox(plot); */
1271             strcpy(VGAGL_zoom.xstr[i], str);
1272             strcpy(VGAGL_zoom.ystr[i], second);
1273             /* if (plot->zoombox_on) DrawBox(plot); */
1274             VGAGL_need_update = TRUE;
1275             break;
1276     }
1277     return;
1278 }
1279
1280 TERM_PUBLIC void
1281 VGAGL_set_ruler(int x, int y)
1282 {
1283     if (x < 0) {
1284         /* erase last ruler */
1285         VGAGL_hline_xor(0, vgagl_lastx, Y(VGAGL_ruler_y));
1286         VGAGL_vline_xor(0, vgagl_lasty, VGAGL_ruler_x);
1287         VGAGL_ruler_x = -1;
1288     } else {
1289         VGAGL_ruler_x = x;
1290         VGAGL_ruler_y = y;
1291         VGAGL_hline_xor(0, vgagl_lastx, Y(VGAGL_ruler_y));
1292         VGAGL_vline_xor(0, vgagl_lasty, VGAGL_ruler_x);
1293     }
1294     VGAGL_need_update = TRUE;
1295     return;
1296 }
1297
1298 TERM_PUBLIC void
1299 VGAGL_set_cursor(int c, int x, int y)
1300 {
1301     /* VGA_FPRINTF((stderr, "(VGAGL_set_cursor) \n")); */
1302     switch (c) {
1303         case -2: /* warp pointer */
1304             /* TODO */
1305             break;
1306         case -1: /* starting zoombox */
1307             VGAGL_zoom.startx = x;
1308             VGAGL_zoom.starty = Y(y);
1309
1310             VGAGL_zoom.currentx = VGAGL_zoom.startx;
1311             VGAGL_zoom.currenty = VGAGL_zoom.starty;
1312
1313             VGAGL_zoombox(VGAGL_zoom.currentx, VGAGL_zoom.currenty);
1314
1315             break;
1316         case 0:  /* standard cross-hair cursor */
1317             if (VGAGL_zoom.startx >= 0) {
1318                 VGAGL_zoombox(VGAGL_zoom.currentx, VGAGL_zoom.currenty);
1319                 VGAGL_zoom.startx = -1; /* turn zoom box off */
1320             }
1321             break;
1322         case 1:  /* cursor during rotation */
1323             /* TODO */
1324             break;
1325         case 2:  /* cursor during scaling */
1326             /* TODO */
1327             break;
1328         case 3:  /* cursor during zooming */
1329             /* TODO */
1330             break;
1331         default:
1332             fprintf(stderr, "(VGAGL_set_cursor) %s:%d protocol error\n", __FILE__, __LINE__);
1333             break;
1334     }
1335     return;
1336 }
1337
1338 TERM_PUBLIC void
1339 VGAGL_set_clipboard(const char s[])
1340 {
1341     (void) s;                   /* avoid -Wunused */
1342     return;                     /* does nothing. */
1343 }
1344
1345 TERM_PUBLIC int
1346 VGAGL_make_palette(t_sm_palette *palette)
1347 {
1348     /* only reallocate colors, if the color spec has changed */
1349     if (palette && (VGAGL_save_pal.colorFormulae < 0
1350             || palette->colorFormulae != VGAGL_save_pal.colorFormulae
1351             || palette->colorMode != VGAGL_save_pal.colorMode
1352             || palette->formulaR != VGAGL_save_pal.formulaR
1353             || palette->formulaG != VGAGL_save_pal.formulaG
1354             || palette->formulaB != VGAGL_save_pal.formulaB
1355             || palette->positive != VGAGL_save_pal.positive)) {
1356         int i, j;
1357 #ifdef VGAGL_ENABLE_TRUECOLOR
1358         switch (VGAGL_truecolor) {
1359             case TRUE:
1360                 for (i = 0; i <= VGAGL_tri_colors; i++) {
1361                     VGAGL_cmap[i] = gl_rgbcolor
1362                         ((int)floor(palette->color[i].r * 255.999),
1363                          (int)floor(palette->color[i].g * 255.999),
1364                          (int)floor(palette->color[i].b * 255.999));
1365                     gl_trisetcolorlookup(i, VGAGL_cmap[i]);
1366                 }
1367                 break;
1368             default:
1369 #endif
1370                 for (j = 0, i = pm3d_color_offset; i <= 0xff; i++, j++) {
1371                     VGAGL_setpalettecolor(i, palette->color[j].r,
1372                         palette->color[j].g, palette->color[j].b);
1373                 }
1374 #ifdef VGAGL_ENABLE_TRUECOLOR
1375         }
1376 #endif
1377         VGAGL_save_pal = *palette;
1378         return 0;
1379     } else {
1380         return VGAGL_pm3d_colors;
1381     }
1382 }
1383
1384 /* set color for subsequent VGAGL_filled_polygon() calls. */
1385 TERM_PUBLIC void
1386 VGAGL_set_color(t_colorspec *colorspec)
1387 {
1388     int color;
1389     double gray = colorspec->value;
1390
1391     if (colorspec->type != TC_FRAC)
1392         return;
1393
1394     /* Note that the gray value is supplied for each vertex.
1395      * This is only for routines which don't draw interpolated
1396      * triangles. These routines should supply a negative
1397      * valued as corners[0].spec.gray, if they really want
1398      * this color to be taken. */
1399     color = (gray <= 0) ? 0 : (int)(gray * VGAGL_pm3d_colors);
1400     if (color >= VGAGL_pm3d_colors)
1401         color = VGAGL_pm3d_colors_;
1402     current_color = pm3d_color_offset + color;
1403     VGAGL_gray = gray;
1404 }
1405
1406 TERM_PUBLIC void
1407 VGAGL_filled_polygon(int points, gpiPoint *corners)
1408 {
1409     int i;
1410     int y[4];
1411     if (4 != points) {
1412         fprintf(stderr, "(VGAGL_filled_polygon) can only plot with 4 points\n");
1413         return;
1414     }
1415     if (!VGAGL_interpolate || corners[0].spec.gray < 0) {
1416         /* draw a solid colored triangle */
1417         int color;
1418         double gray = 0;
1419 #if 0
1420         fprintf(stderr, "(VGAGL_filled_polygon) gray = %f\n",
1421             corners[0].spec.gray);
1422 #endif
1423         if (corners[0].spec.gray < 0) {
1424             for (i = 0; i < 4; i++) {
1425                 y[i] = Y(corners[i].y);
1426             }
1427             gray = VGAGL_gray;
1428         } else {
1429             for (i = 0; i < 4; i++) {
1430                 y[i] = Y(corners[i].y);
1431                 gray += corners[0].spec.gray;
1432             }
1433             gray *= 0.25;
1434         }
1435 #ifdef VGAGL_ENABLE_TRUECOLOR
1436         switch (VGAGL_truecolor) {
1437             case TRUE:
1438                 /* TODO: this does not work */
1439                 color = VGAGL_line_cmap[(int)(gray * VGAGL_pm3d_colors_)];
1440                 break;
1441             default:
1442 #endif
1443                 color = pm3d_color_offset + (int)(gray * VGAGL_pm3d_colors_);
1444 #ifdef VGAGL_ENABLE_TRUECOLOR
1445         }
1446 #endif
1447         gl_striangle(corners[0].x, y[0], corners[1].x, y[1],
1448             corners[2].x, y[2], color, -1);
1449         gl_striangle(corners[2].x, y[2], corners[3].x, y[3],
1450             corners[0].x, y[0], color, -1);
1451     } else {
1452         /* draw color interpolated triangle */
1453         int color[4];
1454 #ifdef VGAGL_ENABLE_TRUECOLOR
1455         switch (VGAGL_truecolor) {
1456             case TRUE:
1457                 for (i = 0; i < 4; i++) {
1458                     y[i] = Y(corners[i].y);
1459                     color[i] = (int)(corners[i].spec.gray * VGAGL_pm3d_colors_);
1460                 }
1461                 break;
1462             default:
1463 #endif
1464                 for (i = 0; i < 4; i++) {
1465                     y[i] = Y(corners[i].y);
1466                     color[i] = pm3d_color_offset + (int)(corners[i].spec.gray * VGAGL_pm3d_colors_);
1467                 }
1468 #ifdef VGAGL_ENABLE_TRUECOLOR
1469         }
1470 #endif
1471         gl_triangle
1472             (corners[0].x, y[0], color[0],
1473              corners[1].x, y[1], color[1],
1474              corners[2].x, y[2], color[2], -1);
1475         gl_triangle
1476             (corners[2].x, y[2], color[2],
1477              corners[3].x, y[3], color[3],
1478              corners[0].x, y[0], color[0], -1);
1479     }
1480 }
1481 #ifdef VGAGL_DEBUGGING
1482 void
1483 VGAGL_write_dump_file()
1484 {
1485     FILE* fp;
1486     unsigned char* buf;
1487     unsigned char* bufptr;
1488     int x, y, index;
1489     char thisfile[0xff];
1490     static int thisfileno = 0;
1491     if (!VGAGL_dump_file) {
1492         return;
1493     }
1494     sprintf(thisfile, "%s%05d.ppm", VGAGL_dump_file, thisfileno++);
1495     fp = fopen(thisfile, "w");
1496     if (!fp) {
1497         free(VGAGL_dump_file);
1498         VGAGL_dump_file = 0;
1499     }
1500     fprintf(fp, "P6\n");
1501     fprintf(fp, "%d %d\n", modeinfo->width, modeinfo->height);
1502     fprintf(fp, "255\n");
1503     buf = gp_alloc(modeinfo->width * modeinfo->height * 3, "vgagl->buf");
1504     bufptr = buf;
1505     for (y = 0; y < modeinfo->height; y++) {
1506         for (x = 0; x < modeinfo->width; x++) {
1507             index = gl_getpixel(x, y);
1508             while (index < 0) {
1509                 /* this is a kludge, as gl_getpixel() seems to
1510                  * return pixels > 128 as the negative complement */
1511                 index += 256;
1512             }
1513             *bufptr++ = VGAGL_palette[index][0];
1514             *bufptr++ = VGAGL_palette[index][1];
1515             *bufptr++ = VGAGL_palette[index][2];
1516         }
1517     }
1518     fwrite(buf, 3, modeinfo->width * modeinfo->height, fp);
1519     fclose(fp);
1520 }
1521 #endif
1522
1523 #undef Y
1524
1525 #endif
1526
1527 #ifdef TERM_TABLE
1528 TERM_TABLE_START(vgagl_driver)
1529     "vgagl", "vgagl driver with mouse support and smooth colors",
1530     VGAGL_XMAX, VGAGL_YMAX, VGAGL_VCHAR, VGAGL_HCHAR,
1531     VGAGL_VTIC, VGAGL_HTIC, VGAGL_options, VGAGL_init, VGAGL_reset,
1532     VGAGL_text, null_scale, VGAGL_graphics, VGAGL_move, VGAGL_vector,
1533     VGAGL_linetype, VGAGL_put_text, VGAGL_text_angle,
1534     null_justify_text, do_point, do_arrow, set_font_null,
1535     0,                          /* pointsize */
1536     TERM_CAN_MULTIPLOT, VGAGL_suspend, VGAGL_resume
1537     , 0, 0 /* fillbox, linewidth */
1538 # ifdef USE_MOUSE
1539     , 0 /* VGAGL_waitforinput */, VGAGL_put_tmptext, VGAGL_set_ruler,
1540     VGAGL_set_cursor, VGAGL_set_clipboard
1541 # endif
1542     , VGAGL_make_palette,
1543     0 /* VGAGL_previous_palette */,
1544     VGAGL_set_color,
1545     VGAGL_filled_polygon
1546 TERM_TABLE_END(vgagl_driver)
1547 #undef LAST_TERM
1548 #define LAST_TERM vgagl_driver
1549 #endif
1550
1551 #ifdef TERM_HELP
1552 START_HELP(vgagl)
1553 "1 vgagl",
1554 "?commands set terminal vgagl",
1555 "?set terminal vgagl",
1556 "?set term vgagl",
1557 "?terminal vgagl",
1558 "?term vgagl",
1559 "?vgagl",
1560 " The `vgagl` driver is a fast linux console driver with full mouse and pm3d",
1561 " support.  It looks at the environment variable SVGALIB_DEFAULT_MODE for the",
1562 " default mode; if not set, it uses a 256 color mode with the highest",
1563 " available resolution.",
1564 "",
1565 " Syntax:",
1566 "    set terminal vgagl \\",
1567 "                 background [red] [[green] [blue]] \\",
1568 "                 [uniform | interpolate] \\",
1569 #if 0
1570 "                 [dump \"file\"] \\",
1571 #endif
1572 "                 [mode]",
1573 "",
1574 " The color mode can also be given with the mode option. Both Symbolic",
1575 " names as G1024x768x256 and integers are allowed. The `background` option",
1576 " takes either one or three integers in the range [0, 255]. If only one",
1577 " integers is supplied, it is taken as gray value for the background.",
1578 " If three integers are present, the background gets the corresponding",
1579 " color.",
1580 " The (mutually exclusive) options `interpolate` and `uniform` control",
1581 " if color interpolation is done while drawing triangles (on by default).",
1582 #if 0
1583 "",
1584 " A `screen dump file` can be specified with the `dump \"file\"` option.",
1585 " If this option is present, (i.e the dump file name is not empty) pressing",
1586 " the key KP_Delete will write the file.  This action cannot and cannot be",
1587 " rebound. The file is written in raw ppm (P6) format. Note that this option",
1588 " is reset each time the `set term` command is issued.",
1589 #endif
1590 "",
1591 " To get high resolution modes, you will probably have to modify the",
1592 " configuration file of libvga, usually /etc/vga/libvga.conf.  Using",
1593 " the VESA fb is a good choice, but this needs to be compiled in the",
1594 " kernel.",
1595 "",
1596 " The vgagl driver uses the first *available* vga mode from the following list:",
1597 "  - the driver which was supplied when setting vgagl, e.g. `set term vgagl",
1598 "    G1024x768x256` would first check, if the G1024x768x256 mode is available.",
1599 "  - the environment variable SVGALIB_DEFAULT_MODE",
1600 "  - G1024x768x256",
1601 "  - G800x600x256",
1602 "  - G640x480x256",
1603 "  - G320x200x256",
1604 "  - G1280x1024x256",
1605 "  - G1152x864x256",
1606 "  - G1360x768x256",
1607 "  - G1600x1200x256",
1608 ""
1609 END_HELP(vgagl)
1610 #endif
1611 #endif /* defined(USE_MOUSE) */