/* Hello, Emacs, this is -*-C-*- * $Id: djsvga.trm,v 1.20.2.1 2007/06/04 21:02:36 mikulik Exp $ */ /* GNUPLOT - djsvga.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: * svga * * AUTHORS * Russell Lang * Edzer Pebesma (gnuplot 3.6: new terminal layout, fonts, grx20) * Hans-Bernhard Broeker (several improvements) * * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net). * */ /* HBB: A new version, called grx21a was released recently. To * tell gnuplot you have it, add '-DGRX21' to your compilation flags. * Currently, that only enables the drawing of wide lines. Maybe more * to come. */ #include "driver.h" #ifdef TERM_REGISTER register_term(djsvga) /* no ; */ #endif #ifdef TERM_PROTO #define DJSVGA_XMAX 640 #define DJSVGA_YMAX 480 #define DJSVGA_XLAST (DJSVGA_XMAX - 1) #define DJSVGA_YLAST (DJSVGA_YMAX - 1) #define DJSVGA_VCHAR 16 #define DJSVGA_HCHAR 8 #define DJSVGA_VTIC 4 #define DJSVGA_HTIC 4 TERM_PUBLIC void DJSVGA_init __PROTO((void)); TERM_PUBLIC void DJSVGA_graphics __PROTO((void)); TERM_PUBLIC void DJSVGA_text __PROTO((void)); TERM_PUBLIC void DJSVGA_reset __PROTO((void)); TERM_PUBLIC void DJSVGA_options __PROTO((void)); TERM_PUBLIC void DJSVGA_linetype __PROTO((int linetype)); TERM_PUBLIC void DJSVGA_move __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC void DJSVGA_vector __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC int DJSVGA_angle __PROTO((int ang)); TERM_PUBLIC int DJSVGA_justify_text __PROTO((enum JUSTIFY mode)); TERM_PUBLIC void DJSVGA_put_text __PROTO((unsigned int x, unsigned int y, const char *str)); TERM_PUBLIC int DJSVGA_set_font __PROTO((const char *fontname)); TERM_PUBLIC void DJSVGA_suspend __PROTO((void)); TERM_PUBLIC void DJSVGA_resume __PROTO((void)); /* clear part of multiplot */ TERM_PUBLIC void DJSVGA_fillbox __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height)); TERM_PUBLIC void DJSVGA_linewidth __PROTO((double linewidth)); #define GOT_DJSVGA_PROTO #endif /* TERM_PROTO */ #ifndef TERM_PROTO_ONLY #ifdef TERM_BODY /* SVGA driver using DJGPP */ #if (DJGPP==2) # define GRX20 #endif #ifdef GRX20 /* use grx20.h for DJGPP V1 / GRX V2 combo as well */ # include #else # include #endif #include static int dj_startx, dj_starty; static int dj_xlast, dj_ylast; #define DJNUMCOLOR 15 /* HBB: Let's just use long for GRX1 as well */ static long dj_color; static long svga256color[DJNUMCOLOR] = /* old sequence: {7, 8, 2, 3, 4, 5, 9, 14, 12, 15, 13, 10, 11, 1, 6}; */ { 7 /*black*/, 8 /*grey*/, #if 0 /* prefer dark colors */ 4 /*dark red*/, 2 /*dark green*/, 1 /*dark blue*/, 5 /*dark magenta*/, 3 /*dark cyan*/, 14 /*yellow*/, 15 /*white*/, 12 /*red*/, 9 /*blue*/, 13 /*magenta*/, 10 /*green*/, 11 /*cyan*/, 6 /*brown*/ #else /* prefer light colors */ 12 /*red*/, 10 /*green*/, 9 /*blue*/, 13 /*magenta*/, 11 /*cyan*/, 14 /*yellow*/, 15 /*white*/, 4 /*dark red*/, 1 /*dark blue*/, 5 /*dark magenta*/, 2 /*dark green*/, 3 /*dark cyan*/, 6 /*brown*/ #endif }; static long dj_colors[DJNUMCOLOR]; #ifdef GRX20 /* Save, Restore: for 16 color mode! */ static void *DJSVGA_colorbuf = NULL; #endif static GrTextOption DJSVGA_TextOption; /* HBB: I think we should use GR_NAMEWIDTH (=16), instead of MAX_ID_LEN, * which has nothing to do with GRX at all */ #ifdef GRX20 char DJSVGA_fontname[MAX_ID_LEN + 1] = ""; #else char DJSVGA_fontname[MAX_ID_LEN + 1] = "@:pc8x14.fnt"; /* EGA bios font */ #endif static GrContext *DJSVGA_context = 0; /* save screen for suspend/resume */ static char *dj_textsave = 0; /* for text-screen-saving */ static int dj_cursorx, dj_cursory; static int dj_width, dj_height; #ifdef GRX21 static double dj_linewidth; /* store linewidth assignments here */ #endif TERM_PUBLIC void DJSVGA_options() { if (!END_OF_COMMAND && isstring(c_token)) { quote_str(DJSVGA_fontname, c_token, MAX_ID_LEN); c_token++; } sprintf(term_options, "\"%s\"", DJSVGA_fontname); } TERM_PUBLIC void DJSVGA_init() { int i, on, r, g, b, medium = 170, low = 85; GrFont *font = NULL; #ifdef GRX20 font = &GrDefaultFont; #endif /* HBB: save textscreen contents and cursor-position */ dj_textsave = gp_alloc(ScreenRows() * ScreenCols() * 2, "djsvga term scrbuf"); ScreenRetrieve(dj_textsave); dj_width = ScreenCols(); dj_height = ScreenRows(); ScreenGetCursor(&dj_cursory, &dj_cursorx); GrSetMode(GR_default_graphics); GrSetRGBcolorMode(); GrResetColors(); /* Allocate colors */ for (i = 0; i < DJNUMCOLOR; i++) { on = (svga256color[i] & 8) ? 255 : medium; r = (svga256color[i] & 4) ? on : 0; g = (svga256color[i] & 2) ? on : 0; b = (svga256color[i] & 1) ? on : 0; if (svga256color[i] == 8) r = g = b = low; dj_colors[i] = GrAllocColor(r, g, b); } /* Get the screen size: */ dj_xlast = GrMaxX(); term->xmax = dj_xlast + 1; dj_ylast = GrMaxY(); term->ymax = dj_ylast + 1; /* if GRX 1.x loads an GRX 2.x save'd file: */ if (font == NULL && DJSVGA_fontname[0] == '\0') sprintf(DJSVGA_fontname, "@:pc8x14.fnt"); if (DJSVGA_fontname[0] != '\0') font = GrLoadFont(DJSVGA_fontname); if (font == NULL) font = GrLoadFont("@:pc8x14.fnt"); /* try EGA bios font */ if (font == NULL) font = GrLoadFont("@:pc8x16.fnt"); /* try VGA bios font */ /* * HBB: There are cases when we reach this point with font still NULL, * eg. when the GRXFONT env.variable points to the GRX V1 fonts, but * GRX V2 is used for this program: some fonts will *fail* to load in * that setup (e.g. cour20b)! So IMHO, there should be some error * treatment here..., like int_error("Couldn't load font!"); */ DJSVGA_TextOption.txo_font = font; DJSVGA_TextOption.txo_direct = GR_TEXT_RIGHT; DJSVGA_TextOption.txo_xalign = GR_ALIGN_LEFT; DJSVGA_TextOption.txo_yalign = GR_ALIGN_CENTER; DJSVGA_TextOption.txo_chrtype = GR_BYTE_TEXT; DJSVGA_TextOption.txo_bgcolor.v = GrNOCOLOR; #ifndef GRX20 DJSVGA_TextOption.txo_xmag = 1; DJSVGA_TextOption.txo_ymag = 1; #endif /* HBB: this version should work in all configurations */ term->v_char = font->h.height; term->h_char = font->h.width; #ifdef GRX20 if (DJSVGA_colorbuf == NULL) DJSVGA_colorbuf = (void *) gp_alloc(GrColorSaveBufferSize(), "djsvga term colorbuf"); GrSaveColors(DJSVGA_colorbuf); #endif GrSetMode(GR_default_text); ScreenUpdate(dj_textsave); ScreenSetCursor(dj_cursory, dj_cursorx); } /* * HBB: make these two inline, as they're called by other routines * inside this module, and -finline-functions (normally switched * on by 'gcc -O3') doesn't work for compiling term.c */ __inline__ TERM_PUBLIC void DJSVGA_graphics() { ScreenRetrieve(dj_textsave); /* HBB: save text screen contents */ ScreenGetCursor(&dj_cursory, &dj_cursorx); GrSetMode(GR_default_graphics); #ifdef GRX20 GrRestoreColors(DJSVGA_colorbuf); #endif } __inline__ TERM_PUBLIC void DJSVGA_text() { (void) getkey(); GrSetMode(GR_width_height_text, dj_width, dj_height); ScreenUpdate(dj_textsave); /* HBB: restore text screen */ ScreenSetCursor(dj_cursory, dj_cursorx); } TERM_PUBLIC void DJSVGA_reset() { GrResetColors(); free(dj_textsave); } TERM_PUBLIC void DJSVGA_linetype(int linetype) { if (linetype < -2) linetype = LT_BLACK; if (linetype >= 13) linetype %= 13; /* HBB: set the TextOption color variable right here (faster) */ DJSVGA_TextOption.txo_fgcolor.v = dj_color = dj_colors[linetype + 2]; } TERM_PUBLIC void DJSVGA_move(unsigned int x, unsigned int y) { dj_startx = x; dj_starty = y; } TERM_PUBLIC void DJSVGA_vector(unsigned int x, unsigned int y) { #ifdef GRX21 GrLineOption dj_lineoption = {dj_color, dj_linewidth, 0, ""}; GrCustomLine(dj_startx, dj_ylast - dj_starty, x, dj_ylast - y, &dj_lineoption); #else GrLine(dj_startx, dj_ylast - dj_starty, x, dj_ylast - y, dj_color); #endif dj_startx = x; dj_starty = y; } /* * HBB: IMHO, the previous version was seriously flawed. E.g. * in the termentry, _justify_text was pointing to the * null_justify_text dummy routine, so DJSVGA_justify wasn't * ever called at all. I copied the routines from my (now * otherwise pointless) own private driver, djgrx.trm, to * cure that. */ TERM_PUBLIC int DJSVGA_angle(int ang) { if (ang) { DJSVGA_TextOption.txo_direct = GR_TEXT_UP; } else { DJSVGA_TextOption.txo_direct = GR_TEXT_RIGHT; } return TRUE; } TERM_PUBLIC int DJSVGA_justify_text(enum JUSTIFY mode) { if (DJSVGA_TextOption.txo_direct == GR_TEXT_RIGHT) { DJSVGA_TextOption.txo_yalign = GR_ALIGN_CENTER; switch (mode) { case LEFT: DJSVGA_TextOption.txo_xalign = GR_ALIGN_LEFT; break; case CENTRE: DJSVGA_TextOption.txo_xalign = GR_ALIGN_CENTER; break; case RIGHT: DJSVGA_TextOption.txo_xalign = GR_ALIGN_RIGHT; break; } } else { DJSVGA_TextOption.txo_xalign = GR_ALIGN_CENTER; switch (mode) { case LEFT: DJSVGA_TextOption.txo_yalign = GR_ALIGN_BOTTOM; break; case CENTRE: DJSVGA_TextOption.txo_yalign = GR_ALIGN_CENTER; break; case RIGHT: DJSVGA_TextOption.txo_yalign = GR_ALIGN_TOP; break; } } return TRUE; } TERM_PUBLIC int DJSVGA_set_font(const char *fontname) { char *cp; GrFont *font; if (!fontname || !fontname[0]) return FALSE; safe_strncpy(DJSVGA_fontname, fontname, sizeof(DJSVGA_fontname)); cp = strstr(DJSVGA_fontname, ","); if (cp != NULL) *cp = NUL; font = GrLoadFont(DJSVGA_fontname); /*HBB: if no font found, do *not* report success! */ if (font != NULL) { GrUnloadFont(DJSVGA_TextOption.txo_font); DJSVGA_TextOption.txo_font = font; return TRUE; } else { graph_error("Font not found"); return FALSE; } } TERM_PUBLIC void DJSVGA_put_text(unsigned int x, unsigned int y, const char *str) { /* HBB: why isn't font!=NULL ensured elsewhere? Testing it at * this point doesn't really make much sense (we're in graphics * mode, so we can't even print out a useful error message!) */ /*if (DJSVGA_TextOption.txo_font != NULL) */ GrDrawString(str, strlen(str), x, dj_ylast - y, &DJSVGA_TextOption); } TERM_PUBLIC void DJSVGA_suspend() { DJSVGA_context = GrCreateContext(GrSizeX(), GrSizeY(), 0, 0); GrBitBltNC(DJSVGA_context, 0, 0, 0, 0, 0, GrMaxX(), GrMaxY(), GrWRITE); DJSVGA_text(); } TERM_PUBLIC void DJSVGA_resume() { DJSVGA_graphics(); GrBitBltNC(0, 0, 0, DJSVGA_context, 0, 0, GrMaxX(), GrMaxY(), GrWRITE); GrDestroyContext(DJSVGA_context); } TERM_PUBLIC void DJSVGA_fillbox( int style, unsigned int left, unsigned int bottom, unsigned int width, unsigned height) { if (style >= 13) style %= 13; /* HBB: prize question: should it be 'width-1' instead? */ /* HBB: fill with GRX Color '0', which *should* be black : */ /* ULIG: the style parameter is now used for the fillboxes style */ /* (not implemented here), see the documentation */ GrFilledBox(left, dj_ylast - bottom, left + width, dj_ylast - bottom - height, 0); } TERM_PUBLIC void DJSVGA_linewidth(double linewidth) { #ifdef GRX21 dj_linewidth = linewidth; #endif } #endif /* TERM_BODY */ #ifdef TERM_TABLE /* HBB: I think \" is more readable than \042. BTW: why is this * option 'documented' here, but not in the Help node? */ TERM_TABLE_START(djsvga_driver) "svga", "IBM PC/Clone with Super VGA graphics board [\"fontname\"]", DJSVGA_XMAX, DJSVGA_YMAX, DJSVGA_VCHAR, DJSVGA_HCHAR, DJSVGA_VTIC, DJSVGA_HTIC, DJSVGA_options, DJSVGA_init, DJSVGA_reset, DJSVGA_text, null_scale, DJSVGA_graphics, DJSVGA_move, DJSVGA_vector, DJSVGA_linetype, DJSVGA_put_text, DJSVGA_angle, DJSVGA_justify_text, do_point, do_arrow, DJSVGA_set_font, 0, /* no pointsize() */ TERM_CAN_MULTIPLOT, DJSVGA_suspend, DJSVGA_resume, DJSVGA_fillbox, DJSVGA_linewidth TERM_TABLE_END(djsvga_driver) #undef LAST_TERM #define LAST_TERM djsvga_driver #endif /* TERM_TABLE */ #endif /* TERM_PROTO_ONLY */ /* * HBB: I think this documentation should be at least a *bit* longer * (E.g., the "fontname" parameter is claimed to be non-existent!) */ /* RCC: Not any more... * If you have other ideas about what could be in the help section, * please let me know (rccrawford@lanl.gov) --- particularly info * about what fonts are permitted, if there is such a list. */ #ifdef TERM_HELP START_HELP(svga) "1 svga", "?commands set terminal svga", "?set terminal svga", "?set term svga", "?terminal svga", "?term svga", "?svga", " The `svga` terminal driver supports PCs with SVGA graphics. It can only be", " used if it is compiled with DJGPP. Its only option is the font.", "", " Syntax:", " set terminal svga {\"\"}" END_HELP(svga) #endif /* TERM_HELP */