bcfa39b406ef3c92d2461b2de25a58c94dd8b680
[gnuplot] / term / linux.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: linux.trm,v 1.29 2006/07/21 02:35:47 sfeam Exp $
3  *
4  */
5
6 /* GNUPLOT - linux.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:
42  *  SVGA up to 1024x768x256 for PC's running the Linux Operating System
43  *  (also VGA 640x480x16, and SVGA 800x600x256)
44  *
45  * AUTHOR
46  *  Scott Heavner (sdh@po.cwru.edu)
47  *  based on original linux.trm by Tommy Frandsen (frandsen@diku.dk)
48  *  patched by David J. Liu (liu@molecule.phri.nyu.edu)
49  *  to increase perfomance and safety based on the features of SVGALib/GL.
50  *  send your comments or suggestions to (pixar!info-gnuplot@sun.com).
51  */
52
53 /*
54  * Compile with Linux SVGAlib 0.95 currently maintained by
55  * Harm Hanemaayer (hhanemaa@cs.ruu.nl).
56  * supports Trident, Tseng, Cirrus, Oak and generic vga.
57  */
58
59 #include "driver.h"
60
61 #ifdef TERM_REGISTER
62 register_term(linux)
63 #endif
64
65 #ifdef TERM_PROTO
66
67 #define LINUX_VCHAR FNT5X9_VCHAR
68 #define LINUX_HCHAR FNT5X9_HCHAR
69 #define LINUX_VTIC 5
70 #define LINUX_HTIC 5
71 #define LINUX_XMAX 0            /* These two entries are just place holders. */
72 #define LINUX_YMAX 0            /* The actual values will be filled in init. */
73
74 TERM_PUBLIC void LINUX_options __PROTO((void));
75 TERM_PUBLIC void LINUX_init __PROTO((void));
76 TERM_PUBLIC void LINUX_reset __PROTO((void));
77 TERM_PUBLIC void LINUX_text __PROTO((void));
78 TERM_PUBLIC void LINUX_graphics __PROTO((void));
79 TERM_PUBLIC void LINUX_linetype __PROTO((int linetype));
80 TERM_PUBLIC void LINUX_move __PROTO((unsigned int x, unsigned int y));
81 TERM_PUBLIC void LINUX_vector __PROTO((unsigned int x, unsigned int y));
82 TERM_PUBLIC int LINUX_text_angle __PROTO((int ang));
83 TERM_PUBLIC void LINUX_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
84 TERM_PUBLIC void LINUX_suspend __PROTO((void));
85 TERM_PUBLIC void LINUX_resume __PROTO((void));
86
87 /* also used in vgagl.trm, so export it: */
88 TERM_PUBLIC int LINUX_graphics_allowed;
89
90 #endif
91
92 #ifdef TERM_BODY
93
94 #define _STRING_H_
95 #include <vga.h>
96
97 static int linux_vmode = G1024x768x256;         /* default mode */
98 static int vgacolor[] = { 7, 8, 2, 3, 4, 5, 9, 14, 12, 15, 13, 10, 11, 1, 6 };
99 static int graphics_on = FALSE;
100 static vga_modeinfo *modeinfo;
101 static int linux_startx, linux_starty, linux_lasty;
102 static int linux_angle;
103 TERM_PUBLIC int LINUX_graphics_allowed = FALSE; /* also used in vgagl.trm */
104 extern void drop_privilege __PROTO((void));
105 extern void take_privilege __PROTO((void));
106
107 typedef int (*linux_line_func_ptr) __PROTO((int x1, int y1, int x2, int y2));
108
109 static void LINUX_putc __PROTO((unsigned int x, unsigned int y, int c, int ang,
110                                 linux_line_func_ptr line_func));
111
112 /* this function is called at the very beginning of main() to initialize
113  *  the vgalib and to revoke suid privileges.
114  * /dev/console and /dev/tty\d and /dev/vc/\d are considered graphic terminals, all other
115  * don't support the linux terminal */
116
117 void
118 LINUX_setup()
119 {
120     char line[256];
121     FILE *pipe;
122
123     LINUX_graphics_allowed = FALSE;
124
125     if (geteuid() != 0)
126         return;                 /* if we aren't root, we cannot init graphics */
127
128     if ((pipe = popen("/usr/bin/tty", "r")) != NULL) {
129         line[0] = 0;
130         fgets(line, 256, pipe);
131         pclose(pipe);
132         line[strlen(line) - 1] = '\0';
133         if (
134             strcmp(line, "/dev/console") == 0 ||
135
136             ( ( strncmp(line, "/dev/tty", 8) == 0 || strncmp(line, "/dev/vc/", 8) == 0 )
137              && isdigit((unsigned char) line[8]))
138
139              ) {
140             LINUX_graphics_allowed = TRUE;
141         } else {
142             /* check for socket name as set for example by `screen' */
143             char* sty = getenv("STY");
144             if (sty) {
145                 int n1, n2;
146                 if (3 == sscanf(sty, "%d.tty%d.%s", &n1, &n2, line)) {
147                     /* we could check here, if host is the
148                      * same as gethostname() returns. */
149                     LINUX_graphics_allowed = TRUE;
150                 }
151             }
152         }
153     }
154     if (LINUX_graphics_allowed) {
155         take_privilege();
156         vga_init();
157         drop_privilege();
158     } else {
159         /* err - shouldn't we give up root uid whatever happens ?
160          * or perhaps vga_init() does it ?
161          */
162         setuid(getuid());
163     }
164 }
165
166 TERM_PUBLIC
167 void LINUX_options()
168 {
169     if (!LINUX_graphics_allowed) {
170         int_error(NO_CARET, "Linux terminal driver not available");
171     }
172     fprintf(stderr, "%s\n", vga_getmodename(linux_vmode));
173 }
174
175 TERM_PUBLIC
176 void LINUX_init()
177 {
178     /* vga_init () has been moved to immediately after main () for security */
179     if (vga_getdefaultmode() != -1)
180         linux_vmode = vga_getdefaultmode();
181     /* get the default mode from GSVGAMODE, if available */
182     if (!vga_hasmode(linux_vmode))
183         linux_vmode = G640x480x16;
184     /* test default mode first */
185     if (!vga_hasmode(linux_vmode)) {
186         fputs("Error, unable to initiate graphics.\n", stderr);
187         return;
188     }                           /* this mode is the bottom line */
189     modeinfo = vga_getmodeinfo(linux_vmode);
190     term->xmax = modeinfo->width;
191     term->ymax = modeinfo->height;
192     linux_lasty = modeinfo->height - 1;
193 }
194
195 TERM_PUBLIC void
196 LINUX_reset()
197 {
198     if (graphics_on) {
199         vga_setmode(TEXT);
200         graphics_on = FALSE;
201     }
202 }
203
204 TERM_PUBLIC void
205 LINUX_text()
206 {
207     if (graphics_on) {
208         vga_getch();
209         vga_setmode(TEXT);
210         graphics_on = FALSE;
211     }
212 }
213
214 TERM_PUBLIC void
215 LINUX_graphics()
216 {
217     if (!graphics_on) {
218         vga_setmode(linux_vmode);
219         graphics_on = TRUE;
220     }
221 }
222
223 TERM_PUBLIC void
224 LINUX_suspend()
225 {
226     vga_flip();
227 }
228
229 TERM_PUBLIC void
230 LINUX_resume()
231 {
232     vga_flip();
233 }
234
235 TERM_PUBLIC void
236 LINUX_linetype(int linetype)
237 {
238     if (linetype < -2)
239         linetype = LT_BLACK;
240     if (linetype >= 13)
241         linetype %= 13;
242     vga_setcolor(vgacolor[linetype + 2]);
243 }
244
245 TERM_PUBLIC void
246 LINUX_move(unsigned int x, unsigned int y)
247 {
248     linux_startx = x;
249     linux_starty = y;
250 }
251
252 TERM_PUBLIC void
253 LINUX_vector(unsigned int x, unsigned int y)
254 {
255     vga_drawline(linux_startx, linux_lasty - linux_starty, x, linux_lasty - y);
256     linux_startx = x;
257     linux_starty = y;
258 }
259
260 TERM_PUBLIC int
261 LINUX_text_angle(int ang)
262 {
263     linux_angle = (ang ? 1 : 0);
264     return TRUE;
265 }
266
267 static void
268 LINUX_putc(
269     unsigned int x, unsigned int y,
270     int c,
271     int ang,
272     linux_line_func_ptr line_func)
273 {
274     int i, j, k;
275     unsigned int pixelon;
276
277     i = (int) (c) - 32;
278     for (j = 0; j < FNT5X9_VBITS; j++) {
279         for (k = 0; k < FNT5X9_HBITS; k++) {
280             pixelon = (((unsigned int) (fnt5x9[i][j])) >> k & 1);
281             if (pixelon) {
282                 switch (ang) {
283                 case 0:
284                     (*line_func) (x + k + 1, y - j, x + k + 1, y - j);
285                     break;
286                 case 1:
287                     (*line_func) (x - j, y - k - 1, x - j, y - k - 1);
288                     break;
289                 }
290             }
291         }
292     }
293 }
294
295 TERM_PUBLIC void
296 LINUX_put_text(unsigned int x, unsigned int y, const char *str)
297 {
298     int i;
299     switch (linux_angle) {
300     case 0:
301         y -= LINUX_VCHAR / 2;
302         break;
303     case 1:
304         x += LINUX_VCHAR / 2;
305         break;
306     }
307     for (i = 0; str[i]; i++) {
308         LINUX_putc(x, linux_lasty - y, str[i], linux_angle, vga_drawline);
309         switch (linux_angle) {
310         case 0:
311             x += LINUX_HCHAR;
312             break;
313         case 1:
314             y += LINUX_HCHAR;
315             break;
316         }
317     }
318 }
319
320 #endif
321
322 #ifdef TERM_TABLE
323 TERM_TABLE_START(linux_driver)
324     "linux", "Linux PC with (s)vgalib",
325     LINUX_XMAX, LINUX_YMAX, LINUX_VCHAR, LINUX_HCHAR,
326     LINUX_VTIC, LINUX_HTIC, LINUX_options, LINUX_init, LINUX_reset,
327     LINUX_text, null_scale, LINUX_graphics, LINUX_move, LINUX_vector,
328     LINUX_linetype, LINUX_put_text, LINUX_text_angle,
329     null_justify_text, do_point, do_arrow, set_font_null,
330     0,                          /* pointsize */
331     TERM_CAN_MULTIPLOT, LINUX_suspend, LINUX_resume
332 TERM_TABLE_END(linux_driver)
333 #undef LAST_TERM
334 #define LAST_TERM linux_driver
335 #endif
336
337 #ifdef TERM_HELP
338 START_HELP(linux)
339 "1 linux",
340 "?commands set terminal linux",
341 "?set terminal linux",
342 "?set term linux",
343 "?terminal linux",
344 "?term linux",
345 "?linux",
346 " The `linux` driver has no additional options to specify.  It looks at the",
347 " environment variable GSVGAMODE for the default mode; if not set, it uses",
348 " 1024x768x256 as default mode or, if that is not possible, 640x480x16",
349 " (standard VGA)."
350 END_HELP(linux)
351 #endif