/* Hello, Emacs, this is -*-C-*- * $Id: linux.trm,v 1.31 2012/01/30 19:31:01 sfeam Exp $ * */ /* GNUPLOT - linux.trm */ /*[ * Copyright 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: * SVGA up to 1024x768x256 for PC's running the Linux Operating System * (also VGA 640x480x16, and SVGA 800x600x256) * * AUTHOR * Scott Heavner (sdh@po.cwru.edu) * based on original linux.trm by Tommy Frandsen (frandsen@diku.dk) * patched by David J. Liu (liu@molecule.phri.nyu.edu) * to increase perfomance and safety based on the features of SVGALib/GL. * send your comments or suggestions to (pixar!info-gnuplot@sun.com). */ /* * Compile with Linux SVGAlib 0.95 currently maintained by * Harm Hanemaayer (hhanemaa@cs.ruu.nl). * supports Trident, Tseng, Cirrus, Oak and generic vga. */ #include "driver.h" /* * January 2012 (Gnuplot version 4.6) * This font used to be imported from bitmap.c, which is no longer built * by default. */ #ifndef FNT5X9 #define FNT5X9 0 #define FNT5X9_VCHAR 11 /* vertical spacing between characters */ #define FNT5X9_VBITS 9 /* actual number of rows of bits per char */ #define FNT5X9_HCHAR 7 /* horizontal spacing between characters */ #define FNT5X9_HBITS 5 /* actual number of bits per row per char */ #ifndef TERM_HELP /* 5x9 font, bottom row first, left pixel in lsb */ const unsigned int fnt5x9[96][FNT5X9_VBITS] = { /* */ {000000,000000,000000,000000,000000,000000,000000,000000,000000}, /*!*/ {000000,000000,0x0004,000000,0x0004,0x0004,0x0004,0x0004,0x0004}, /*"*/ {000000,000000,000000,000000,000000,000000,0x000a,0x000a,0x000a}, /*#*/ {000000,000000,0x000a,0x000a,0x001f,0x000a,0x001f,0x000a,0x000a}, /*$*/ {000000,000000,0x0004,0x000f,0x0014,0x000e,0x0005,0x001e,0x0004}, /*%*/ {000000,000000,0x0018,0x0019,0x0002,0x0004,0x0008,0x0013,0x0003}, /*&*/ {000000,000000,0x0016,0x0009,0x0015,0x0002,0x0005,0x0005,0x0002}, /*'*/ {000000,000000,000000,000000,000000,0x0002,0x0004,0x0006,0x0006}, /*(*/ {000000,000000,0x0008,0x0004,0x0002,0x0002,0x0002,0x0004,0x0008}, /*)*/ {000000,000000,0x0002,0x0004,0x0008,0x0008,0x0008,0x0004,0x0002}, /***/ {000000,000000,0x0004,0x0015,0x000e,0x001f,0x000e,0x0015,0x0004}, /*+*/ {000000,000000,000000,0x0004,0x0004,0x001f,0x0004,0x0004,000000}, /*,*/ {000000,0x0002,0x0004,0x0006,0x0006,000000,000000,000000,000000}, /*-*/ {000000,000000,000000,000000,000000,0x001f,000000,000000,000000}, /*.*/ {000000,000000,0x0006,0x0006,000000,000000,000000,000000,000000}, /*-/-*/{000000,000000,000000,0x0001,0x0002,0x0004,0x0008,0x0010,000000}, /*0*/ {000000,000000,0x000e,0x0011,0x0013,0x0015,0x0019,0x0011,0x000e}, /*1*/ {000000,000000,0x000e,0x0004,0x0004,0x0004,0x0004,0x0006,0x0004}, /*2*/ {000000,000000,0x001f,0x0001,0x0001,0x000e,0x0010,0x0011,0x000e}, /*3*/ {000000,000000,0x000e,0x0011,0x0010,0x000c,0x0010,0x0011,0x000e}, /*4*/ {000000,000000,0x0008,0x0008,0x001f,0x0009,0x000a,0x000c,0x0008}, /*5*/ {000000,000000,0x000e,0x0011,0x0010,0x0010,0x000f,0x0001,0x001f}, /*6*/ {000000,000000,0x000e,0x0011,0x0011,0x000f,0x0001,0x0002,0x000c}, /*7*/ {000000,000000,0x0001,0x0001,0x0002,0x0004,0x0008,0x0010,0x001f}, /*8*/ {000000,000000,0x000e,0x0011,0x0011,0x000e,0x0011,0x0011,0x000e}, /*9*/ {000000,000000,0x0006,0x0008,0x0010,0x001e,0x0011,0x0011,0x000e}, /*:*/ {000000,000000,000000,0x0006,0x0006,000000,0x0006,0x0006,000000}, /*;*/ {000000,0x0001,0x0002,0x0006,0x0006,000000,0x0006,0x0006,000000}, /*<*/ {000000,000000,0x0008,0x0004,0x0002,0x0001,0x0002,0x0004,0x0008}, /*=*/ {000000,000000,000000,000000,0x001f,000000,0x001f,000000,000000}, /*>*/ {000000,000000,0x0002,0x0004,0x0008,0x0010,0x0008,0x0004,0x0002}, /*?*/ {000000,000000,0x0004,000000,0x0004,0x0008,0x0010,0x0011,0x000e}, /*@*/ {000000,000000,0x000e,0x0015,0x0015,0x0016,0x0010,0x0011,0x000e}, /*A*/ {000000,000000,0x0011,0x0011,0x001f,0x0011,0x0011,0x000a,0x0004}, /*B*/ {000000,000000,0x000f,0x0012,0x0012,0x000e,0x0012,0x0012,0x000f}, /*C*/ {000000,000000,0x000e,0x0011,0x0001,0x0001,0x0001,0x0011,0x000e}, /*D*/ {000000,000000,0x000f,0x0012,0x0012,0x0012,0x0012,0x0012,0x000f}, /*E*/ {000000,000000,0x001f,0x0001,0x0001,0x0007,0x0001,0x0001,0x001f}, /*F*/ {000000,000000,0x0001,0x0001,0x0001,0x0007,0x0001,0x0001,0x001f}, /*G*/ {000000,000000,0x001e,0x0011,0x0011,0x0019,0x0001,0x0001,0x001e}, /*H*/ {000000,000000,0x0011,0x0011,0x0011,0x001f,0x0011,0x0011,0x0011}, /*I*/ {000000,000000,0x000e,0x0004,0x0004,0x0004,0x0004,0x0004,0x000e}, /*J*/ {000000,000000,0x000e,0x0011,0x0010,0x0010,0x0010,0x0010,0x0010}, /*K*/ {000000,000000,0x0011,0x0009,0x0005,0x0003,0x0005,0x0009,0x0011}, /*L*/ {000000,000000,0x001f,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001}, /*M*/ {000000,000000,0x0011,0x0011,0x0011,0x0015,0x0015,0x001b,0x0011}, /*N*/ {000000,000000,0x0011,0x0011,0x0011,0x0019,0x0015,0x0013,0x0011}, /*O*/ {000000,000000,0x000e,0x0011,0x0011,0x0011,0x0011,0x0011,0x000e}, /*P*/ {000000,000000,0x0001,0x0001,0x0001,0x000f,0x0011,0x0011,0x000f}, /*Q*/ {000000,0x0018,0x000e,0x0015,0x0011,0x0011,0x0011,0x0011,0x000e}, /*R*/ {000000,000000,0x0011,0x0009,0x0005,0x000f,0x0011,0x0011,0x000f}, /*S*/ {000000,000000,0x000e,0x0011,0x0010,0x000e,0x0001,0x0011,0x000e}, /*T*/ {000000,000000,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x001f}, /*U*/ {000000,000000,0x000e,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011}, /*V*/ {000000,000000,0x0004,0x0004,0x000a,0x000a,0x0011,0x0011,0x0011}, /*W*/ {000000,000000,0x0011,0x001b,0x0015,0x0011,0x0011,0x0011,0x0011}, /*X*/ {000000,000000,0x0011,0x0011,0x000a,0x0004,0x000a,0x0011,0x0011}, /*Y*/ {000000,000000,0x0004,0x0004,0x0004,0x0004,0x000a,0x0011,0x0011}, /*Z*/ {000000,000000,0x001f,0x0001,0x0002,0x0004,0x0008,0x0010,0x001f}, /*[*/ {000000,000000,0x000e,0x0002,0x0002,0x0002,0x0002,0x0002,0x000e}, /*\ */ {000000,000000,000000,0x0010,0x0008,0x0004,0x0002,0x0001,000000}, /*]*/ {000000,000000,0x000e,0x0008,0x0008,0x0008,0x0008,0x0008,0x000e}, /*^*/ {000000,000000,000000,000000,000000,000000,0x0011,0x000a,0x0004}, /*_*/ {000000,000000,0x001f,000000,000000,000000,000000,000000,000000}, /*`*/ {000000,000000,000000,000000,000000,0x0008,0x0004,0x000c,0x000c}, /*a*/ {000000,000000,0x001e,0x0011,0x001e,0x0010,0x000e,000000,000000}, /*b*/ {000000,000000,0x000d,0x0013,0x0011,0x0013,0x000d,0x0001,0x0001}, /*c*/ {000000,000000,0x000e,0x0011,0x0001,0x0011,0x000e,000000,000000}, /*d*/ {000000,000000,0x0016,0x0019,0x0011,0x0019,0x0016,0x0010,0x0010}, /*e*/ {000000,000000,0x000e,0x0001,0x001f,0x0011,0x000e,000000,000000}, /*f*/ {000000,000000,0x0004,0x0004,0x0004,0x000e,0x0004,0x0014,0x0008}, /*g*/ {0x000e,0x0011,0x0016,0x0019,0x0011,0x0019,0x0016,000000,000000}, /*h*/ {000000,000000,0x0011,0x0011,0x0011,0x0013,0x000d,0x0001,0x0001}, /*i*/ {000000,000000,0x000e,0x0004,0x0004,0x0004,0x0006,000000,0x0004}, /*j*/ {0x0006,0x0009,0x0008,0x0008,0x0008,0x0008,0x000c,000000,0x0008}, /*k*/ {000000,000000,0x0009,0x0005,0x0003,0x0005,0x0009,0x0001,0x0001}, /*l*/ {000000,000000,0x000e,0x0004,0x0004,0x0004,0x0004,0x0004,0x0006}, /*m*/ {000000,000000,0x0015,0x0015,0x0015,0x0015,0x000b,000000,000000}, /*n*/ {000000,000000,0x0011,0x0011,0x0011,0x0013,0x000d,000000,000000}, /*o*/ {000000,000000,0x000e,0x0011,0x0011,0x0011,0x000e,000000,000000}, /*p*/ {0x0001,0x0001,0x000d,0x0013,0x0011,0x0013,0x000d,000000,000000}, /*q*/ {0x0010,0x0010,0x0016,0x0019,0x0011,0x0019,0x0016,000000,000000}, /*r*/ {000000,000000,0x0001,0x0001,0x0001,0x0013,0x000d,000000,000000}, /*s*/ {000000,000000,0x000f,0x0010,0x000e,0x0001,0x001e,000000,000000}, /*t*/ {000000,000000,0x0008,0x0014,0x0004,0x0004,0x001f,0x0004,0x0004}, /*u*/ {000000,000000,0x0016,0x0019,0x0011,0x0011,0x0011,000000,000000}, /*v*/ {000000,000000,0x0004,0x000a,0x0011,0x0011,0x0011,000000,000000}, /*w*/ {000000,000000,0x000a,0x0015,0x0015,0x0011,0x0011,000000,000000}, /*x*/ {000000,000000,0x0011,0x000a,0x0004,0x000a,0x0011,000000,000000}, /*y*/ {0x000e,0x0010,0x001e,0x0011,0x0011,0x0011,0x0011,000000,000000}, /*z*/ {000000,000000,0x001f,0x0002,0x0004,0x0008,0x001f,000000,000000}, /*{*/ {000000,000000,0x0008,0x0004,0x0004,0x0002,0x0004,0x0004,0x0008}, /*|*/ {000000,000000,0x0004,0x0004,0x0004,000000,0x0004,0x0004,0x0004}, /*}*/ {000000,000000,0x0002,0x0004,0x0004,0x0008,0x0004,0x0004,0x0002}, /*~*/ {000000,000000,000000,000000,000000,000000,0x0008,0x0015,0x0002}, /*DEL*/{000000,000000,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f}, }; #endif /* TERM_HELP */ #endif /* local copy of 5x9 font */ #ifdef TERM_REGISTER register_term(linux) #endif #ifdef TERM_PROTO #define LINUX_VCHAR FNT5X9_VCHAR #define LINUX_HCHAR FNT5X9_HCHAR #define LINUX_VTIC 5 #define LINUX_HTIC 5 #define LINUX_XMAX 0 /* These two entries are just place holders. */ #define LINUX_YMAX 0 /* The actual values will be filled in init. */ TERM_PUBLIC void LINUX_options __PROTO((void)); TERM_PUBLIC void LINUX_init __PROTO((void)); TERM_PUBLIC void LINUX_reset __PROTO((void)); TERM_PUBLIC void LINUX_text __PROTO((void)); TERM_PUBLIC void LINUX_graphics __PROTO((void)); TERM_PUBLIC void LINUX_linetype __PROTO((int linetype)); TERM_PUBLIC void LINUX_move __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC void LINUX_vector __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC int LINUX_text_angle __PROTO((int ang)); TERM_PUBLIC void LINUX_put_text __PROTO((unsigned int x, unsigned int y, const char *str)); TERM_PUBLIC void LINUX_suspend __PROTO((void)); TERM_PUBLIC void LINUX_resume __PROTO((void)); /* also used in vgagl.trm, so export it: */ TERM_PUBLIC int LINUX_graphics_allowed; #endif #ifdef TERM_BODY #define _STRING_H_ #include static int linux_vmode = G1024x768x256; /* default mode */ static int vgacolor[] = { 7, 8, 2, 3, 4, 5, 9, 14, 12, 15, 13, 10, 11, 1, 6 }; static int graphics_on = FALSE; static vga_modeinfo *modeinfo; static int linux_startx, linux_starty, linux_lasty; static int linux_angle; TERM_PUBLIC int LINUX_graphics_allowed = FALSE; /* also used in vgagl.trm */ extern void drop_privilege __PROTO((void)); extern void take_privilege __PROTO((void)); typedef int (*linux_line_func_ptr) __PROTO((int x1, int y1, int x2, int y2)); static void LINUX_putc __PROTO((unsigned int x, unsigned int y, int c, int ang, linux_line_func_ptr line_func)); /* this function is called at the very beginning of main() to initialize * the vgalib and to revoke suid privileges. * /dev/console and /dev/tty\d and /dev/vc/\d are considered graphic terminals, all other * don't support the linux terminal */ void LINUX_setup() { char line[256]; FILE *pipe; LINUX_graphics_allowed = FALSE; if (geteuid() != 0) return; /* if we aren't root, we cannot init graphics */ if ((pipe = popen("/usr/bin/tty", "r")) != NULL) { line[0] = 0; fgets(line, 256, pipe); pclose(pipe); line[strlen(line) - 1] = '\0'; if ( strcmp(line, "/dev/console") == 0 || ( ( strncmp(line, "/dev/tty", 8) == 0 || strncmp(line, "/dev/vc/", 8) == 0 ) && isdigit((unsigned char) line[8])) ) { LINUX_graphics_allowed = TRUE; } else { /* check for socket name as set for example by `screen' */ char* sty = getenv("STY"); if (sty) { int n1, n2; if (3 == sscanf(sty, "%d.tty%d.%s", &n1, &n2, line)) { /* we could check here, if host is the * same as gethostname() returns. */ LINUX_graphics_allowed = TRUE; } } } } if (LINUX_graphics_allowed) { take_privilege(); vga_init(); drop_privilege(); } else { /* err - shouldn't we give up root uid whatever happens ? * or perhaps vga_init() does it ? */ setuid(getuid()); } } TERM_PUBLIC void LINUX_options() { if (!LINUX_graphics_allowed) { int_error(NO_CARET, "Linux terminal driver not available"); } fprintf(stderr, "%s\n", vga_getmodename(linux_vmode)); } TERM_PUBLIC void LINUX_init() { /* vga_init () has been moved to immediately after main () for security */ if (vga_getdefaultmode() != -1) linux_vmode = vga_getdefaultmode(); /* get the default mode from GSVGAMODE, if available */ if (!vga_hasmode(linux_vmode)) linux_vmode = G640x480x16; /* test default mode first */ if (!vga_hasmode(linux_vmode)) { fputs("Error, unable to initiate graphics.\n", stderr); return; } /* this mode is the bottom line */ modeinfo = vga_getmodeinfo(linux_vmode); term->xmax = modeinfo->width; term->ymax = modeinfo->height; linux_lasty = modeinfo->height - 1; } TERM_PUBLIC void LINUX_reset() { if (graphics_on) { vga_setmode(TEXT); graphics_on = FALSE; } } TERM_PUBLIC void LINUX_text() { if (graphics_on) { vga_getch(); vga_setmode(TEXT); graphics_on = FALSE; } } TERM_PUBLIC void LINUX_graphics() { if (!graphics_on) { vga_setmode(linux_vmode); graphics_on = TRUE; } } TERM_PUBLIC void LINUX_suspend() { vga_flip(); } TERM_PUBLIC void LINUX_resume() { vga_flip(); } TERM_PUBLIC void LINUX_linetype(int linetype) { if (linetype < -2) linetype = LT_BLACK; if (linetype >= 13) linetype %= 13; vga_setegacolor(vgacolor[linetype + 2]); } TERM_PUBLIC void LINUX_move(unsigned int x, unsigned int y) { linux_startx = x; linux_starty = y; } TERM_PUBLIC void LINUX_vector(unsigned int x, unsigned int y) { vga_drawline(linux_startx, linux_lasty - linux_starty, x, linux_lasty - y); linux_startx = x; linux_starty = y; } TERM_PUBLIC int LINUX_text_angle(int ang) { linux_angle = (ang ? 1 : 0); return TRUE; } static void LINUX_putc( unsigned int x, unsigned int y, int c, int ang, linux_line_func_ptr line_func) { int i, j, k; unsigned int pixelon; i = (int) (c) - 32; for (j = 0; j < FNT5X9_VBITS; j++) { for (k = 0; k < FNT5X9_HBITS; k++) { pixelon = (((unsigned int) (fnt5x9[i][j])) >> k & 1); if (pixelon) { switch (ang) { case 0: (*line_func) (x + k + 1, y - j, x + k + 1, y - j); break; case 1: (*line_func) (x - j, y - k - 1, x - j, y - k - 1); break; } } } } } TERM_PUBLIC void LINUX_put_text(unsigned int x, unsigned int y, const char *str) { int i; switch (linux_angle) { case 0: y -= LINUX_VCHAR / 2; break; case 1: x += LINUX_VCHAR / 2; break; } for (i = 0; str[i]; i++) { LINUX_putc(x, linux_lasty - y, str[i], linux_angle, vga_drawline); switch (linux_angle) { case 0: x += LINUX_HCHAR; break; case 1: y += LINUX_HCHAR; break; } } } #endif #ifdef TERM_TABLE TERM_TABLE_START(linux_driver) "linux", "Linux PC with (s)vgalib", LINUX_XMAX, LINUX_YMAX, LINUX_VCHAR, LINUX_HCHAR, LINUX_VTIC, LINUX_HTIC, LINUX_options, LINUX_init, LINUX_reset, LINUX_text, null_scale, LINUX_graphics, LINUX_move, LINUX_vector, LINUX_linetype, LINUX_put_text, LINUX_text_angle, null_justify_text, do_point, do_arrow, set_font_null, 0, /* pointsize */ TERM_CAN_MULTIPLOT, LINUX_suspend, LINUX_resume TERM_TABLE_END(linux_driver) #undef LAST_TERM #define LAST_TERM linux_driver #endif #ifdef TERM_HELP START_HELP(linux) "1 linux", "?commands set terminal linux", "?set terminal linux", "?set term linux", "?terminal linux", "?term linux", "?linux", " The `linux` driver has no additional options to specify. It looks at the", " environment variable GSVGAMODE for the default mode; if not set, it uses", " 1024x768x256 as default mode or, if that is not possible, 640x480x16", " (standard VGA)." END_HELP(linux) #endif