/* This is a Small GKS Graphics Library which supports the following platforms: 1. Borland's C++ (tcc/bcc) version 3.0/4.5 Compiler running under DOS with an EGAVGA (or IBM8514) display. Note that you have two choices: 1a. Compile (with BGIOBJ.EXE) the video drivers (EGAVGA.BGI (or IBM8514.BGI)) and (with TLIB) add them to Borland's GRAPHICS.LIB (this has known bugs with Borland C++ version 4.5 and IBM8514). 1b. Edit BGI_PATH to reflect your situation and load BGI-drivers on demand. Makefiles: makefile.bcc Defines: defined(TURBEAUX) 2. Microsoft's C (cl) version 6.0/7.0 or Visual C++ Compiler version 1.5/2.0 running under DOS with an EGAVGA (or SVGA/VESA) display. Makefiles: makefile.c70 Makefiles: makefile.msv Defines: defined(MSDOS) 3. D.J. Delorie's 32-bit VCPI port of the GCC Compiler with DESQview/X's DVX-Libraries for running under DESQview/X (both X-Server and X-Client). Makefiles: makefile.dsq Defines: defined(DESQ) 4. D.J. Delorie's 32-bit DPMI-port of the GCC Compiler with Borland graphics translation library BCC2GRX -> GRX so that we can define "TURBEAUX" and reuse almost all of the Borland code! Makefiles: makefile.gcc Defines: defined(TURBEAUX) && undefined(MSDOS) 5. Any Color Unix Workstation with X11 (R.4.0/5.0/6.0) and an ANSI cc compiler (or use gcc). Makefiles: makefile.unx Defines: defined(DESQ) Hopefully, the code will be useful to students for comparison between PC's and the XLib on an X-Workstation. Files in this distribution needed for GKS build: xgks.c source for GKS-GRAPHICS library xstate.c common module for both GKS-GRAPHICS and GKS-VIRTUAL xstate.h header file for xstate.c raster.h string, stroke character def's Files in this distribution useful for GKS programs proto.h prototypes for routines in the GKS library xgks.h useful define's for GKS values, contants, etc. Marc Thomas Organization is as follows: ----------------------------------------------------- | Virtual Device Layer with GKS Primitives | | reportstatus() | | initvdi() | | setcliprect() | | gbeginframe() | | gpolyline() | | gmove() | | gdraw() | | gpolymarker() | | gmark() | | gtext() | | gappendtext() | | garc() | | gellipse() | | grectangle() | | gpolygon() | | reqstring() | | reqlocator() | | reqvaluator() | | ... | | begindialog() | | enddialog() | | ... | | gendframe() | | closevdi() | ----------------------------------------------------- | Public Pixel-Dependent Functions | | with Some Blocks of Conditional Code | | xabspix() | | yabspix() | | ... | | stcursavearea() | | stviscursor() | | set_defaults() | ----------------------------------------------------- | Private Pixel-Dependent Functions | | with Considerable Blocks of Conditional Code | | init_adapter() | | ... | | rest_adapter() | ----------------------------------------------------- | Borland/Microsoft | | | GRAPHICS.LIB | | --------------------------| XLIB | | [S]VGA Video Adapter | | | | | ----------------------------------------------------- | Network -------------------------- | | | X-Server on X-WkStation | | | -------------------------- Of course, the X-Server could be running on the SAME workstation or on a DIFFERENT workstation. */ #include /* Standard INCLUDEs */ #include #include /* for ANSI C */ #include #include "xstate.h" /* ABSOLUTE defines */ #define PUBLIC #define PRIVATE static /* C has strange default of PUBLIC */ /* Set up Conditional FLAGS ----------------------------------------------- | DESQ X-Workstation | | TURBEAUX Borland C++ (versions 2.0 and 3.0) | | MSDOS Microsoft C (versions 7.0 and Visual C++) | | */ #if defined(_DJGPP) /* DJGPP with BCC2GRX */ #undef MSDOS #define TURBEAUX 0 /* BGI-fonts only */ #define BGI_PATH "d:\\bc\\bgi" #elif defined(DESQ) #elif defined(MSDOS) /* Microsoft C++ */ #else /* Borland C++ */ #define TURBEAUX 0 /* you MUST edit BGI_PATH */ #define BGI_PATH "e:\\bc45\\bgi" #endif /* Re Borland: If you do NOT have an 8514-Compatible display you should define NO_8514 in your Makefile */ #if defined(TURBEAUX) && defined(NO_8514) #define HANDLE_8514 #elif defined(TURBEAUX) && !defined(_DJGPP) #define HANDLE_8514 gdriver = IBM8514; \ gmode = IBM8514HI; \ strcpy(chrline, BGI_PATH); \ goto tryspecific; /* *** OLD (if you LINK-IN BGI-OBJ to GRAPHICS.LIB) *** #define HANDLE_8514 ret=registerbgidriver(IBM8514_driver); \ if (ret >= 0) \ { printf( \ "IBM8514_driver found. Enter [y] for 8514, [n] for VGA "); \ gets(chrline); \ if (chrline[0] == 'y') \ { gdriver = IBM8514; gmode = IBM8514HI; \ chrline[0] = '\0'; goto tryspecific; } } */ /* Re Microsoft: set _TRY_256COLOR if you have an SVGA display. Look at Microsoft's literature BEFORE you set _TRY_1024X768 */ #elif defined(MSDOS) /* *** NESTED *** */ #if defined(_TRY_256COLOR) #define HANDLE_XRES screencode = _XRES256COLOR; \ ret = _setvideomode(_XRES256COLOR); \ if (ret) { \ _setvideomode(_DEFAULTMODE); \ printf( \ "XRES256COLOR found. Enter [y] for XRES, [n] for SVGA "); \ fflush(stdout); \ gets(chrline); \ if (chrline[0] != 'y') ret = 0; \ else ret = _setvideomode(_XRES256COLOR); } \ else { \ screencode = _XRES16COLOR; \ ret = _setvideomode(_XRES16COLOR); \ if (ret) { \ _setvideomode(_DEFAULTMODE); \ printf( \ "XRES16COLOR found. Enter [y] for XRES, [n] for SVGA "); \ fflush(stdout); \ gets(chrline); \ if (chrline[0] != 'y') ret = 0; \ else ret = _setvideomode(_XRES16COLOR); } } #else #define HANDLE_XRES screencode = _XRES16COLOR; \ ret = _setvideomode(_XRES16COLOR); \ if (ret) { \ _setvideomode(_DEFAULTMODE); \ printf( \ "XRES16COLOR found. Enter [y] for XRES, [n] for SVGA "); \ fflush(stdout); \ gets(chrline); \ if (chrline[0] != 'y') ret = 0; \ else ret = _setvideomode(_XRES16COLOR); } #endif /* ... of NEST */ #endif /* | | ------------------------------------------------------------------------- */ /* GENERAL Conditional INCLUDEs in order to make Borland C++, Microsoft C,- | and DESQview/X11 code more compatible: | | | | CONDITIONAL INCLUDES/DEFINES: YES | | */ #if defined(DESQ) /* X-Workstation */ #include #include #include #include #else /* Borland C++, Microsoft C */ #include /* needed for bios_key() */ #include /* needed for reqstring() */ #endif #if defined(DESQ) /* X-Workstation */ #elif defined(_DJGPP) /* DJGPP with BCC2GRX */ #include #include #define FL_DEPTH 500 /* aux_flood_fill max stack depth */ unsigned _stklen = 1048576; /* DJGPP needs LOTS of space; You may need a 1MB stack for vquicksort() in ximage.c */ #elif defined(TURBEAUX) && !defined(_DJGPP) /* handle Borland/Microsoft differences with regard to malloc() and the STACK */ #include #include /* Borland handles the STACK with a global variable rather than a LINKER option */ #define FL_DEPTH 500 /* aux_flood_fill max stack depth */ extern unsigned _stklen = 0xC000; /* do NOT reduce this without reducing FL_DEPTH also */ #include /* TURBEAUX graphics header for Borland's GRAPHICS.LIB: initgraph() moveto() closegraph() lineto() putpixel() cleardevice() getcolor() setlinestyle() imagesize() setrgbpalette() getimage() rectangle() putimage() ellipse() setcolor() arc() getpixel() floodfill() setviewport() setfillpattern() fillpoly() fillellipse() getpalette() sector() setwritemode() setpalette() */ #else /* Microsoft C */ #include #include /* for int86() */ #endif /* | | -------------------------------------------------------------------------- */ /* EVENT-TYPE GLOBALS ------------------------------------------------------ | | | CONDITIONAL DEFINES: NO | | */ #define SAMPLE_INPUT 0 #define REQUEST_INPUT 1 #define AWAIT_INPUT_EVENT 2 #define MOUSE_MOTION 0x0100 #define MOUSE_UPDATE 0x0200 #define SUPPRESS_KEYRELEASE 0x0400 /* | | -------------------------------------------------------------------------- */ /* X-GKS GLOBALS SPECIFICALLY required for XLib -> GKS --------------------- | | | CONDITIONAL DEFINES: YES | | */ #if defined(DESQ) #define GKS_HELLO "GKS X-Window" /* Title of GKS Window */ #define _XDISPLAY 100 #define BUTTON_LEFT 1 #define BUTTON_MIDDLE 2 #define BUTTON_RIGHT 3 #define DEF_BORDER_WIDTH 4 /* *** NESTED *** */ #if defined(_TRY_1024X768) #define DEF_WINDOW_WIDTH 1024 #define DEF_WINDOW_HEIGHT 768 #elif defined(_TRY_1000X750) /* XGetImage() sometimes gives problems on PC when using FULL screen */ #define DEF_WINDOW_WIDTH 1000 #define DEF_WINDOW_HEIGHT 750 #else /* problem with Linux #define DEF_WINDOW_WIDTH 800 #define DEF_WINDOW_HEIGHT 600 */ #define DEF_WINDOW_WIDTH 784 #define DEF_WINDOW_HEIGHT 588 #endif /* ... of NEST */ /* First try: */ #define DEF_GKS_FONT1 "-*-courier-medium-r-normal-*-*-120-*-*-*-*-*-*" #define DEF_GKS_FONT2 "7x13" /* Second try: */ #define DEF_GKS_FONT3 "fixed" /* Third try: generic fixed */ #define DEF_ALIGN_FONT 0 /* no corrections needed now */ /* If your system does NOT support SCALABLE fonts, the larger sizes below will FAIL and you will get size 120 */ static char *namefonts[10] = { DEF_GKS_FONT1, "-*-courier-medium-r-normal-*-*-240-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-360-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-480-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-600-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-720-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-840-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-960-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-960-*-*-*-*-*-*", "-*-courier-medium-r-normal-*-*-960-*-*-*-*-*-*"}; /* All Parameters following are SET by init_adapter() */ Font szfont[10]; /* other font ID's for text sizes */ XFontStruct *szfontpointer[10]; XFontStruct *deffontpointer;/* DEFAULT used for base size */ Font deffont; /* (10) and for text input */ Display *gksdisplay; /* our X-server's display */ Window gkswindow; /* our GKS window */ /* XIMAGES are used for the CHOICE menu. Fullscreen ones are SLOW (we previously used them for large cursors). */ XImage *gksimage; /* fullscreen: (slow!) */ int imagevalid = 0; /* set when gksimage is valid ptr */ int image_x = DEF_WINDOW_WIDTH; int image_y = DEF_WINDOW_HEIGHT; XImage *cursaveimage; /* cursor_save_area: stviscursor() */ int cursaveimagevalid = 0; XImage *choiceimage; /* choice_window: reqchoice() */ int choiceimagevalid = 0; GC gksGC; /* our Graphics Context */ GC tempGC; /* temp Graphics Context */ int gksscreen; /* our screen on the display */ unsigned long gksfore; /* foreground */ unsigned long gksback; /* background */ XSizeHints gkshint; /* size hint struct for GKS window */ XEvent gksevent; /* an X-type event */ KeySym gkskey; /* for a key pressed event */ Cursor gkscurs; /* crosshair cursor for locator */ int gkscurs_exist = 0; /* has this been created ? */ Cursor arrcurs; /* normal arrow cursor for X */ int arrcurs_exist = 0; /* has this been created ? */ Cursor waitcurs; /* watch for BUSY */ int waitcurs_exist = 0; /* has this been created ? */ Pixmap smcrossbmp; /* bitmap from data */ Cursor smcrosscurs; /* associated cursor */ int smcross_exist = 0; /* has this been created ? */ /* There is always a problem with color on multiple application systems. There are three common choices, namely StaticColor, PsuedoColor, and DirectColor: StaticColor is the SAFEST and will ensure that one application won't clobber another application's colors, however, the round-off errors in read only color cells can be SUBSTANTIAL and the X-Server may be reticent to let you Free and ReUse the pixel indexes since the color cells themselves are public and may be in-use. PsuedoColor allows one to dynamically change shades with fine control at the expense of having some inactive applications show TEMPORARILY inaccurate shades. In essence, the pixel index is simply a lookup into an RGB table. The third, DirectColor is ONLY for displays which have RGB SubGroupings of bit planes (e.g. a 24-bit plane with 8-bit RGB SubPlanes) */ Colormap xcolor_map; /* Our color map ID */ static char *namecolors[MAXCOLORZ] = { "black", "NavyBlue", "red", "dark violet", "green", "LightSeaGreen", "yellow", "white", "orange", "PaleGreen", "cyan", "SlateBlue", "magenta", "salmon", "DimGrey", "LightGrey"}; /* named colors ONLY for insurance */ unsigned long pseudo_index[MAXCOLORZ]; unsigned long pseudo_mask_dummy[MAXPLANES]; XColor gks_exactcolors[MAXCOLORZ]; /* exact, requested colors */ XColor gkscolors[MAXCOLORZ]; /* actual, hardware rounded-off, color array of following structure: typedef struct _XColor { unsigned long pixel; this is the INTERNAL index from 0 -- 15, gkscolors[index].pixel = pseudo_index[index] unsigned short red, green, blue; char flags; do_red, do_green, do_blue char pad; } XColor; */ struct _x99base { int last99red; int last99green; int last99blue; }; extern struct _x99base enq99rgb[]; /* now in xstate.c */ XRectangle gkscliprect[16]; /* our array of clip rectangles */ /* our Dash Lists: */ char sd_dashed[8] = {3,1,3,1,3,1,3,1}; char sd_dotted[8] = {1,1,1,1,1,1,1,1}; char sd_dotdash[8] = {4,1,2,1,4,1,2,1}; /* Some Bitmap variables for Hatching: */ Pixmap hatchbmp[8]; /* htable[] converted to (monochrome) Bitmaps */ int hatch_exist = 0; /* Some Pixmap variables: Note that Patterns (or Tiles, as they are called in X) are very flexible. However, we only use a FRACTION of this capability because we are also trying to maintain compatibility with the very limited way Borland C++ and Microsoft C handle patterns (i.e. as an 8 by 8 array ptable[] of VGA indices). */ Pixmap pattbmp[MAXCOLORZ]; /* For each colorindex, this is the current fillpattern ptable[] converted to a (monochrome) Bitmap. It is used only as a mask. */ Pixmap pattpixmap[MAXCOLORZ]; /* For each colorindex, this is a 2-color, 4-plane Pixmap made from ptable[]. */ Pixmap tilepixmap; /* This 16-color Pixmap contains the current fillpattern infomation in X-Format. It is built from pattpixmap[]'s using pattbmp[]'s as masks. In contrast, Borland C++/Microsoft C, use the 8 by 8 pattern VGA indices stored in ptable[] directly. */ int patt_exist = 0; /* Some data for Cursor Bitmaps: */ /* for XDK, Visual C++ V5.0 only */ #pragma warning( disable : 4305 ) #define smcross_width 16 #define smcross_height 16 static char smcross_bits[] = { 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; XGCValues xgcattr, temp_xgcattr; /* used by init_adapter(), there are LOTS of attributes, as defined in Xlib.h: typedef struct { int function; logical operation unsigned long plane_mask; plane mask unsigned long foreground; foreground pixel unsigned long background; background pixel int line_width; line width int line_style; LineSolid, LineOnOffDash, LineDoubleDash int cap_style; CapNotLast, CapButt, CapRound, CapProjecting int join_style; JoinMiter, JoinRound, JoinBevel int fill_style; FillSolid, FillTiled, FillStippled, FillOpaeueStippled int fill_rule; EvenOddRule, WindingRule int arc_mode; ArcChord, ArcPieSlice Pixmap tile; tile pixmap for tiling operations Pixmap stipple; stipple 1 plane pixmap for stipping int ts_x_origin; offset for tile or stipple operations int ts_y_origin; Font font; default text font for text operations int subwindow_mode; ClipByChildren, IncludeInferiors Bool graphics_exposures;boolean, should exposures be generated int clip_x_origin; origin for clipping int clip_y_origin; Pixmap clip_mask; bitmap clipping; other calls for rects int dash_offset; patterned/dashed line information char dashes; } XGCValues; */ XSetWindowAttributes xswinattr; /* used with XCreateWindow() only */ XWindowAttributes xwinattr; /* used by gbeginframe() and init_adapter(), there are LOTS of attributes, as defined in Xlib.h: typedef struct _XWindowAttributes { int x, y; location of window int width, height; width and height of window int border_width; border width of window int depth; depth of window Visual *visual; the associated visual structure Window root; root of screen containing window #if defined(__cplusplus) || defined(c_plusplus) int c_class; C++ InputOutput, InputOnly #else int class; InputOutput, InputOnly #endif int bit_gravity; one of bit gravity values int win_gravity; one of the window gravity values int backing_store; NotUseful, WhenMapped, Always unsigned long backing_planes; planes to be preserved if possible unsigned long backing_pixel; value to be used when restoring planes Bool save_under; boolean, should bits under be saved? Colormap colormap; color map to be associated with window Bool map_installed; boolean, is color map currently installed int map_state; IsUnmapped, IsUnviewable, IsViewable long all_event_masks; set of events all people have interest in long your_event_mask; my event mask long do_not_propagate_mask; set of events that should not propagate Bool override_redirect; boolean value for override-redirect Screen *screen; back pointer to correct screen } XWindowAttributes; */ #else #define DEF_WINDOW_WIDTH 800 #define DEF_WINDOW_HEIGHT 600 #endif /* | | ------------------------------------------------------------------------- */ #include "gksstart.h" /* (Finally) this includes the startup structure and the cmdline parser: cmdline_startup() */ /* GENERAL Conditional DEFINEs in order to make Borland C++, Microsoft C,-- | and DESQview/X Graphics Calls more COMPATIBLE: | | | | CONDITIONAL DEFINES: YES | | */ #if defined(DESQ) /* X-Workstation */ /* arguments to _setvideomode() from Microsoft graph.h */ #define _DEFAULTMODE (-1) /* restore screen original mode */ #define _HRESBW 6 /* 640 x 200, BW */ #define _HRES16COLOR 14 /* 640 x 200, 16 color */ #define _ERESCOLOR 16 /* 640 x 350, 4 or 16 color */ #define _VRES16COLOR 18 /* 640 x 480, 16 color */ #define _8514COLOR 25 /* 1024 x 768, 256 color */ #define _ORES256COLOR 0x0100 /* 640 x 400, 256 color */ #define _VRES256COLOR 0x0101 /* 640 x 480, 256 color */ #define _SRES16COLOR 0x0102 /* 800 x 600, 16 color */ #define _SRES256COLOR 0x0103 /* 800 x 600, 256 color */ #define _XRES16COLOR 0x0104 /* 1024 x 768, 16 color */ #define _XRES256COLOR 0x0105 /* 1024 x 768, 256 color */ #define _ZRES16COLOR 0x0106 /* 1280 x 1024, 16 color */ #define _ZRES256COLOR 0x0107 /* 1280 x 1024, 256 color */ /* try to use C pre-processor, if possible, to redefine to XLib */ #define CLEARSCREEN(a) XClearWindow(gksdisplay, gkswindow) #define MOVETO(a,b) {xpixlast = a; ypixlast = b;} #define LINETO(a,b) XDrawLine(gksdisplay, gkswindow, gksGC, \ xpixlast, ypixlast, a, b); xpixlast = a; ypixlast = b #define XOVRSTRING(a,b,c) XDrawString(gksdisplay, gkswindow, \ gksGC, a, b, c, strlen(c)) #define XREPSTRING(a,b,c) XDrawImageString(gksdisplay, gkswindow, \ gksGC, a, b, c, strlen(c)) /* XLib Arc uses: ul_x, ul_y, width, height, angle_from*64, angle_extent*64 */ /* Arc Params (not all used) are: u = ul_x, y = ul_y, l= lr_x, m = lr_y, b = center_x, center_y, h = half_x, k = half_y, o = x3, p = y3, q = x4, r = y4, f = from, t = to */ #define ARC(u,v,l,m,b,c,h,k,o,p,q,r,f,t) XDrawArc(gksdisplay, \ gkswindow, gksGC, u, v, 2*h, 2*k, f*64, ((t) - (f))*64 ) /* X11 has the PECULIAR FEATURE that the FILL commands draw an outfile which is ONE PIXEL SHORTER in width and height that the DRAW commands */ #define FILLARC(u,v,l,m,b,c,h,k,o,p,q,r,f,t) XFillArc(gksdisplay, \ gkswindow, gksGC, u, v, 2*h + 1, 2*k + 1, f*64, ((t) - (f))*64 ) /* Ellipse Params (not all used) are: u = ul_x, v = ul_y, l = lr_x, m = lr_y, b = center_x, c = center_y, h = half_x, k = half_y, f = 0, t = 360 */ #define ELLIPSE(u,v,l,m,b,c,h,k,f,t) XDrawArc(gksdisplay, gkswindow, \ gksGC, u, v, 2*h, 2*k, f*64, ((t) - (f))*64 ) /* X11 has the PECULIAR FEATURE that the FILL commands draw an outfile which is ONE PIXEL SHORTER in width and height that the DRAW commands */ #define FILLELLIPSE(u,v,l,m,b,c,h,k,f,t) XFillArc(gksdisplay, gkswindow, \ gksGC, u, v, 2*h + 1, 2*k + 1, f*64, ((t) - (f))*64 ) /* XLib Polygon allows "Convex" option in order to speed up performance */ #define XPOLYLINE(a,b) XDrawLines(gksdisplay, gkswindow, gksGC, \ a, b, CoordModeOrigin) #define FILLPOLY(a,b) XFillPolygon(gksdisplay, gkswindow, gksGC, \ a, b, Convex, CoordModeOrigin) /* XLib Rectangle uses: ul_x, ul_y, width, height we translate from: ul_x, ul_y, ll_x, ll_y */ #define RECTANGLE(z,a,b,c,d) XDrawRectangle(gksdisplay, gkswindow, \ gksGC, a, b, (c) - (a), (d) - (b)) /* X11 has the PECULIAR FEATURE that the FILL commands draw an outfile which is ONE PIXEL SHORTER in width and height that the DRAW commands */ #define FILLRECTANGLE(a,b,c,d) XFillRectangle(gksdisplay, gkswindow, \ gksGC, a, b, (c) - (a) + 1, (d) - (b) + 1) /* We no longer ALTERNATE BlackPixel/WhitePixel for MONOCHROME indices. Now ALL non-zero MONOCHROME indices are mapped to WhitePixel #define COLINDEX(a) ((unsigned)a % colorindices) */ #define COLINDEX(a) ((unsigned)a) #define SETCOLOR(a) XSetForeground(gksdisplay, gksGC, gkscolors[ a ].pixel) /* X11 has another HARDware (squared?) layer of abstraction: i -> vdi_index -> pseudo_index[vdi_index] */ #define SET_HARD_COLOR(a) \ XSetForeground(gksdisplay, gksGC, (unsigned long)a) #define SETPIXEL(a,b) XDrawPoint(gksdisplay, gkswindow, gksGC, a, b) /* default is Width=0 (unspecified for X-Workstation) */ #define LINE_SOLID LineSolid #define LINE_DASHED LineOnOffDash #define LINE_DOTTED LineDoubleDash #define LINE_DOTDASH LineOnOffDash /* Note that a LineWidth of 0 means one-pixel wide line using any fast hardware algorithm. LineWidths 1 on up are done in (slower) but "compatible" manner */ unsigned int Xlinewidth = 1; unsigned int oldXlinewidth = 1; #define SETLINESTYLE(a) if (Xlinewidth == 1) \ XSetLineAttributes(gksdisplay, gksGC, 0, \ a, CapButt, JoinMiter); \ else \ XSetLineAttributes(gksdisplay, gksGC, Xlinewidth, \ a, CapButt, JoinMiter); #define CHKANDSETLINESTYLE(j) \ if (j == 0) XSetLineAttributes(gksdisplay, gksGC, 0, LineSolid, \ CapButt, JoinMiter); \ if (j == 1) { XSetLineAttributes(gksdisplay, gksGC, 0, \ LineOnOffDash, CapButt, JoinMiter); \ XSetDashes(gksdisplay, gksGC, 0, sd_dashed, 8); } \ if (j == 2) { XSetLineAttributes(gksdisplay, gksGC, 0, \ LineOnOffDash, CapButt, JoinMiter); \ XSetDashes(gksdisplay, gksGC, 0, sd_dotted, 8); } \ if (j == 3) { XSetLineAttributes(gksdisplay, gksGC, 0, \ LineOnOffDash, CapButt, JoinMiter); \ XSetDashes(gksdisplay, gksGC, 0, sd_dotdash, 8); } #define SETCLIPRGN(a,b,c,d) gkscliprect[0].x = a; \ gkscliprect[0].y = b; \ gkscliprect[0].width = ((c) - (a) + 1); \ gkscliprect[0].height = ((d) - (b) + 1); \ XSetClipRectangles(gksdisplay, gksGC, 0, 0, gkscliprect, 1, Unsorted) /* IMAGE_SLOW X-Workstation image manipulation. Note that previous full-screen image MUST BE thrown away if user resizes window. */ #define CHKIMAGE \ if (imagevalid == 0) \ { \ XGetWindowAttributes(gksdisplay, gkswindow, &xwinattr); \ image_x = xwinattr.width; \ image_y = xwinattr.height; \ gksimage = XGetImage(gksdisplay, gkswindow, 0, 0, \ xwinattr.width, xwinattr.height, AllPlanes, XYPixmap); \ imagevalid = 1; \ imagedesc[GKS_XINDEX].valid = 1; \ imagedesc[GKS_XINDEX].pwidth = image_x; \ imagedesc[GKS_XINDEX].pheight = image_y; \ } \ else \ { \ XGetWindowAttributes(gksdisplay, gkswindow, &xwinattr); \ if ((image_x != xwinattr.width) || (image_y != xwinattr.height)) \ { \ gksimage = XGetImage(gksdisplay, gkswindow, 0, 0, \ xwinattr.width, xwinattr.height, AllPlanes, XYPixmap); \ image_x = xwinattr.width; \ image_y = xwinattr.height; \ imagedesc[GKS_XINDEX].pwidth = image_x; \ imagedesc[GKS_XINDEX].pheight = image_y; \ } \ } /* next macro converts some special XKeySym's to PC ScanCodes */ #define XFKEY_TO_SCAN(a,b) \ if (a == XK_F1) b = 59; \ else if (a == XK_F2) b = 60; \ else if (a == XK_F3) b = 61; \ else if (a == XK_F4) b = 62; \ else if (a == XK_F5) b = 63; \ else if (a == XK_F6) b = 64; \ else if (a == XK_F7) b = 65; \ else if (a == XK_F8) b = 66; \ else if (a == XK_Left) b = 75; \ else if (a == XK_Up) b = 72; \ else if (a == XK_Right) b = 77; \ else if (a == XK_Down) b = 80; \ else b = 0; /* WARNING: you MUST ALIGN the horizontal coordinate (e.g. with (xp - (xp % 8)), otherwise GETIMAGE will fail. This does NOT seem to be documented anywhere. */ #define GETIMAGE(a,b,c,d,z) XGetSubImage(gksdisplay, gkswindow, (a), (b), \ (c) - (a) + 1, (d) - (b) + 1, AllPlanes, XYPixmap, \ gksimage, (a), (b)) #define GETPIXEL(x,y) (unsigned)XGetPixel(gksimage, (x), (y)) /* Cursor Image is a SUBSET of the full screen with upper left corner at: curspwindow[0], curspwindow[3] */ #define CURS_GETPIXEL(x,y) (unsigned)XGetPixel(cursaveimage, \ (x) - curspwindow[0], (y) - curspwindow[3]) #define PUTPIXEL(x,y) XPutPixel(gksimage, (x), (y), \ (unsigned long)lncolor) #define PUTIMAGE(a,b,w,h,i,z) XPutImage(gksdisplay, gkswindow, gksGC, \ gksimage, (a), (b), (a), (b), (w), (h)) #elif defined(TURBEAUX) /* Borland C++ */ #define _KEYBRD_READ 0 /* next character from keyboard */ #define _KEYBRD_READY 1 /* check for keystroke */ /* arguments to _setvideomode() from Microsoft graph.h */ #define _DEFAULTMODE (-1) /* restore screen original mode */ #define _HRESBW 6 /* 640 x 200, BW */ #define _HRES16COLOR 14 /* 640 x 200, 16 color */ #define _ERESCOLOR 16 /* 640 x 350, 4 or 16 color */ #define _VRES16COLOR 18 /* 640 x 480, 16 color */ #define _8514COLOR 25 /* 1024 x 768, 256 color */ #define _ORES256COLOR 0x0100 /* 640 x 400, 256 color */ #define _VRES256COLOR 0x0101 /* 640 x 480, 256 color */ #define _SRES16COLOR 0x0102 /* 800 x 600, 16 color */ #define _SRES256COLOR 0x0103 /* 800 x 600, 256 color */ #define _XRES16COLOR 0x0104 /* 1024 x 768, 16 color */ #define _XRES256COLOR 0x0105 /* 1024 x 768, 256 color */ #define _ZRES16COLOR 0x0106 /* 1280 x 1024, 16 color */ #define _ZRES256COLOR 0x0107 /* 1280 x 1024, 256 color */ #define _XDISPLAY 100 /* control parameters for _ellipse, _rectangle, _pie and _polygon */ #define _GBORDER 2 /* draw outline only */ #define _GFILLINTERIOR 3 /* fill using current mask */ /* parameters for _clearscreen */ #define _GCLEARSCREEN 0 #define _GVIEWPORT 1 #define _GWINDOW 2 /* "action verb" for PUTIMAGE() Microsoft's _GPSET = 3, whereas we need Borland's COPY_PUT = 0 */ #define _GPSET 0 /* try to use C pre-processor, if possible, to redefine to Borland */ #define COLINDEX(a) ((a > 15) ? a : vdi2vga[ a ]) #define SETCOLOR setcolor #define SETPIXEL(a,b) putpixel(a,b,getcolor()) #define GETPIXEL getpixel /* Borland setlinestyle is MUCH MORE functional */ #define LINE_SOLID 0xffff #define LINE_DASHED 0xeeee #define LINE_DOTTED 0xaaaa #define LINE_DOTDASH 0xf6f6 #define CHKANDSETLINESTYLE(j) \ if (j == 0) setlinestyle(USERBIT_LINE,0xffff,NORM_WIDTH); \ if (j == 1) setlinestyle(USERBIT_LINE,0xeeee,NORM_WIDTH); \ if (j == 2) setlinestyle(USERBIT_LINE,0xaaaa,NORM_WIDTH); \ if (j == 3) setlinestyle(USERBIT_LINE,0xf6f6,NORM_WIDTH) #define SETLINESTYLE(m) setlinestyle(USERBIT_LINE,m,NORM_WIDTH) /* Borland setviewport QUITE DIFFERENT from Microsoft _setcliprgn in that coordinates are RELATIVE. This difference is handled by xpix() and ypix() */ #define SETCLIPRGN(l,t,r,b) setviewport(l,t,r,b,1) /* Borland's setfillpattern AND setfillstyle ALLOW COLOR control */ /* Borland setpalette MUCH LESS functional in that RGB cannot be DIRECTLY changed, BUT we can use setrgbpalette IF display is VGA or 8514 (NOT EGA) */ /* *** BUG *** doesn't change xpixlast, ypixlast #define LINETO lineto #define MOVETO moveto */ #define LINETO(a,b) {lineto(a,b); xpixlast = a; ypixlast = b;} #define MOVETO(a,b) {moveto(a,b); xpixlast = a; ypixlast = b;} #define CLEARSCREEN(a) cleardevice() /* Borland sector MUCH DIFFERENT in parameters */ #define RECTANGLE(z,l,t,r,b) rectangle(l,t,r,b) /* Borland rectangle DOESN'T fill, use fillpoly */ #define FILLRECTANGLE(l,t,r,b) rectangle(l,t,r,b) #define FILLPOLY(p,n) fillpoly(n,p) /* Ellipse Params (not all used) are: u = ul_x, v = ul_y, l = lr_x, m = lr_y, b = center_x, c = center_y, h = half_x, k = half_y, f = 0, t = 360 */ #define ELLIPSE(u,v,l,m,b,c,h,k,f,t) ellipse(b,c,f,t,h,k) #define FILLELLIPSE(u,v,l,m,b,c,h,k,f,t) fillellipse(b,c,h,k) /* Arc Params (not all used) are: u = ul_x, y = ul_y, l= lr_x, m = lr_y, b = center_x, center_y, h = half_x, k = half_y, o = x3, p = y3, q = x4, r = y4, f = from, t = to */ #define ARC(u,v,l,m,b,c,h,k,o,p,q,r,f,t) ellipse(b,c,f,t,h,k) #define FILLARC(u,v,l,m,b,c,h,k,o,p,q,r,f,t) sector(b,c,f,t,h,k) /* Borland floodfill can only use ONE color, for multicolored patterns we use the internal routine aux_flood_fill() */ #define FLOODFILL floodfill #define CHKIMAGE /* Borland uses FAR pointers for next two */ #define PUTIMAGE(a,b,w,h,i,z) putimage(a,b,i,z) #define GETIMAGE getimage /* *** NOW DONE ABOVE #include TURBEAUX graphics header for Borland's GRAPHICS.LIB: initgraph() moveto() closegraph() lineto() putpixel() cleardevice() getcolor() setlinestyle() imagesize() setrgbpalette() getimage() rectangle() putimage() ellipse() setcolor() arc() getpixel() floodfill() setviewport() setfillpattern() fillpoly() fillellipse() getpalette() sector() setwritemode() setpalette() */ #else /* Microsoft C */ /* try to use C pre-processor, if possible, to standardize */ #define _XDISPLAY 100 #define _8514COLOR 25 /* 1024 x 768, 256 color */ #define COLINDEX(a) ((a > 15) ? a : vdi2vga[ a ]) #define SETCOLOR _setcolor #define SETPIXEL(a,b) _setpixel(a,b) #define GETPIXEL _getpixel #define LINE_SOLID 0xffff #define LINE_DASHED 0xeeee #define LINE_DOTTED 0xaaaa #define LINE_DOTDASH 0xf6f6 #define CHKANDSETLINESTYLE(j) \ if (j == 0) _setlinestyle(0xffff); \ if (j == 1) _setlinestyle(0xeeee); \ if (j == 2) _setlinestyle(0xaaaa); \ if (j == 3) _setlinestyle(0xf6f6) #define SETLINESTYLE(m) _setlinestyle(m) #define SETCLIPRGN(l,t,r,b) _setcliprgn(l,t,r,b) #define REMAPALLPALETTE(p) _remapallpalette(p) #define REMAPPALETTE(i,l) _remappalette(i,l) /* *** BUG *** doesn't change xpixlast, ypixlast #define LINETO _lineto #define MOVETO _moveto */ #define LINETO(a,b) {_lineto(a,b); xpixlast = a; ypixlast = b;} #define MOVETO(a,b) {_moveto(a,b); xpixlast = a; ypixlast = b;} #define CLEARSCREEN(a) _clearscreen(a) #define RECTANGLE(z,l,t,r,b) _rectangle(z,l,t,r,b) #define FILLRECTANGLE(l,t,r,b) _rectangle(_GFILLINTERIOR,l,t,r,b) #define FILLPOLY(p,n) _polygon(_GFILLINTERIOR,p,n) /* Ellipse Params (not all used) are: u = ul_x, v = ul_y, l = lr_x, m = lr_y, b = center_x, c = center_y, h = half_x, k = half_y, f = 0, t = 360 */ #define ELLIPSE(u,v,l,m,b,c,h,k,f,t) _ellipse(_GBORDER,u,v,l,m) #define FILLELLIPSE(u,v,l,m,b,c,h,k,f,t) _ellipse(_GFILLINTERIOR, \ u,v,l,m) /* Arc Params (not all used) are: u = ul_x, y = ul_y, l= lr_x, m = lr_y, b = center_x, center_y, h = half_x, k = half_y, o = x3, p = y3, q = x4, r = y4, f = from, t = to */ #define ARC(u,v,l,m,b,c,h,k,o,p,q,r,f,t) _arc(u,v,l,m,o,p,q,r) #define FILLARC(u,v,l,m,b,c,h,k,o,p,q,r,f,t) \ _pie(_GFILLINTERIOR,u,v,l,m,o,p,q,r) #define FLOODFILL _floodfill #define CHKIMAGE /* Microsoft uses HUGE pointers for next two */ #define PUTIMAGE(a,b,w,h,i,z) _putimage(a,b,i,z) #define GETIMAGE _getimage #include /* includes PC graphics pixel and scan-line (extern) conversion functions in Microsoft's GRAPHICS.LIB: _setvideomode() _setfillmask() _setvideoconfig() _rectangle() _setcolor() _ellipse() _clearscreen() _arc() _setlinestyle() _pie() _moveto() _setcliprgn() _setpixel() _getpixel() _lineto() _floodfill() _remappalette() _remapallpalette() _imagesize() _getimage() _putimage() _setwritemode() */ #endif /* end of Microsoft C */ /* | | ------------------------------------------------------------------------ */ /* Segment, XImage/Xbitmap/Cursor Globals Common to ALL ------------------ | | | ALL these variables are now EXTERN in module: xstate.c | | | | CONDITIONAL DEFINES: YES | | */ /* SEGMENT/XBITMAP Descriptor Table The Reserved positions are: 0 type=SEGMENT LARGECROSS_CURSOR in XOR 1 type=SEGMENT SMALLCROSS_CURSOR in BrightWhite 2 type=XBITMAP BOLDARROW_CURSOR in BrightWhite 3 type=XBITMAP SQUAREBOX_CURSOR in BrightWhite 4 type=XBITMAP VERTBAR_CURSOR in BrightWhite 5 type=XBITMAP HORIZBAR_CURSOR in BrightWhite */ /* needed by module: xbitmap */ struct _segandxbm { int active; /* >= 1 if active, 2 if RESERVED */ int type; /* 1 for SEGMENT, 2 for XBITMAP */ int assoccurs; /* set if there is a CURSOR associated with the XBITMAP */ int curs_fg; /* cursor foreground color */ int curs_bg; /* cursor background color */ int curs_xh; /* cursor x hot spot */ int curs_yh; /* cursor y hot spot */ #if defined(DESQ) /* X-Workstation */ Pixmap xbm; /* set if type is XBITMAP */ Cursor curs; /* set if assoccurs == 1 */ #endif int width; /* set to XBITMAP width in PIXELS */ int height; /* set to XBITMAP height in PIXELS */ char *bits; /* not actually used in the case of an X-Workstation since the XLib allocates storage itself */ char *save_bits; /* allocated in the case of a PC for saving the screen under an XBITMAP when the associated CURSOR is used */ }; extern struct _segandxbm _FAR descript[]; extern int max_descript; extern int descript_initdone; extern int curspwindow[4]; /* cursor_save_window (pixel coords) in which cursor is allowed to roam, used by stcursavearea() and stviscursor() */ extern int boldarr_exist; /* typical X11-type bitmap info for BOLDARROW_CURSOR note weird bit numbering (due to LITTLE_ENDIAN) of: l0 l1 l2 l3 l4 l5 l6 l7 r0 r1 r2 r3 r4 r5 r6 r7 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 = 0x03 0xc0 */ #define boldarrow_width 16 #define boldarrow_height 16 extern char _FAR boldarrow_bits[]; extern char _FAR boldarrow_save_bits[]; /* typical X11-type bitmap info for SQUAREBOX_CURSOR */ extern int squarebox_exist; #define squarebox_width 16 #define squarebox_height 16 extern char _FAR squarebox_bits[]; extern char _FAR squarebox_save_bits[]; /* typical X11-type bitmap info for VERTBAR_CURSOR */ extern int vertbar_exist; #define vertbar_width 16 #define vertbar_height 16 extern char _FAR vertbar_bits[]; extern char _FAR vertbar_save_bits[]; /* typical X11-type bitmap info for HORIZBAR_CURSOR */ extern int horizbar_exist; #define horizbar_width 16 #define horizbar_height 16 extern char _FAR horizbar_bits[]; extern char _FAR horizbar_save_bits[]; /* IMAGES Descriptor Table The Reserved positions are: 0 gksimage 1 cursaveimage 2 choiceimage */ struct _cmap { unsigned char used[CMAP256]; /* set if HARDWARE index is used in the image */ unsigned char r[CMAP256]; /* values for rgb from 0-maxbright */ unsigned char g[CMAP256]; unsigned char b[CMAP256]; }; struct _imageandximage { int active; /* >= 1 if active, 2 if RESERVED */ int valid; /* set if memory has been allocated on client side and pointer to image is valid */ int format; /* 1 = XIMAGE_FORMAT, 2 = PC8PL_FORMAT, 3 = TMPFILE_FORMAT (when too low on memory to malloc() preferably on a RAMdisk) */ int pwindow[4]; /* pixel coords: lleft, uright */ long bytes_alloc; /* not actually used in the case of an X-Workstation since the XLib allocates storage itself*/ int bppixel; /* bits per pixel */ FILE *ifp; /* used when .format == 3 */ #if defined(DESQ) /* X-Workstation */ void *imageptr; /* cast (XImage *) if format is XImage, cast (char *) if format is PC Image */ struct _cmap *pcolormap; /* pointer to colormap */ #elif defined(TURBEAUX) void far *imageptr; /* Borland C++ */ struct _cmap far *pcolormap; /* pointer to colormap */ #else char _huge *imageptr; /* Microsoft C++ */ struct _cmap _far *pcolormap; /* pointer to colormap */ #endif int pwidth; /* set to width in PIXELS */ int pheight; /* set to height in PIXELS */ int maxbright; /* RGB values range from 0-maxbright */ }; extern struct _imageandximage _FAR imagedesc[]; extern int max_imagedesc; extern int imagedesc_initdone; /* | | ------------------------------------------------------------------------ */ /* GKS Color and Font Globals Common to All ------------------------------ | | | CONDITIONAL DEFINES: NO | | */ /* in module: xstate.c */ extern long vcxlong; /* e.g. for VGA: 639, for 8514: 1023 */ extern long vcylong; /* e.g. for VGA: 479, for 8514: 767 */ int expose_flag = 0;/* SET after reception of a contiguous block of Expose events in await_wk_event() CLEARED by call of enq_expose(l); */ /* vdi COLOR indices: 0 = black 8 = orange 1 = blue 9 = light green 2 = red 10 = light cyan 3 = magenta 11 = light blue 4 = green 12 = light magenta 5 = cyan 13 = light red 6 = yellow 14 = dark grey 7 = white 15 = light grey */ /* COLOR PERMUTATIONS(virtual indices to hardware indices): These are used to STANDARDIZE the FIRST 16 colors (in xstate.c). */ extern int _FAR vdi2tek[]; /* size for all is 16 */ extern int _FAR vdi2intel[]; extern int _FAR vdi2aix[]; extern int _FAR vdi2vga[]; /* INVERSES of ABOVE: hardware indices to virtual indices */ extern int _FAR vga2xwin[]; extern int _FAR vga2vdi[]; /* in module: xstate.c */ extern long _FAR def_colorsarray[]; /* size for both is MAXCOLORZ */ extern long _FAR colorsarray[]; /* bottom 16 are VGA */ extern int colorsarr_initdone; #define XMASK 7 #define YMASK 9 /* The following default STRING size ONE 7 x 9 Font is now included from raster.h: PRIVATE char amr10[96][9] ={ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, space {0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x08,0x08}, ! {0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00}, " ... */ /* Short Polyline (SHORT_PL) records for STROKE output (positions 0--94) followed by records for MARKer output (positions 95--104): The FORMAT is: Header_Word SHORT_PL word count Initial_Move x_1 y_1 ... Draw_Move x_k y_k ... Where if (-64 <= x_k < 0) OR (0 <= x_k < 64) the operation is a DRAW, otherwise the 6th bit is dropped and a MOVE is performed. */ #define X_BOX 7 #define Y_BOX 9 #define SHORT_PL 0x1d #define MOVE_PL 64 #define MAXPL_BYTES 40 /* The following default STRING size ONE 7 x 9 Font is now included from raster.h: PRIVATE signed char strk10[105][MAXPL_BYTES] = { {SHORT_PL, 1}, space {SHORT_PL, 6, 4,0,1,0,0,1,-1,0,0,8}, ! {SHORT_PL, 5, 2,7,1,2,2,0,-1,-2}, " ... */ #include "raster.h" /* | | ------------------------------------------------------------------------- */ /* Virtual Coordinate and HARDWARE DEPENDENT Globals. These are set either by a call to reportstatus() or initvdi() ------------------------ | | | CONDITIONAL DEFINES: YES | | */ /* in module: xstate.c */ extern int reportdone; /* report done yet ? */ /* (0) wkcode = 10 on PC */ PRIVATE int screencode; /* (1) type of PC graphics: 0 -- 19 + svga. note enqvideo() returns a SIMPLIFIED screencode */ PRIVATE int dyn_segments; /* (2) always = 0 (no) on PC */ /* recommended device numbers: -1 = generic -2 = not supported */ PRIVATE int def_locator_dev; /* (3) this = mousetype for PC */ PRIVATE int def_string_dev; /* (4) */ PRIVATE int def_stroke_dev; /* (5) */ PRIVATE int def_pick_dev; /* (6) */ PRIVATE int def_choice_dev; /* (7) */ PRIVATE int def_valuator_dev;/* (8) */ /* in module: xstate.c */ extern int colorindices; /* (9) 2 (monochrome), 16 or 256 */ extern int xormask; /* 0x000f for 16, 0x00ff for 256 */ extern int bitsppixel; /* 4 for 16, 8 for 256 */ PRIVATE int mouseexist; /* (10) mouse: 0 = absent, 1 = present */ PRIVATE int mousetype; /* if mouse is present 2 = microsoft (2-button), 3 = msmouse (3-button) */ PRIVATE int tabletexist; /* (11) tablet: 0 = absent, 1 = present */ PRIVATE int tablettype; /* for FUTURE expansion */ #if defined(DESQ) /* X-Workstation */ extern int X11_readyforinput; /* this will STAY equal to ZERO in GKS-VIRTUAL mode */ int Xcolorindices; /* Actual colors allocated by XAllocColors(). Depending on the X-Workstation, we MAY have: Xcolorindices < DisplayCells(gksdisplay, gksscreen) */ #elif defined(TURBEAUX) /* Borland GRAPHICS.LIB */ PRIVATE int savehorz[64]; /* used to save screen under small cursor */ PRIVATE int savevert[64]; /* used to save screen under small cursor */ PRIVATE int ibufallocated = 0; /* image buffer not yet allocated */ void far *image_buf; /* pointer to image buffer for reqchoice() */ #else /* Microsoft GRAPHICS.LIB */ PRIVATE int savehorz[64]; /* used to save screen under small cursor */ PRIVATE int savevert[64]; /* used to save screen under small cursor */ PRIVATE struct videoconfig vc; /* used by _getvideoconfig() */ PRIVATE int ibufallocated = 0; /* image buffer not yet allocated */ char _huge *image_buf; /* pointer to image buffer for reqchoice() */ #endif PRIVATE int def_bitsprecision = 12; /* default */ PRIVATE int bitsprecision; /* default is 12 */ PRIVATE long def_xvdlaxis = 4095; /* def, can be changed by initcoor() */ PRIVATE long def_yvdlaxis = 3071; /* def, can be changed by initcoor() */ PRIVATE long xvdlaxis; /* default is 2^12 - 1 = 4095 */ PRIVATE long yvdlaxis; /* default is (3/4)(xvdlaxis + 1) - 1 = 3071 */ /* | | --------------------------------------------------------------------------- */ /* Global GKS Graphics Context (GC) Variables Common to All ----------------- | | | CONDITIONAL DEFINES: NO | | */ PRIVATE int wkcode; /* 2 = tektronix 4100/4200 workstations 9 = standard metafile code on disk 10 = IBM PC/XT/AT/PS2 100 = X-Workstation */ PRIVATE int wklevel;/* 0 = base level, no additional features 1 = supports dynamic segments (PC does NOT) */ PRIVATE int curpage; /* current graphics page, 0 if only one */ PRIVATE char gframename[64]; /* name of current graphics frame */ PRIVATE int xlast,ylast; /* last virtual device coordinates */ PRIVATE int xpixlast,ypixlast; /* last actual pixel coords */ PRIVATE int viewattrib; /* background color index and 'wipe' or 'erase' index. on PC this is FIXED at 0 */ /* Tekronix workstation transformation: 1. clips viewextent 2. maps viewextent subset of (0,0,xvdlaxis,yvdlaxis) to viewport subset of fullscreen. PC workstation transformation: 1. clips viewextent which MUST EQUAL viewport. */ PRIVATE int viewextent[4]; /* tektronix 'window', default is (0,0,xvdlaxis,yvdlaxis) */ /* needed by module: xbitmap.c */ int pixviewext[4]; /* as above with, but with pixels, default is (0,0,vcxlong,vcylong) */ PRIVATE int viewport[4]; /* tektronix 'viewport' default is (0,0,xvdlaxis,yvdlaxis) */ /* needed by module: xbitmap.c */ int fullviewind; /* 1 = viewport is fullscreen, 0 = not */ PRIVATE int clipind; /* clip indicator, ALWAYS 1 = clip */ /* graphics DRAWING primitives */ PRIVATE int lntype; /* line type, default is 0 = solid */ /* needed by module: xbitmap.c */ int lncolor; /* line color AND ALSO CURRENT PC graphics color, default is 7 = white */ PRIVATE int lnwidth; /* line width default = 1 pixel */ PRIVATE int lnwidthalign; /* 0 = center (default), 1 = up, 2 = left, 3 = down, 4 = right */ PRIVATE int lnmode; /* line mode, default is 1 = overlay */ PRIVATE int mktype; /* marker type, default is 0 = dot */ PRIVATE int mkcolor; /* marker color, default is 7 = white */ PRIVATE int mksize; PRIVATE int mkmode; /* marker mode, default is 1 = overlay */ PRIVATE int flpattern[4]; /* fillpattern control, defaults are int. style = 0 (hollow) color = 7 (white) pattern = index 0 hatch = index 0 */ /* Load the 8 by 8 default user pattern 256 with VGA (hardware) color indices (note, in contrast, that an X-Workstation always converts ptable[] to a 16-color Pixmap): */ PRIVATE int ptable_num = 256; PRIVATE unsigned char ptable[16][8] = { /* 0 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 1 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 2 green */ {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, /* 3 cyan */ {0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}, /* 4 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 5 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 6 orange */ {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40}, /* 7 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 8 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 9 light_blue */ {0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02}, /* 10 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 11 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 12 light_red */ {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80}, /* 13 light_magenta */ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, /* 14 yellow */ {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}, /* 15 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, }; /* format of the double array is: ptable[index][] = {0xhh, ... other masks ,0xhh} e.g. to set every other pixel in index 5 ptable[5][] = {0xaa, 0xaa, 0xaa, ... 0xaa}; */ /* load default hatch types 0 - 7 (see gfillpattern() for discussion of types). while it is true that hatch types are really patterns, they are DISTINGUISHED in that vector terminals are also able to draw them. */ PRIVATE unsigned char htable[8][8] = { /* 0 */ {0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00}, /* 1 */ {0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88}, /* 2 */ {0x88,0x44,0x22,0x11,0x88,0x44,0x22,0x11}, /* 3 */ {0x88,0x11,0x22,0x44,0x88,0x11,0x22,0x44}, /* 4 */ {0x88,0x55,0x22,0x55,0x88,0x55,0x22,0x55}, /* 5 */ {0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81}, /* 6 */ {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 7 */ {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80} }; /* end of hatch patterns */ PRIVATE int prmeter[4]; /* perimeter control, defaults are visibility = 0 (visible !) type = 0 (solid) color = 7 (white) width = default is 1 pixel and more MAY NOT be supported */ /* graphics TEXT primitives */ PRIVATE int txcolor; /* text color, default is 7 = white */ PRIVATE int txsize; /* text size, def is 10 = 10 tenths normal */ /* basic cell size (before magnification) for STRING */ PRIVATE int cellwidth; /* these are in vdl units, on Tektronix */ PRIVATE int cellheight; /* 4100 series def's are: 39 59 12 in a */ PRIVATE int cellspace; /* terminal space of 4095 x 3130 */ /* basic cell size (before magnification) for STROKE */ PRIVATE int vectwidth; PRIVATE int vectheight; PRIVATE int vectspace; PRIVATE int txorient; /* text baseline contol, def is 0 degrees */ PRIVATE int txpath; /* writing direction, def is 0 deg (right) */ PRIVATE int txprec; /* 0 = string (def), 1 = char, 2 = stroke */ PRIVATE int txmode; /* 0 = replace, 1 = overlay, 2 = XOR */ PRIVATE int txpixoverride; /* used by gappendtext() and gtext() */ /* graphics INPUT STATE primitives */ PRIVATE int echostate[10]; /* flags to tell whether echo is off (0) or on (1): echostate[0] = locator (fixed at 0) echostate[1] = string echostate[2] = stroke (fixed at 0) echostate[4] = pick (fixed at 0) echostate[3] = choice (fixed at 0) echostate[5] = valuator (fixed at 0) default is 1 unless fixed at 0 */ PRIVATE int promptstate[10];/* flags to tell whether prompting is off (0) or on (1): promptstate[0] = locator (fixed at 1) promptstate[1] = string promptstate[2] = stroke (fixed at 1) promptstate[4] = pick (fixed at 1) promptstate[3] = choice (fixed at 1) promptstate[5] = valuator (fixed at 1) default is 1 = on */ /* NOTE: "xxxactive" variables below are recorded for future expansion */ /* LOCATOR primitives */ PRIVATE int locactive; /* last locator device initialized: -1 = unspecified (or generic) 0 = tektronix-style joydisk 2 = microsoft 2-button mouse 3 = msmouse 3-button mouse 4 = arrow keys 8 = summagraphics-style tablet */ PRIVATE int kloclast; /* last raw locator (lower 3-bits) */ PRIVATE int xloclast,yloclast; /* last vdl locator position */ PRIVATE int xlocplast,ylocplast; /* last pix locator/cursor position */ PRIVATE int awlastwasarrow = 0; /* set if last move was done by an arrow key (left, right, up, down) */ PRIVATE int loccursor; /* locator cursor, available are: seg 1 = small crosshairs seg 0 = tektronix-style crosshairs */ PRIVATE int locgrid; /* 0 = off, 1 = on (default is off) */ PRIVATE int xmodgrid,ymodgrid; /* snap grid settings for x and y */ PRIVATE int locband; /* 0 = off, 1 = on (default is off) */ PRIVATE int xlocpband,ylocpband; /* last pivot for band */ PRIVATE int locwindow[4]; /* graphics input window for locator, default is fullscreen = (0,0,xvdlaxis,yvdlaxis) */ PRIVATE int locpwindow[4]; /* pixel version of above, default is fullscreen = (0,vcylong,vcxlong,0) */ /* STRING INPUT primitives */ PRIVATE int strgactive; /* last string input device initialized: -1 = unspecified (a keyboard) */ PRIVATE int strgwindow[4]; /* graphics input window for string, default is fullscreen = (0,0,xvdlaxis,yvdlaxis) */ /* STROKE primitives */ PRIVATE int stkactive; /* last stroke device initialized: 10 = summagraphics-style tablet */ /* PICK primitives */ PRIVATE int pikactive; /* last pick device initialized: -1 = unspecified (functions like locator) 1 = tektronix-style joydisk 2 = microsoft 2-button mouse 3 = msmouse 3-button mouse 4 = arrow keys 9 = summagraphics-style tablet */ PRIVATE int xpiklast,ypiklast; /* last vdl pick position */ PRIVATE int xpikplast,ypikplast; /* last pixel pick/cursor position */ PRIVATE int pikcursor; /* pick cursor, available are: seg 1 = small crosshairs seg 0 = tektronix-style crosshairs */ PRIVATE int pikaperture; /* GIN pick aperture (def is 8 vdl units) */ PRIVATE int pikwindow[4]; /* graphics input window for pick, default is fullscreen = (0,0,xvdlaxis,yvdlaxis) */ /* VALUATOR primitives */ PRIVATE int valactive; /* last valuator device initialized: -1 = unspecified (functions like locator) 1 = tektronix-style joydisk 2 = microsoft 2-button mouse 3 = msmouse 3-button mouse */ /* Mouse Valuator ALSO USES Locator's: PRIVATE int xloclast,yloclast; PRIVATE int xlocplast,ylocplast; */ PRIVATE int valwindow[4]; /* graphics input window for valuator, default is botscreen = (0,0,4095,160) */ PRIVATE int valpwindow[4];/* same as above but in PIXEL coords */ PRIVATE int valpxrange, valpyrange; PRIVATE int valwinflag; /* orientation of valuator: 0 = horizontal (default) 1 = vertical */ PRIVATE int valcursor; /* valuator cursor, available are: 4 = vertical bar in BrightWhite (default) 5 = horizontal bar in BrightWhite */ PRIVATE double valmin; /* minimum real value (default = 0.0) */ PRIVATE double valstart; /* starting real value (default = 0.5 unless valuator has been used in which case valstart=vallast) */ PRIVATE double valmax; /* maximum real value (default = 1.0) */ PRIVATE double vallast; /* last value set by operator (MUST be be in the interval [valmin, valmax]) */ /* CHOICE primitives */ PRIVATE char *chotags[8] = { "-F1-", "-F2-", "-F3-", "-F4-", "-F5-", "-F6-", "-F7-", "-F8-" }; PRIVATE int chopwindow[4];/* Choice window in PIXEL coords */ PRIVATE int choactive; /* last choice device initialized: -1 = unspecified */ PRIVATE int chocursor; /* choice cursor, available are: 0 = function key F1 .. F8 buttons */ /* | | ------------------------------------------------------------------------- */ /* ======================================================================= PRIVATE PIXEL-DEPENDENT functions: MOUSECML() init_adapter() init_descript() (extern) alloc_mem() bios_key() set_solid_fill() aux_flood_fill() (Borland) set_patt_fill() (Microsoft, X) set_hatch_fill() dda_line() dda_rect() set_palette() set_all_palette() rest_adapter() ======================================================================= */ #if defined(DESQ) /* X-Workstation */ #elif defined(_DJGPP) /* DJGPP with BCC2GRX */ void MOUSECML(int *pm1, int *pm2, int *pm3, int *pm4) /* This low level function is used ONLY in the case of the GCC Compiler (we have to be careful with 32-bit DPMI code) */ { int m1, m2, m3, m4; _go32_dpmi_registers inreg, outreg; /* it is *** ESSENTIAL *** to zero unused registers (why the HELL it is essential is beyond me) */ memset(&inreg, 0, sizeof(inreg)); memset(&outreg, 0, sizeof(outreg)); m1 = *pm1; m2 = *pm2; m3 = *pm3; m4 = *pm4; inreg.x.ax = m1; inreg.x.bx = m2; inreg.x.cx = m3; inreg.x.dx = m4; outreg.x.ax = m1; outreg.x.bx = m2; outreg.x.cx = m3; outreg.x.dx = m4; /* simulate int86x() */ _go32_dpmi_simulate_int(0x33, &outreg); *pm1 = (int)outreg.x.ax; *pm2 = (int)outreg.x.bx; *pm3 = (int)outreg.x.cx; *pm4 = (int)outreg.x.dx; } /* end of MOUSECML */ #elif !defined(_DJGPP) /* Borland C++, Microsoft C */ void MOUSECML(int *pm1, int *pm2, int *pm3, int *pm4) /* This low level function is used ONLY in the case of the PC with (Borland C++/Microsoft C). It directly calls (via DOS int 0x33) the standard DOS-type mouse driver. */ { int m1, m2, m3, m4; union REGS inreg, outreg; m1 = *pm1; m2 = *pm2; m3 = *pm3; m4 = *pm4; inreg.x.ax = m1; inreg.x.bx = m2; inreg.x.cx = m3; inreg.x.dx = m4; int86(0x33, &inreg, &outreg); *pm1 = outreg.x.ax; *pm2 = outreg.x.bx; *pm3 = outreg.x.cx; *pm4 = outreg.x.dx; } /* end of MOUSECML */ #endif /* ----------------------------------------------------------------------- */ #if defined(DESQ) /* X-Workstation */ int gks_ehandler(Display *dsp, XErrorEvent *gks_err) /* Our own error handler */ { char mess[128]; XGetErrorText(dsp, gks_err->error_code, mess, 128); fprintf(stderr, "\nXError: code=%d request_code=%d minor_code=%d", (int)(gks_err->error_code), (int)(gks_err->request_code), (int)(gks_err->minor_code)); fprintf(stderr, "\n %s\n", mess); fflush(stderr); return(0); } /* end of gks_ehandler */ #endif /* ----------------------------------------------------------------------- */ PRIVATE int init_adapter(void) /* This is a COMPLETELY hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- Opens X-Display(gksdisplay) Creates GKS X-Window(gkswindow) Creates GC(gksGC) Loads the Fonts Creates a Colormap(PseudoColor) Queries Video Adapter Enters Graphics Mode Sets screencode Sets screencode Sets vcxlong, vcylong Sets vcxlong, vcylong and returns a (non-zero) screencode if successful. */ { #if defined(DESQ) /* X-Workstation */ int i, ret, argc; char *argv[12]; #elif defined(_DJGPP) /* DJGPP with BCC2GRX */ int ret, gdriver, gmode; #elif defined(TURBEAUX) /* Borland C++ */ int ret, gdriver, gmode; char chrline[80]; #else /* Microsoft C */ int ret; char chrline[80]; #endif #if defined(DESQ) /* X-Workstation */ /* Open X-server display. Note that NULL string means use the default as set by environmental DISPLAY variable. */ /* *** OLD *** gksdisplay = XOpenDisplay(""); */ gksdisplay = XOpenDisplay(gks_startup.display_str); if (gksdisplay == NULL) { fprintf(stderr, "\n\ninit_adapter: XOpenDisplay(\"%s\") failed *** \n\n", gks_startup.display_str); fflush(stderr); exit(-1); } /* Use macro DefaultScreen to set gksscreen (int), and set defaults for background = black [0], foreground = white [7] */ gksscreen = DefaultScreen(gksdisplay); #if defined(_BACKING_STOR) /* Note these calls need type (Screen *), hence the XDefaultScreenOfDisplay() call: */ ret = XDoesBackingStore(XDefaultScreenOfDisplay(gksdisplay)); switch(ret) { case WhenMapped: fprintf(stderr, "\n (WhenMapped)=XDoesBackingStore() "); fflush(stderr); break; case NotUseful: fprintf(stderr, "\n (NotUseful)=XDoesBackingStore() "); fflush(stderr); break; case Always: fprintf(stderr, "\n (Always)=XDoesBackingStore() "); fflush(stderr); break; default: fprintf(stderr, "\n (%d?)=XDoesBackingStore() ", ret); fflush(stderr); } if (XDoesSaveUnders(XDefaultScreenOfDisplay(gksdisplay)) == True) fprintf(stderr, "\n (True)=XDoesSaveUnders()\n"); else fprintf(stderr, "\n (False)=XDoesSaveUnders()\n"); fflush(stderr); #endif gksback = BlackPixel(gksdisplay, gksscreen); gksfore = WhitePixel(gksdisplay, gksscreen); /* Note that { BlackPixel , WhitePixel } may NOT equal { Black , White } in the case of a non-Default Colormap on a COLOR X-Workstation. These colors just guaranteed to be CONSTRASTING, which is why we adjust below */ if ( (gks_startup.private_cmap == USE_PRIVATE_CMAP) && (gksback != 0L) ) { /* *** DIAGNOSTIC *** fprintf(stderr, "\n gksback=0x0%lx gksfore=0x0%lx ... fixing ", gksback, gksfore); fflush(stderr); */ gksback = 0L; } /* Create a window (which will NOT yet be displayed) with pixel size DEF_WINDOW_WIDTH by DEF_WINDOW_HEIGHT */ /* *** OLD *** gkshint.x = 15; gkshint.y = 30; gkshint.width = DEF_WINDOW_WIDTH; gkshint.height = DEF_WINDOW_HEIGHT; vcxlong = (long)(DEF_WINDOW_WIDTH - 1); vcylong = (long)(DEF_WINDOW_HEIGHT - 1); */ gkshint.x = gks_startup.offset_x; gkshint.y = gks_startup.offset_y; gkshint.width = gks_startup.geometry_width; gkshint.height = gks_startup.geometry_height; /* pixels start at 0 */ vcxlong = (long)(gks_startup.geometry_width - 1); vcylong = (long)(gks_startup.geometry_height - 1); gkshint.flags = PPosition | PSize; #if defined(_BACKING_STOR) /* Problem with X11R6 structure change(?): xswinattr.border_pixel = WhitePixel(gksdisplay, gksscreen); */ xswinattr.backing_pixel = gksback; xswinattr.backing_store = WhenMapped; gkswindow = XCreateWindow(gksdisplay, DefaultRootWindow(gksdisplay), gkshint.x, gkshint.y, gkshint.width, gkshint.height, DEF_BORDER_WIDTH, CopyFromParent, CopyFromParent, CopyFromParent, CWBorderPixel | CWBackPixel | CWBackingStore, &xswinattr); #else gkswindow = XCreateSimpleWindow (gksdisplay, DefaultRootWindow (gksdisplay), gkshint.x, gkshint.y, gkshint.width, gkshint.height, DEF_BORDER_WIDTH, gksfore, gksback); #endif /* Set standard Window Manager properties */ argc = 0; argv[0] = (char *)NULL; XSetStandardProperties(gksdisplay, gkswindow, GKS_HELLO, GKS_HELLO, None, argv, argc, &gkshint); /* Create Graphical Context with modified value mask and some additional values at this time (basically we are just setting default GKS Attributes here.) Also create a temporary Graphical Context for Pixmap manipulation. */ xgcattr.foreground = gksfore; xgcattr.background = gksback; gksGC = XCreateGC(gksdisplay, gkswindow, (GCForeground | GCBackground), &xgcattr); /* *** DIAGNOSTIC *** XGetGCValues(gksdisplay, gksGC, (GCForeground | GCBackground), &temp_xgcattr); fprintf(stderr, "\n xgcattr.foreground=0x0%lx, xgcattr.background=0x0%lx gksback=0x0%lx \n", temp_xgcattr.foreground, temp_xgcattr.background, gksback); fflush(stderr); */ tempGC = XCreateGC(gksdisplay, gkswindow, (GCForeground | GCBackground), &xgcattr); /* Load the default GKS font and make THREE tries. */ deffontpointer = XLoadQueryFont(gksdisplay, DEF_GKS_FONT1); if (deffontpointer == NULL) { /* make second try */ deffontpointer = XLoadQueryFont(gksdisplay, DEF_GKS_FONT2); if (deffontpointer == NULL) { /* make third and last try */ deffontpointer = XLoadQueryFont(gksdisplay, DEF_GKS_FONT3); if (deffontpointer == NULL) { fprintf(stderr, "Fonts %s, %s, and %s are ALL unavailable. \n", DEF_GKS_FONT1, DEF_GKS_FONT2, DEF_GKS_FONT3); fflush(stderr); XFreeGC (gksdisplay, gksGC); XDestroyWindow (gksdisplay, gkswindow); XCloseDisplay (gksdisplay); exit(-1); /* clean up and clear out */ } /* end of third try */ } /* end of second try */ } /* end of first try */ deffont = (*deffontpointer).fid; szfont[0] = deffont; szfontpointer[0] = deffontpointer; XSetFont(gksdisplay, gksGC, deffont); /* Try to load sizes 20--100 for gtextsize(). Note that size 10=index_0 is always the DEFAULT font ID: deffont */ for (i = 1 ; i <= 9 ; i++) { szfontpointer[i] = XLoadQueryFont(gksdisplay, namefonts[i]); if (szfontpointer[i] == NULL) { szfont[i] = deffont; /* use the DEFAULT */ szfontpointer[i] = deffontpointer; } else { szfont[i] = (*szfontpointer[i]).fid; } } /* end of for (i = ...) */ /* Set the GKSdisplay/gksGC background and foreground */ XSetBackground(gksdisplay, gksGC, gksback); XSetForeground(gksdisplay, gksGC, gksfore); /* Either use the default colormap (which will change the desktop less BUT give you fewer colors or Create a non-Default colormap and Install it. */ if (gks_startup.private_cmap == USE_DEFAULT_CMAP) { xcolor_map = DefaultColormap(gksdisplay, 0); } else if (gks_startup.private_cmap == USE_PRIVATE_CMAP) { xcolor_map = XCreateColormap(gksdisplay, gkswindow, DefaultVisual(gksdisplay, 0), AllocNone); } XSetWindowColormap(gksdisplay, gkswindow, xcolor_map); /* Initially, the X-Server will not report ANY events, so we set the following acceptible events Mask: ButtonPress KeyPress Exposure (tell us when previously covered part of window has been exposed and now needs re-drawing) ResizeRequest (This is DANGEROUS -- only ONE client at a time can be notified of Window Resizing, so if we are, then the Window Manager is NOT!) XSelectInput (gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | ExposureMask | ResizeRedirectMask); */ XSelectInput (gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | ExposureMask ); /* Set Our Own Error-Handler for non-critical errors, especially BadAccess in XStoreColor(s) with idiot window managers on PC's */ XSetErrorHandler(gks_ehandler); /* Note that colorindices is set by reportstatus/initvdi and, at this point in time, is undefined. */ for (i = 0 ; i < 16 ; i++) { /* Lookup Color definitions for indices 0 -- 15 by "name". exact color definitions (from RGB.TXT) will be returned in gks_exactcolors[] and actual, hardware roundoff values, will be returned in gkscolors[]. This is ONLY for INSURANCE in case set_defaults() conversion of VGA to X fails. */ XLookupColor(gksdisplay, xcolor_map, namecolors[i], &gks_exactcolors[i], &gkscolors[i]); } /* Make some modifications to Orange */ gks_exactcolors[8].red = 0xE000; gks_exactcolors[8].green = 0x9000; gks_exactcolors[8].blue = 0x0000; gkscolors[8].red = gks_exactcolors[8].red; gkscolors[8].green = gks_exactcolors[8].green; gkscolors[8].blue = gks_exactcolors[8].blue; /* Now Alloc psuedo_color Model, but let set_all_palette() Store RGB values in the FIRST 16 color cells. */ /* Try 256 colors as a maximum first ... NOTE: if you are using Hummingbird's EXceed on a PC you will have to set only 8-16 bit colorplanes and go into Configuration, select Video, then set ServerVisual to "PseudoColor" NOT "AutoSelect" */ Xcolorindices = 256; ret = XAllocColorCells(gksdisplay, xcolor_map, False, pseudo_mask_dummy, 0, pseudo_index, 256); if (ret == 0) { fprintf(stderr, "XAllocColorCells(...,256) failed...\n"); fflush(stderr); /* ... then fall back ... down to 16 */ for (i = 255 ; i >= 16 ; i--) { ret = XAllocColorCells(gksdisplay, xcolor_map, True, pseudo_mask_dummy, 0, pseudo_index, i); if (ret != 0) break; } if (ret == 0) { Xcolorindices = 2; fprintf(stderr, "...even XAllocColorCells(...,16) failed.\n"); fflush(stderr); } else { Xcolorindices = i; fprintf(stderr, "...only %d/256 colors could be allocated.\n", i); fflush(stderr); } } /* Clear the Event Queue (sometimes an extra CR is belatedly sent by main() to the Event Queue after program initiation) */ XSync(gksdisplay, False); if (XEventsQueued(gksdisplay, QueuedAfterReading) != 0) XNextEvent(gksdisplay,(XEvent *)&gksevent); /* Indicate to ALL that X11 is READY */ X11_readyforinput = 1; /* Set screencode and return */ screencode = _XDISPLAY; return(screencode); #elif defined(_DJGPP) /* DJGPP with BCC2GRX */ /* first try IBM8514 */ gdriver = IBM8514; gmode = IBM8514HI; set_BGI_mode( &gdriver, &gmode); ret = graphresult(); /* Read result of initialization */ if (ret != grOk) { fprintf(stderr, "\nIBM8514 unknown: gdriver=%d gmode=%d ", gdriver, gmode); fflush(stderr); /* second try native-mode VESA */ gdriver = NATIVE_GRX; gmode = 20; initgraph( &gdriver, &gmode, BGI_PATH ); ret = graphresult(); /* Read result of initialization */ } if (ret != grOk) { fprintf(stderr, "\nNATIVE_GRX unknown: gdriver=%d gmode=%d ", gdriver, gmode); fflush(stderr); /* third try autoDETECT */ gdriver = DETECT; gmode = 0; initgraph( &gdriver, &gmode, BGI_PATH ); ret = graphresult(); /* Read result of initialization */ } if (ret == grOk) { screencode = _VRES16COLOR; vcxlong = (long)getmaxx(); vcylong = (long)getmaxy(); if ( (vcxlong == 1023L) && (vcylong == 767L) ) { screencode = _XRES256COLOR; } else if ( (vcxlong == 799L) && (vcylong == 599L) ) { screencode = _SRES256COLOR; } else if (getmaxcolor() >= 255) { screencode = _VRES256COLOR; } fprintf(stderr, "\ngrOk: x=%ld y=%ld gdrv=%d mode=%d maxc=%d name=\"%s\"", vcxlong, vcylong, gdriver, gmode, getmaxcolor(), getdrivername()); fflush(stderr); return(screencode); } else /* NON-recoverable */ { fprintf(stderr, "\nGraphics System Error(ret=%d): %s\n", ret, grapherrormsg( ret ) ); fflush(stderr); exit( 1 ); } #elif defined(TURBEAUX) /* Borland GRAPHICS.LIB */ HANDLE_8514 /* Depends if NO_8514 is defined or not */ gdriver = VGA; gmode = VGAHI; strcpy(chrline, BGI_PATH); goto tryspecific; /* *** OLD (if you LINK-IN BGI-OBJ to GRAPHICS.LIB) *** ret = registerbgidriver(EGAVGA_driver); if (ret < 0) { fprintf(stderr, "EGAVGA_driver not registered ... \n"); fflush(stderr); strcpy(chrline, BGI_PATH); } else { chrline[0] = '\0'; } */ tryagain: gdriver = DETECT; /* let turbo try to find best */ tryspecific: initgraph(&gdriver, &gmode, chrline); fprintf(stderr, "\ngdriver=%d gmode=%d chrline=\"%s\" ", gdriver, gmode, chrline); fflush(stderr); if (gdriver == -2) /* this should NOT happen */ { fprintf(stderr, "\nCannot find a graphics card at all. \n"); fflush(stderr); return(0); } else if (gdriver == -3) { fprintf(stderr, "\nCannot find the bgi file in %s. \n", chrline); fprintf(stderr, "\nPlease enter bgi-path (or Return for VGA): "); fflush(stderr); gets(chrline); if (strlen(chrline) > 0) { goto tryagain; } else { gdriver = VGA; gmode = VGAHI; strcpy(chrline, BGI_PATH); goto tryspecific; } } else if (gdriver == IBM8514 && gmode == IBM8514HI) { screencode = _8514COLOR; vcxlong = 1020; /* Borland *** BUG *** with 1023 */ vcylong = 767; return(screencode); } else if (gdriver == VGA && gmode == VGAHI) { screencode = _VRES16COLOR; vcxlong = 639; vcylong = 479; return(screencode); } else if (gdriver == EGA && gmode == EGAHI) { screencode = _ERESCOLOR; vcxlong = 639; vcylong = 349; return(screencode); } else { fprintf(stderr, "\nOther error(%d) in BGI driver. \n", gdriver); fflush(stderr); return(0); } #else /* Microsoft GRAPHICS.LIB */ ret = 0; /* assume failure */ /* *** NESTED *** */ #if defined(_TRY_1024X768) HANDLE_XRES /* MAY cause problems on some PC's */ #endif /* ... of NEST */ if (ret) goto globs; else { /* *** NESTED *** */ #if defined(_TRY_256COLOR) screencode = _SRES256COLOR; /* svga 0x0103 */ ret = _setvideomode(_SRES256COLOR); #else screencode = _SRES16COLOR; /* svga 0x0102 */ ret = _setvideomode(_SRES16COLOR); #endif /* ... of NEST */ } if (ret) goto globs; else { /* *** NESTED *** */ #if defined(_TRY_256COLOR) screencode = _VRES256COLOR; /* vga 256 color */ ret = _setvideomode(_VRES256COLOR); if (ret) goto globs; else /* no more 256 colors to try ... drop to 16 */ { screencode = _VRES16COLOR; /* vga 16 color */ ret = _setvideomode(_VRES16COLOR); } #else screencode = _VRES16COLOR; /* vga 16 color */ ret = _setvideomode(_VRES16COLOR); #endif /* ... of NEST */ } if (ret) goto globs; else { screencode = _ERESCOLOR; /* ega poor second */ ret = _setvideomode(_ERESCOLOR); } if (ret) goto globs; else { screencode = _HRES16COLOR; /* lower res. ega */ ret = _setvideomode(_HRES16COLOR); } if (ret) goto globs; else { screencode = _HRESBW; /* cga, mda */ ret = _setvideomode(_HRESBW); } if (ret) goto globs; else { screencode = 0; /* FAILURE */ return(0); } globs: _getvideoconfig(&vc); vcxlong = vc.numxpixels - 1; /* pixels start at 0 */ vcylong = vc.numypixels - 1; return(screencode); #endif } /* end of init_adapter */ /* -------------------------------------------------------------------- */ extern int init_descript(void); /* now in xstate.c */ /* -------------------------------------------------------------------- */ PRIVATE int alloc_mem(void) /* This Function allocates PC buffers using IMAGESIZE, but is NOT needed on an X-Workstation. */ { #if defined(DESQ) /* X-Workstation */ #elif defined(TURBEAUX) /* Borland C++ */ size_t tsize; /* size_t is defined in stdio.h as the size returned by the operator sizeof */ ibufallocated = 0; /* choice image buffer NOT YET allocated */ /* now get image buffer */ if (!ibufallocated) { tsize = imagesize(0,(int)MAX_VCY - 20, (int)MAX_VCX,(int)MAX_VCY - 5); /* 16 lines */ image_buf = malloc(tsize); ibufallocated = 1; imagedesc[CHOICE_XINDEX].valid = 1; imagedesc[CHOICE_XINDEX].bppixel = bitsppixel; imagedesc[CHOICE_XINDEX].bytes_alloc = (long)tsize; imagedesc[CHOICE_XINDEX].pwindow[0] = 0; imagedesc[CHOICE_XINDEX].pwindow[1] = (int)vcylong - 5; imagedesc[CHOICE_XINDEX].pwindow[2] = (int)vcxlong; imagedesc[CHOICE_XINDEX].pwindow[3] = (int)vcylong - 20; imagedesc[CHOICE_XINDEX].pwidth = (int)vcxlong + 1; imagedesc[CHOICE_XINDEX].pheight = 16; imagedesc[CHOICE_XINDEX].imageptr = image_buf; } #else /* Microsoft C */ long imsize; ibufallocated = 0; /* choice image buffer NOT YET allocated */ /* now get image buffer */ if (!ibufallocated) { imsize = _imagesize(0,(short)MAX_VCY - 20, (short)MAX_VCX,(short)MAX_VCY - 5); /* 16 lines */ image_buf = halloc(imsize, sizeof( char)); ibufallocated = 1; imagedesc[CHOICE_XINDEX].valid = 1; imagedesc[CHOICE_XINDEX].bppixel = bitsppixel; imagedesc[CHOICE_XINDEX].bytes_alloc = (long)imsize; imagedesc[CHOICE_XINDEX].pwindow[0] = 0; imagedesc[CHOICE_XINDEX].pwindow[1] = (int)vcylong - 5; imagedesc[CHOICE_XINDEX].pwindow[2] = (int)vcxlong; imagedesc[CHOICE_XINDEX].pwindow[3] = (int)vcylong - 20; imagedesc[CHOICE_XINDEX].pwidth = (int)vcxlong + 1; imagedesc[CHOICE_XINDEX].pheight = 16; imagedesc[CHOICE_XINDEX].imageptr = image_buf; } #endif return(0); } /* end of alloc_mem */ /* -------------------------------------------------------------------- */ #if defined(DESQ) /* X-Workstation */ #else /* Borland C++, Microsoft C */ PRIVATE unsigned bios_key(int param) /* This function is completely UNNECESSARY in the case of an X-Workstation. In the case of a PC under DOS, it handles differences between Borland C++ and Microsoft C in BIOS calls as follows: If param == _KEYBRD_READY then if no char is in queue this call returns 0, otherwise it returns highbyte = scancode lowbyte = ascii value, of the next keystroke in queue, BUT THE queue IS LEFT UNCHANGED. If param == _KEYBRD_READ then it will BLOCK until there is at least one keystroke in the queue, which it will subsequently READ AND REMOVE FROM THE queue. */ { unsigned code; #endif #if defined(DESQ) /* X-Workstation */ #elif defined(TURBEAUX) /* Borland BIOS.H */ if (param == _KEYBRD_READY) { code = (unsigned)bioskey(1); return(code); } else if (param == _KEYBRD_READ) { while(bioskey(1) == 0); code = (unsigned)bioskey(0); return(code); } else return(0); } /* end of bios_key */ #else /* Microsoft BIOS.H */ if (param == _KEYBRD_READY) { code = _bios_keybrd(_KEYBRD_READY); return(code); } else if (param == _KEYBRD_READ) { code = _bios_keybrd(_KEYBRD_READ); return(code); } else return(0); } /* end of bios_key */ #endif /* -------------------------------------------------------------------- */ /* needed by module: xbitmap */ int set_solid_fill(int col) /* This Function handles the differences between the setting of solid fill and the color to be used. In the case of Borland C++ the fill color can be set INDEPENDENTLY of the linecolor whereas X-Workstations and Microsoft C ALWAYS use the current foreground color for fill. */ { int top; #if defined(DESQ) XGCValues OurXGCValues; #endif if (colorindices > 16) top = (colorindices - 1); else top = 15; if (col < 0 || col > top) return(-1); #if defined(DESQ) /* X-Workstation */ OurXGCValues.fill_style = FillSolid; XChangeGC(gksdisplay, gksGC, GCFillStyle, &OurXGCValues); XSetForeground(gksdisplay, gksGC, gkscolors[ col ].pixel); XSetBackground(gksdisplay, gksGC, gksback); #elif defined(TURBEAUX) /* Borland C++ */ /* note that COLOR is Borland option */ setcolor(col); /* to control "outline" only */ /* Borland *** BUG *** (setfillpattern() fails if using IBM8514 and col > 15) char pattern[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; setfillpattern(pattern, col); */ setfillstyle(SOLID_FILL, col); #else /* Microsoft C */ _setcolor(col); _setfillmask(NULL); /* NULL means that fillmask = 'solid' */ #endif return(0); } /* end of set_solid_fill */ /* -------------------------------------------------------------------- */ #if defined(TURBEAUX) PRIVATE int aux_flood_fill(int x, int y, int col, int dep) /* This function is a mid-point modified RECURSIVE floodfill used EXCLUSIVELY with Borland C++ for the filling of CONVEX polygons, ellipses, rectangles, and arcs since Borland's FLOODFILL function ERASES pixels set with previous colors (i.e. you can only use a pattern with a SINGLE color). To use call this you MUST first ERASE the polygon using fillpoly with index 0. Then draw a boundary in a NON-ZERO INDEX col. Then call aux_flood_fill with (x,y) as an INTERNAL "seed" point and with dep = FL_DEPTH for insurance. The current USER PATTERN is then used to fill the polygon. The complications introduced in order to remove the CONVEX restriction would probably make a slow pattern fill EVEN SLOWER. */ { int i,k,xl,xr; unsigned char xmask; --dep; /* keep track of stack depth */ if (dep <= 0) return(0); /* with damn Borland clip regions we have to check for out-of-bounds since computed barycenter COULD have negative RELATIVE coordinates. */ if ( (x < 0) || (y < 0) || (x > pixviewext[2] - pixviewext[0]) || (y > pixviewext[3] - pixviewext[1]) ) return(0); k = getpixel(x,y); if (k != 0) return(0); /* at border or already painted */ xl = x; while( (k == 0) && (xl >= 0) ) { xmask = 0x80 >> (xl % 8); for (i = 1 ; i < 16 ; i++) { if ((ptable[i][y % 8] & xmask) != 0x00) { putpixel(xl, y, i); /* modify if i color bit set */ break; } } --xl; k = getpixel(xl, y); /* move LEFT as long as you can */ } /* end of while */ /* xl is now on left border */ xr = x; k = 0; while( (k == 0) && ( xr <= pixviewext[2] - pixviewext[0]) ) { xmask = 0x80 >> (xr % 8); for (i = 1 ; i < 16 ; i++) { if ((ptable[i][y % 8] & xmask) != 0x00) { putpixel(xr, y, i); /* modify if i color bit set */ break; } } ++xr; k = getpixel(xr, y); /* move RIGHT as long as you can */ } /* end of while */ /* xr is now on right border */ /* move to MIDPOINT */ aux_flood_fill((xl + xr)/2, y - 1, col, dep); /* UP */ aux_flood_fill((xl + xr)/2, y + 1, col, dep); /* DOWN */ return(0); } /* end of aux_flood_fill */ #endif /* -------------------------------------------------------------------- */ #if defined(TURBEAUX) #else /* X-Workstation, Microsoft C */ PRIVATE int set_patt_fill(int patt_index, int col) /* This function is used by Microsoft C and by X-Workstations. In the case of X-Workstations, ALL COLOR INFORMATION IS CONTAINED in tilepixmap and "col" is IRRELEVANT. In the case of Microsoft C, a user-defined pattern with index col for EACH VGA COLOR is specified. Borland uses the routine aux_flood_fill above. The routine returns -1 if the pattern for the designated color is empty (all 0x00). */ { int top; #endif #if defined(TURBEAUX) #elif defined(DESQ) /* X-Workstation */ XGCValues OurXGCValues; #endif #if defined(TURBEAUX) #else /* X-Workstation, Microsoft C */ if (colorindices > 16) top = (colorindices - 1); else top = 15; if (col < 0 || col > top) return(-1); if (patt_index != ptable_num) return(-1); /* we CURRENTLY only support ONE user- defined pattern at a time. */ #endif #if defined(TURBEAUX) #elif defined(DESQ) /* X-Workstation */ if (colorindices == 2) return(-1); /* Monochrome */ /* tilepixmap is BUILT from pattpixmap[] so ALL COLORS are included */ OurXGCValues.fill_style = FillTiled; XChangeGC(gksdisplay, gksGC, GCFillStyle, &OurXGCValues); XSetTile(gksdisplay, gksGC, tilepixmap); XSetBackground(gksdisplay, gksGC, gksback); #else /* Microsoft C */ _setcolor(col); _setfillmask(&ptable[col][0]); #endif #if defined(TURBEAUX) #else /* X-Workstation, Microsoft C */ if ((ptable[col][0] == 0x00) && (ptable[col][1] == 0x00) && (ptable[col][2] == 0x00) && (ptable[col][3] == 0x00) && (ptable[col][4] == 0x00) && (ptable[col][5] == 0x00) && (ptable[col][6] == 0x00) && (ptable[col][7] == 0x00)) /* all 0x00's */ return(-1); else return(0); } /* end of set_patt_fill */ #endif /* -------------------------------------------------------------------- */ PRIVATE int set_hatch_fill(int hatch_index, int col) /* This function sets a fill mask using a pre-defined hatch pattern and the specified VGA color. Microsoft C and X-Workstations use the current foreground/background colors for fill. */ { int top; #if defined(DESQ) XGCValues OurXGCValues; #endif if (colorindices > 16) top = (colorindices - 1); else top = 15; if (col < 0 || col > top) return(-1); /* currently only hatch patterns 0 - 7 are defined (in htable[][]) */ if ((hatch_index < 0) || (hatch_index > 7)) return(-1); #if defined(DESQ) /* X-Workstation */ OurXGCValues.fill_style = FillStippled; XChangeGC(gksdisplay, gksGC, GCFillStyle, &OurXGCValues); XSetStipple(gksdisplay, gksGC, hatchbmp[hatch_index]); XSetForeground(gksdisplay, gksGC, gkscolors[ col ].pixel); XSetBackground(gksdisplay, gksGC, gksback); #elif defined(TURBEAUX) /* Borland C++ */ /* note that COLOR is Borland option */ setcolor(col); /* to control "outline" only */ setfillpattern(&htable[hatch_index][0], col); #else /* Microsoft C */ _setcolor(col); _setfillmask(&htable[hatch_index][0]); #endif return(0); } /* end of set_hatch_fill */ /* ----------------------------------------------------------------------- */ PRIVATE int dda_line(int vdicolor, int x1, int y1, int x2, int y2) /* In the case of an X-Workstation, this Function draws a line from pixel position (x1,y1) to (x2,y2) in GXxor drawing mode (note two XOR's = no change) with the given vdicolor index, (virtual color indices being the SAME as the X-color indicies). In the case of a PC, this function first checks for the case of a horizontal or vertical line, otherwise it implements BRESENHAM'S algorithm to XOR-draw a line of dots from pixel position (x1,y1) to (x2,y2). NOTE that the XORing is done with the GKS VIRTUAL color indices, NOT with the hardware color indices (as is the case with Microsoft's _setwritemode(_GPSET or _GXOR) and Borland's setwritemode(COPY_PUT or XOR_PUT), and the latter call is _VRES16COLOR specific). This function is primarily used by rubberbanding routines when pixels along a line have to be saved/restored. */ { int id, dx, dy, adx, ady, dxsign, dysign, lowx, lowy; #if defined(DESQ) /* X-Workstation */ #else /* Borland C++, Microsoft C */ int i, x, y, es, curcolor, from, run; #endif /* compute relative displacements */ dx = x2 - x1; if (dx >= 0) { dxsign = 1; adx = dx; lowx = x1;} else { dxsign = -1; adx = -dx; lowx = x2;} dy = y2 - y1; if (dy >= 0) { dysign = 1; ady = dy; lowy = y1;} else { dysign = -1; ady = -dy; lowy = y2;} #if defined(DESQ) /* X-Workstation */ /* change GC function to XOR */ XSetFunction(gksdisplay, gksGC, GXxor); /* for X, COLINDEX() = identity() */ SETCOLOR(COLINDEX(vdicolor)); XDrawLine(gksdisplay, gkswindow, gksGC, x1, y1, x2, y2); /* restore GC function to COPY */ XSetFunction(gksdisplay, gksGC, GXcopy); #else /* Microsoft C, Borland C++ */ SETCOLOR(COLINDEX(vdicolor)); curcolor = vdicolor; /* Optimization: check for horizontal or vertical lines */ if (ady == 0) /* horizontal */ { x = 0; from = 0; run = 0; while (x <= adx) { if (GETPIXEL(lowx + x, y1) > 15) id = GETPIXEL(lowx + x, y1); else id = vga2vdi[ GETPIXEL(lowx + x, y1) ]; i = xormask & (id ^ vdicolor); if (curcolor != i) { if (run > 1) { MOVETO(lowx + from, y1); LINETO(lowx + x - 1, y1);} else if (run == 1) { SETPIXEL(lowx + x - 1, y1); } run = 1; from = x; curcolor = i; SETCOLOR(COLINDEX(curcolor)); } else { run++; } x++; } /* end of while (x <= adx) */ if (run > 1) { MOVETO(lowx + from, y1); LINETO(lowx + x - 1, y1); } else if (run == 1) { SETPIXEL(lowx + from, y1); } goto finish; } else if (adx == 0) /* vertical */ { y = 0; from = 0; run = 0; while (y <= ady) { if (GETPIXEL(x1, lowy + y) > 15) id = GETPIXEL(x1, lowy + y); else id = vga2vdi[ GETPIXEL(x1, lowy + y) ]; i = xormask & (id ^ vdicolor); if (curcolor != i) { if (run > 1) { MOVETO(x1, lowy + from); LINETO(x1, lowy + y - 1);} else if (run == 1) { SETPIXEL(x1, lowy + y - 1); } run = 1; from = y; curcolor = i; SETCOLOR(COLINDEX(curcolor)); } else { run++; } y++; } /* end of while (x <= adx) */ if (run > 1) { MOVETO(x1, lowy + from); LINETO(x1, lowy + y - 1); } else if (run == 1) { SETPIXEL(x1, lowy + y - 1); } goto finish; } /* NON-horizontal, NON-vertical */ /* case of adx >= ady */ if (adx >= ady) /* always increment horizontal */ { x = 0; y = 0; /* relative origin */ es = 2*ady - adx; loop1: /* draw in XOR mode with vdicolor */ if (GETPIXEL(x1 + dxsign*x, y1 + dysign*y) > 15) id = GETPIXEL(x1 + dxsign*x, y1 + dysign*y); else id = vga2vdi[ GETPIXEL(x1 + dxsign*x, y1 + dysign*y) ]; i = xormask & (id ^ vdicolor); if (curcolor != i) /* change color */ { curcolor = i; SETCOLOR(COLINDEX(curcolor)); } SETPIXEL(x1 + dxsign*x, y1 + dysign*y); if (x >= adx) goto finish; if (es >= 0) { y++; es = es - 2*adx; } es = es + 2*ady; x++; goto loop1; } /* end of case adx >= ady */ else /* case of ady > adx (interchange x and y) */ { x = 0; y = 0; /* relative origin */ es = 2*adx - ady; loop2: /* draw in XOR mode with brightwhite */ if (GETPIXEL(x1 + dxsign*x, y1 + dysign*y) > 15) id = GETPIXEL(x1 + dxsign*x, y1 + dysign*y); else id = vga2vdi[ GETPIXEL(x1 + dxsign*x, y1 + dysign*y) ]; i = xormask & (id ^ vdicolor); if (curcolor != i) /* change color */ { curcolor = i; SETCOLOR(COLINDEX(curcolor)); } SETPIXEL(x1 + dxsign*x, y1 + dysign*y); if (y >= ady) goto finish; if (es >= 0) { x++; es = es - 2*ady; } es = es + 2*adx; y++; goto loop2; } /* end of case ady > adx */ finish: #endif SETCOLOR(COLINDEX(lncolor)); /* restore drawing color */ return(0); } /* end of dda_line */ /* ------------------------------------------------------------------- */ PRIVATE int dda_rect(int vdicolor, int x1, int y1, int x2, int y2) /* This function is very similar to dda_line(), but instead of a line in XOR mode, it draws a bounding rectangle between the pixel corners (x1, y1) and (x2, y2) */ { int xpul, ypul, xplr, yplr; /* orient rectangle (xpul,ypul) to (xplr,yplr) */ if (x1 > x2) { xpul = x2; xplr = x1; } else { xpul = x1; xplr = x2; } if (y1 > y2) { ypul = y2; yplr = y1; } else { ypul = y1; yplr = y2; } #if defined(DESQ) /* X-Workstation */ /* change GC function to XOR */ XSetFunction(gksdisplay, gksGC, GXxor); /* for X, COLINDEX() = identity() */ SETCOLOR(COLINDEX(vdicolor)); RECTANGLE(0, xpul, ypul, xplr, yplr); /* restore GC function to COPY */ XSetFunction(gksdisplay, gksGC, GXcopy); #else /* Borland C++, Microsoft C */ dda_line(vdicolor, xpul, ypul, xplr, ypul); dda_line(vdicolor, xplr, ypul, xplr, yplr); dda_line(vdicolor, xplr, yplr, xpul, yplr); dda_line(vdicolor, xpul, yplr, xpul, ypul); #endif SETCOLOR(COLINDEX(lncolor)); /* restore drawing color */ return(0); } /* end of dda_rect */ /* ---------------------------------------------------------------------- */ #if defined(DESQ) #else /* Borland C++, Microsoft C */ int set_palette(int vga_index, long rgb) /* This routine is completely UNNECESSARY for an X-Workstation. In the case of a PC with VGA display, it changes RGB (encoded as long) for a single VGA index in the palette. It also handles differences between Borland C++ and Microsoft C. */ { #endif #if defined(DESQ) /* X-Workstation */ #elif defined(_DJGPP) /* DJGPP with BCC2GRX */ int r,g,b; r = (int)(rgb & 0x00003fL); g = (int)((rgb & 0x003f00L) >> 8); b = (int)((rgb & 0x3f0000L) >> 16); setrgbpalette(vga_index, r, g, b); return(0); } /* end of set_palette */ #elif defined(TURBEAUX) /* Borland C++ */ int r,g,b,pack; struct palettetype pal; if (screencode == _8514COLOR) /* Borland IBM8514 */ { /* getpalette does NOT work with the IBM8514 getpalette(&pal); */ r = (int)(rgb & 0x00003fL); g = (int)((rgb & 0x003f00L) >> 8); b = (int)((rgb & 0x3f0000L) >> 16); setrgbpalette(vga_index, r * 4, g * 4, b * 4); } if (screencode == _VRES16COLOR) /* Borland VGA */ { getpalette(&pal); /* Borland needs conversion of indices routine */ r = (int)(rgb & 0x00003fL); g = (int)((rgb & 0x003f00L) >> 8); b = (int)((rgb & 0x3f0000L) >> 16); setrgbpalette(pal.colors[vga_index], r, g, b); } else if (screencode == _ERESCOLOR) { /* EGA packing: 00RGBrgb */ pack = (int)(rgb & 0x000020L) | (int)((rgb & 0x000010L) >> 2); pack = pack | (int)((rgb & 0x002000L) >> 9) | (int)((rgb & 0x001000L) >> 11); pack = pack | (int)((rgb & 0x200000L) >> 18) | (int)((rgb & 0x100000L) >> 20); setpalette(vga_index, pack); } return(0); } /* end of set_palette */ #else /* Microsoft C */ REMAPPALETTE(vga_index, rgb); return(0); } /* end of set_palette */ #endif /* ----------------------------------------------------------------------- */ PRIVATE int set_all_palette(long col_array[]) /* In the case of an X-Workstation, this routine loads the current desired colors from the XColor array gkscolors[]. It also resets ForeGround and BackGround colors. In the case of a VGA display the full VGA palette (encoded as an array of long int's) is loaded. This routine also handles the differences between the Borland C++ compiler and the Microsoft C compiler */ { #if defined(DESQ) /* X-Workstation */ int i; /* xcolor_map has already been obtained and color cells Alloc'ed in init_adapter(), and default RGB values have been set from def_colorsarray[] in set_defaults() */ if (colorindices == 2) /* Monochrome: Map index 0 to BlackPixel and all non-zero indices to WhitePixel */ { gkscolors[0].pixel = BlackPixel(gksdisplay, gksscreen); for (i = 1 ; i < 16 ; i++) { gkscolors[i].pixel = WhitePixel(gksdisplay, gksscreen); gks_exactcolors[i].pixel = WhitePixel(gksdisplay, gksscreen); } } else for (i = 0 ; i < colorindices ; i++) { /* "pseudo" indices (internal index remapping by X11) have been set previously by XAllocColorCells() */ gkscolors[i].pixel = pseudo_index[i]; gks_exactcolors[i].pixel = pseudo_index[i]; gkscolors[i].flags = DoRed | DoGreen | DoBlue; XStoreColor(gksdisplay, xcolor_map, &gkscolors[i]); /* set all %-age based RGB to -1 (= invalid) so that first enqrgb() will FORCE binary to %-age conversion */ enq99rgb[i].last99red = -1; enq99rgb[i].last99green = -1; enq99rgb[i].last99blue = -1; } /* (Re)Set the GKSdisplay/gksGC background and foreground */ if (gks_startup.private_cmap == USE_DEFAULT_CMAP) { gksback = BlackPixel(gksdisplay, gksscreen); gksfore = WhitePixel(gksdisplay, gksscreen); } else if (gks_startup.private_cmap == USE_PRIVATE_CMAP) { gksback = 0L; gksfore = 7L; } XSetBackground(gksdisplay, gksGC, gksback); XSetForeground(gksdisplay, gksGC, gksfore); #elif defined(_DJGPP) /* DJGPP with BCC2GRX */ long rgb; int i,r,g,b; for (i = 0 ; i < colorindices ; i++) { rgb = col_array[i]; r = (int)(rgb & 0x00003fL); g = (int)((rgb & 0x003f00L) >> 8); b = (int)((rgb & 0x3f0000L) >> 16); setrgbpalette(i, r, g, b); } #elif defined(TURBEAUX) /* Borland C++ */ long rgb; int i,r,g,b,pack; struct palettetype pal; if (screencode == _8514COLOR) /* Borland IBM8514 */ { /* getpalette does NOT work with the IBM8514 getpalette(&pal); */ for (i = 0 ; i < 16 ; i++) { rgb = col_array[i]; r = (int)(rgb & 0x00003fL); g = (int)((rgb & 0x003f00L) >> 8); b = (int)((rgb & 0x3f0000L) >> 16); setrgbpalette(i, r * 4, g * 4, b * 4); } } if (screencode == _VRES16COLOR) /* Borland EGA */ { getpalette(&pal); /* Borland needs conversion of indices routine */ for (i = 0 ; i < pal.size ; i++) { rgb = col_array[i]; r = (int)(rgb & 0x00003fL); g = (int)((rgb & 0x003f00L) >> 8); b = (int)((rgb & 0x3f0000L) >> 16); setrgbpalette(pal.colors[i], r, g, b); } } else if (screencode == _ERESCOLOR) { /* EGA packing: 00RGBrgb */ for (i = 0 ; i < 16 ; i++) { rgb = col_array[i]; pack = (int)(rgb & 0x000020L) | (int)((rgb & 0x000010L) >> 2); pack = pack | (int)((rgb & 0x002000L) >> 9) | (int)((rgb & 0x001000L) >> 11); pack = pack | (int)((rgb & 0x200000L) >> 18) | (int)((rgb & 0x100000L) >> 20); setpalette(i, pack); } } #else /* Microsoft C */ REMAPALLPALETTE(col_array); #endif return(0); } /* end of set_all_palette */ /* --------------------------------------------------------------------- */ PRIVATE int rest_adapter(void) /* This is a COMPLETELY hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- Leaves Graphics Mode and Enters Text Mode Frees Graphics Context (GC) Destroys GKS X-Window(gkswindow) Closes the X-Display(gksdisplay) */ { #if defined(DESQ) /* X-Workstation */ XFreeGC (gksdisplay, gksGC); XDestroyWindow (gksdisplay, gkswindow); XCloseDisplay (gksdisplay); #elif defined(TURBEAUX) /* Borland C++ */ closegraph(); #else /* Microsoft C */ _setvideomode(_DEFAULTMODE); #endif return(0); } /* end of rest_adapter */ /* ======================================================================= PUBLIC PIXEL-DEPENDENT functions: xpix() ypix() xinvpix() yinvpix() xabspix() yabspix() xabsinvpix() yabsinvpix() put_mask() put_vect() gloc_pix() await_wk_event() set_defaults() stcursavearea() stviscursor() ======================================================================= General Remark about: xpix(), ypix(), xabspix()...xabsinvpix(), yabsinvpix() 1. We must deal with roundoff errors and since virtual coordinates are larger than pixel coordinates we adjust the integer truncations below so that: x[abs]pix(x[abs]invpix(X) = X, and y[abs]pix(y[abs]invpix(Y) = Y. 2. The abs-variants of the functions DO NOT adjust for Borland RELATIVE pixel coordinates when using clip rectangles less than full screen. ======================================================================= */ int xpix(int xvdl) /* Converts vdl coords to pixels - x axis */ { long xl, rl; int r; xl = xvdl; /* *** TRUNCATION *** adjustment: rl = (xl * vcxlong)/xvdlaxis; */ rl = (xl * vcxlong + (xvdlaxis >>1))/xvdlaxis; r = (int)rl; #if defined(TURBEAUX) if (fullviewind == 0) /* Borland viewport is in effect so adjust for RELATIVE pixel coordinates */ r = r - pixviewext[0]; #endif return(r); } /* end of xpix */ /* ---------------------------------------------------------------------- */ int ypix(int yvdl) /* Converts vdl coords to pixels - y axis */ { long yl, rl; int r; yl = yvdl; rl = (yvdlaxis - yl) * vcylong; /* NOTE: pixel origin is upper left */ /* *** TRUNCATION *** adjustment: rl = rl/yvdlaxis; */ rl = (rl + (yvdlaxis >>1))/yvdlaxis; r = (int)rl; #if defined(TURBEAUX) if (fullviewind == 0) /* Borland viewport is in effect so adjust for RELATIVE pixel coordinates */ r = r - pixviewext[1]; #endif return(r); } /* end of ypix */ /* ----------------------------------------------------------------------- */ int xinvpix(int xp) /* Converts DEVICE pixels to vdl coords - x axis. */ { long xl, rl; int r; xl = xp; #if defined(TURBEAUX) if (fullviewind == 0) /* Borland viewport is in effect so adjust for RELATIVE pixel coordinates */ xl = xp + pixviewext[0]; #endif /* *** TRUNCATION *** adjustment: rl = (xl * xvdlaxis)/vcxlong; */ rl = (xl * xvdlaxis + (vcxlong >>1))/vcxlong; r = (int)rl; return(r); } /* end of xinvpix */ /*----------------------------------------------------------------------- */ int yinvpix(int yp) /* Converts DEVICE pixels to vdl coords - y axis. */ { long yl, rl; int r; yl = yp; #if defined(TURBEAUX) if (fullviewind == 0) /* Borland viewport is in effect so adjust for RELATIVE pixel coordinates */ yl = yp + pixviewext[1]; #endif /* *** TRUNCATION *** adjustment: rl = (yl * yvdlaxis)/vcylong; */ rl = (yl * yvdlaxis - (vcylong >> 1))/vcylong; r = (int)(yvdlaxis - rl); return(r); } /* end of yinvpix */ /* ---------------------------------------------------------------------- */ int xabspix(int xvdl) /* Converts vdl coords to ABSOLUTE pixels - x axis, REGARDLESS whether Borland's viewport is active or not */ { long xl, rl; int r; xl = xvdl; /* *** TRUNCATION *** adjustment: rl = (xl * vcxlong)/xvdlaxis; */ rl = (xl * vcxlong + (xvdlaxis >>1))/xvdlaxis; r = (int)rl; return(r); } /* end of xabspix */ /* ---------------------------------------------------------------------- */ int yabspix(int yvdl) /* Converts vdl coords to ABSOLUTE pixels - y axis, REGARDLESS whether Borland's viewport is active or not. */ { long yl, rl; int r; yl = yvdl; rl = (yvdlaxis - yl) * vcylong; /* NOTE: pixel origin is upper left */ /* *** TRUNCATION *** adjustment: rl = rl/yvdlaxis; */ rl = (rl + (yvdlaxis >>1))/yvdlaxis; r = (int)rl; return(r); } /* end of yabspix */ /* ----------------------------------------------------------------------- */ int xabsinvpix(int xp) /* Converts ABSOLUTE pixels to vdl coords on the x axis, REGARDLESS whether Borland's viewport is active or not. It is used PRIMARILY by the GIN functions: reqlocator() reqvaluator() getlocator() but also when we need the x-size of a pixel: xabsinvpix(1) */ { long xl, rl; int r; xl = xp; /* *** TRUNCATION *** adjustment: rl = (xl * xvdlaxis)/vcxlong; */ rl = (xl * xvdlaxis + (vcxlong >>1))/vcxlong; r = (int)rl; return(r); } /* end of xabsinvpix */ /*----------------------------------------------------------------------- */ int yabsinvpix(int yp) /* Converts ABSOLUTE pixels to vdl coords on the y axis, REGARDLESS whether Borland's viewport is active or not. It is used PRIMARILY by the GIN functions: reqlocator() reqvaluator() getlocator() but also when we need the y-size of a pixel: yabsinvpix(1) */ { long yl, rl; int r; yl = yp; /* *** TRUNCATION *** adjustment: rl = (yl * yvdlaxis)/vcylong; */ rl = (yl * yvdlaxis - (vcylong >> 1))/vcylong; r = (int)(yvdlaxis - rl); return(r); } /* end of yabsinvpix */ /* ----------------------------------------------------------------------- */ int put_mask(char *cptr, int mode, int xpxl, int ypxl, int mag) /* This Function is used to generate text output for the PC when the textprecision is STRING (txprec = 0). It uses the XMASK x YMASK (currently 7 x 9) mask passed by REFERENCE with cptr. An optional integer magnification factor can be specified (1 <= mag <= 10), and the mode, REPLACE (mode=0), OVERLAY (mode=1), or (in the case of the PC only, since X-Workstations have a built in GXxor) XOR (mode=2), of transferring the raster mask can be specified as well. */ { int id, erase, i, j, l, xor, htimes; char cmask[YMASK], k; for (i = 0 ; i < YMASK ; i++) cmask[i] = *(cptr++); /* get row bytes */ if (mag < 1 || mag > 10) return(-1); /* 1 <= magnification <= 9 */ erase = 0; #if defined(DESQ) /* X-Workstation */ if (mode == 2) return(0); /* GXxor is built in */ #endif /* start in upper right corner: 01234560123456 0 s = start 1xxxxxxs e = end 2xxxxxxx . . ypxl--> 9exxxxxx xpxl-----^ NOTE: that the above alignment differs slightly from tektronix-style alignment in which underscore is actually a descender. */ xpxl = xpxl + (XMASK * mag) - 1; ypxl = ypxl - (YMASK * mag) + 1; for (i = 0 ; i < YMASK ; i++) /* (9 * mag) rows */ { htimes = 0; hrows: k = cmask[i]; /* reload k */ for (j = 0 ; j < XMASK ; j++) /* (7 * mag) dots per row */ { if (mode == 1) /* overlay */ { for (l = 0 ; l < mag ; l++) { if ((k & 0x01) != 0) SETPIXEL(xpxl--,ypxl); else xpxl--; /* skip pixel */ } } else if (mode == 0) /* replace */ { if ((k & 0x01) != 0) /* bit set */ { if (!erase) { ; } /* do nothing */ else { SETCOLOR(COLINDEX(txcolor)); erase = 0;} } else /* bit not set */ { if (erase) { ; } /* do nothing */ else { SETCOLOR(0); erase = 1;} } for (l = 0 ; l < mag ; l++) SETPIXEL(xpxl--,ypxl); } else if (mode == 2) /* xor */ { for (l = 0 ; l < mag ; l++) { if (k & 0x01) { if (GETPIXEL(xpxl, ypxl) > 15) id = GETPIXEL(xpxl, ypxl); else id = vga2vdi[ GETPIXEL(xpxl, ypxl) ]; xor = xormask & (id ^ txcolor); SETCOLOR(COLINDEX(xor)); SETPIXEL(xpxl--,ypxl); } else xpxl--; /* skip pixel */ } } k = (char)(k >> 1); /* shift k */ } xpxl = xpxl + (XMASK * mag); /* reset horizontal */ ++ypxl; ++htimes; if (htimes < mag) goto hrows; /* for magnification */ } if ( (erase) || (mode == 2) ) SETCOLOR(COLINDEX(txcolor)); return(0); } /* end of put_mask */ /* ----------------------------------------------------------------------- */ /* Problem: on SGI-Indy the keyword "__mips" IS defined and chars are unsigned by default */ #if defined(__sgi) int put_vect(signed char *cptr, int mode, int xpxl, int ypxl, int mag10, int theta, int xcolor) /* DEC VMS says ALL chars are "signed" (they should know) */ #elif defined(__vax) || defined(__mips) int put_vect(char *cptr, int mode, int xpxl, int ypxl, int mag10, int theta, int xcolor) #else int put_vect(signed char *cptr, int mode, int xpxl, int ypxl, int mag10, int theta, int xcolor) #endif /* This function is used to generate text output when the textprecision is STROKE (txprec = 2) and to generate MARKer output as well (character codes 127--136 in strk10[][]). It expects a short polyline formatted record to be passed by REFERENCE with cptr. The record should start with SHORT_PL as a key byte. This function is conceptually similar to put_mask() which is used to generate text output for PC's when textprecision is STRING (txprec = 0). However, the magnification factor mag10 is given in TENTHS (1 to 100) rather than in whole numbers since stroke can be more finely sized. There is also the option of specifying a rotation angle theta as well. Note that REPLACE mode (mode = 0) and OVERLAY mode (mode = 1) are the SAME (OVERLAY) for stroke. Also note that mode XOR (mode = 2) is supported. Finally, the color, as a virtual color index, is passed to this routine since it is used by BOTH gmark() and gtext(). */ { int i, xp, yp, delta_x, delta_y, magdelta_x, tmp, magdelta_y, count, xfrom, yfrom, draw, total_delta_x, total_delta_y, total_dx, total_dy; double xrel, yrel, dtheta, xsin, xcos, rads; if (mag10 < 1 || mag10 > 100) return(-1); /* mag out of range */ if (mode < 0 || mode > 2) return(-1); /* superfluous */ if (*cptr != SHORT_PL) return -1; /* bad SHORT_PL record */ count = *(++cptr); /* get count */ if (count < 1) return(-1); /* bad SHORT_PL record */ dtheta = (double)theta; /* some trigonometry */ rads = (6.283 * dtheta)/360.0; xsin = sin(rads); xcos = cos(rads); /* *** DIAGNOSTIC *** fprintf(stderr, "\nput_vect(\' \', mode=%d, xpxl=%d, ypxl=%d, mag10=%d ...)", mode, xpxl, ypxl, mag10); fflush(stderr); */ SETCOLOR(COLINDEX(xcolor)); /* change drawing color */ xp = xpxl; yp = ypxl; /* *** Modification for better quality (and slower draw) when using small fractional sizes on low resolution displays: delta_x = (mag10 * (*(++cptr)))/10; delta_y = (mag10 * (*(++cptr)))/10; */ total_dx = (int)*(++cptr); total_dy = (int)*(++cptr); delta_x = (mag10 * total_dx)/10; delta_y = (mag10 * total_dy)/10; total_delta_x = delta_x; total_delta_y = delta_y; if (theta != 0) /* apply rotation by theta */ { xrel = (double)delta_x; yrel = (double)delta_y; magdelta_x = (int)(xrel*xcos - yrel*xsin); magdelta_y = (int)(xrel*xsin + yrel*xcos); xfrom = xpxl + magdelta_x; yfrom = ypxl - magdelta_y; MOVETO(xfrom, yfrom); } else { xfrom = xp + delta_x; yfrom = yp - delta_y; MOVETO(xfrom, yfrom); /* move */ } xp = xp + delta_x; yp = yp - delta_y; /* update */ for (i = 2; i < count; i++) { /* *** DIAGNOSTIC *** fprintf(stderr, "\nxp=%d, yp=%d, delta_x=%d, delta_y=%d", xp, yp, delta_x, delta_y); fflush(stderr); */ tmp = (int)(*(++cptr)); if (tmp < -64) { draw = 0; tmp = tmp + 64; } else if (tmp >= 64) { draw = 0; tmp = tmp - 64; } else { draw = 1; } /* *** Modification for better quality (and slower draw) when using small fractional sizes on low resolution displays: delta_x = (mag10 * tmp)/10; delta_y = (mag10 * (*(++cptr)))/10; */ total_dx = total_dx + tmp; total_dy = total_dy + (int)*(++cptr); /* where we should be - our last actual position */ delta_x = ((mag10 * total_dx)/10) - total_delta_x; delta_y = ((mag10 * total_dy)/10) - total_delta_y; total_delta_x = total_delta_x + delta_x; total_delta_y = total_delta_y + delta_y; if (theta != 0) { xrel = (double)(xp + delta_x - xpxl); yrel = (double)(ypxl - (yp - delta_y)); magdelta_x = (int)(xrel*xcos - yrel*xsin); magdelta_y = (int)(xrel*xsin + yrel*xcos); if (draw) { if (mode != 2) { LINETO(xpxl + magdelta_x, ypxl - magdelta_y); } else { dda_line(xcolor, xfrom, yfrom, xpxl + magdelta_x, ypxl - magdelta_y); } } else { if (mode != 2) { MOVETO(xpxl + magdelta_x, ypxl - magdelta_y); } } xfrom = xpxl + magdelta_x; yfrom = ypxl - magdelta_y; } else /* if theta == 0 */ { if (draw) { if (mode != 2) { LINETO(xp + delta_x, yp - delta_y); } /* draw */ else { dda_line(xcolor, xfrom, yfrom, xp + delta_x, yp - delta_y); } } else { if (mode != 2) { MOVETO(xp + delta_x, yp - delta_y); } /* move */ } xfrom = xp + delta_x; yfrom = yp - delta_y; } xp = xp + delta_x; yp = yp - delta_y; /* update */ } return(0); } /* end of put_vect */ /* ----------------------------------------------------------------------- */ int gloc_pix(int xpxl, int ypxl) /* This function moves the current locator position, given PIXEL, as opposed to virtual, coordinates. It also updates (xlocplast, ylocplast). This routine assumes that any caller will have SETCLIPRGN to fullscreen BEFORE this call. */ { #if defined(DESQ) #else int m1,m2,m3,m4; #endif xlocplast = xpxl; ylocplast = ypxl; #if defined(DESQ) /* X-Workstation */ /* Move to Last Position */ XWarpPointer(gksdisplay, None, gkswindow, 0, 0, 0, 0, /* No source window */ xlocplast, ylocplast); #else /* Borland C++, Microsoft C */ m1 = 4; m3 = xlocplast; m4 = ylocplast; /* *** DIAGNOSTIC *** fprintf(stderr, "\ncalling gloc_pix(&4,&m2,&m3=%d,&m4=%d", m3, m4); fflush(stderr); */ /* PROBLEM: some PC Mouse drivers seem to ROUND-OFF values on command=m1=4 (e.g. mod 4 or mod 8) EVEN at lower resolutions. I don't know why, unless it relates to the use of an 8514 or SVGA software driver? */ MOUSECML(&m1,&m2,&m3,&m4); /* (re)SET cursor position */ #endif return(0); } /* end of gloc_pix */ /* ----------------------------------------------------------------------- */ int await_wk_event(unsigned mask, int *event, char str[], int *xpxl, int *ypxl) /* This function handles the basic differences between PC events (through the BIOS INT10h, and MOUSE INT33h calls) and X-Workstation Events (which are very powerful and are queued). One MAIN PROBLEM is the overhead of monitoring ALL motion events. However, this will be done if: (mask & MOUSE_MOTION) != 0 Another problem is (re)checking coordinates whenever a button/key is pressed/released. This will be done if: (mask & MOUSE_UPDATE) != 0 Finally, note that PC's and some X-Workstations cannot detect a keyboard key release. if (mask & SUPPRESS_KEYRELEASE) != 0 this will supress the key release event UNCONDITIONALLY. */ { #if defined(DESQ) /* X-Workstation */ int done, count, left, i; char tmptext[16]; Time lasttime; lasttime = 0; /* initialize */ XFlush(gksdisplay); /* make sure any prompts are out */ if ( (mask & MOUSE_MOTION) && (!(mask & SUPPRESS_KEYRELEASE)) ) XSelectInput(gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | KeyReleaseMask | ExposureMask | PointerMotionMask | ButtonReleaseMask ); else if ( (!(mask & MOUSE_MOTION)) && (!(mask & SUPPRESS_KEYRELEASE)) ) XSelectInput(gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | KeyReleaseMask | ExposureMask | ButtonReleaseMask ); else if ( (mask & MOUSE_MOTION) && (mask & SUPPRESS_KEYRELEASE) ) XSelectInput(gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | ExposureMask | PointerMotionMask | ButtonReleaseMask ); else XSelectInput(gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | ExposureMask | ButtonReleaseMask ); done = 0; while (done == 0) { left = 0; XNextEvent(gksdisplay, (XEvent *)&gksevent); switch (gksevent.type) { case Expose: /* Set the expose_flag if we have received the LAST contiguous Expose event */ if (gksevent.xexpose.count != 0) { expose_flag = 0; /* *** DIAGNOSTIC *** fprintf(stderr, "\n Expose Non-contiguous"); fflush(stderr) */ } else { expose_flag = 1; /* *** DIAGNOSTIC *** fprintf(stderr, "\n Expose Contiguous"); fflush(stderr); */ } break; case MappingNotify: /* Update keyboard knowledge */ XRefreshKeyboardMapping((XMappingEvent *)&gksevent); break; case ButtonRelease: left = 4; case ButtonPress: /* 3 button mouse will send: */ /* left='1' middle='3' right='2'*/ if (gksevent.xbutton.button == BUTTON_LEFT) { kloclast = 0x01; *event = 0x0001 << left; } else if (gksevent.xbutton.button == BUTTON_RIGHT) { kloclast = 0x02; *event = 0x0002 << left; } else { kloclast = 0x03; *event = 0x0004 << left; } str[0] = kloclast + '0'; str[1] = '\0'; if (mask & MOUSE_UPDATE) { *xpxl = gksevent.xbutton.x; *ypxl = gksevent.xbutton.y; } done = 1; break; case KeyRelease: left = 4; case KeyPress: /* Note that pushing SHIFT, for example, is an XKeyEvent so that XLookupString returns a KeySym BUT count = 0. */ count = XLookupString((XKeyEvent *)&gksevent, tmptext, /* ASCII temporary buffer */ 16, /* size of temporary buffer */ (KeySym *)&gkskey, /* get Key Symbol */ (XComposeStatus *)NULL); if (count == 0) { /* check for function/arrow keys */ if ( (gkskey == XK_F1) || (gkskey == XK_F2) || (gkskey == XK_F3) || (gkskey == XK_F4) || (gkskey == XK_F5) || (gkskey == XK_F6) || (gkskey == XK_F7) || (gkskey == XK_F8) || (gkskey == XK_Left) || (gkskey == XK_Up) || (gkskey == XK_Right) || (gkskey == XK_Down) ) { /* set NON-ascii bit */ *event = (0x0008 << left) | 0x0200; /* translate into scan codes */ XFKEY_TO_SCAN(gkskey, kloclast) str[0] = (char)kloclast; str[1] = '\0'; /* *** DIAGNOSTIC *** fprintf(stderr, "\nawait_wk_event: XFKEY_TO_SCAN str[0]=0x%2.2x ", (int)(str[0] & 0x00ff)); fflush(stderr); */ done = 1; /* update: may be arrow key */ if (mask & MOUSE_UPDATE) { *xpxl = gksevent.xkey.x; *ypxl = gksevent.xkey.y; /* *** DIAGNOSTIC *** fprintf(stderr, "\nawait_wk_event: MOUSE_UPDATE xpxl=%d ypxl=%d", *xpxl, *ypxl); fflush(stderr); */ } } } /* end of if (count == 0) */ else if (count >= 1) /* may get more than one ascii char if rebinding has been done */ { if (count > 15) count = 15; for (i = 0 ; i < count ; i++) str[i] = tmptext[i]; str[count] = '\0'; kloclast = tmptext[count - 1]; *event = 0x0008 << left; if (mask & MOUSE_UPDATE) { *xpxl = gksevent.xkey.x; *ypxl = gksevent.xkey.y; } done = 1; } /* end of if (count >= 1) */ break; case MotionNotify: lasttime = gksevent.xmotion.time; *xpxl = gksevent.xmotion.x; *ypxl = gksevent.xmotion.y; *event = 0x0100; /* *** DIAGNOSTIC *** fprintf(stderr, "\nawait_wk_event: MotionNotify: xpxl=%d ypxl=%d", *xpxl, *ypxl); fflush(stderr); */ done = 1; break; default: break; } /* end of switch */ } /* end of while */ return(0); /* end of X-Workstation */ #else /* Borland C++, Microsoft C */ int noerror,m1,m2,m3,m4,xmin,xmax,ymin,ymax,press,release; unsigned code; noerror = 1; if (mouseexist == 0) /* check that mouse driver loaded */ { *event = -1; noerror = 0; } if (noerror) { xmin = locpwindow[0]; xmax = locpwindow[2]; ymin = locpwindow[3]; ymax = locpwindow[1]; m1 = 7; MOUSECML(&m1,&m2,&xmin,&xmax); /* set GIN window */ m1 = 8; MOUSECML(&m1,&m2,&ymin,&ymax); /* now start checking events */ elocloop: m1 = 5; m2 = 0; /* left button */ MOUSECML(&m1,&m2,&m3,&m4); /* get button press times */ press = m2; m1 = 6; m2 = 0; MOUSECML(&m1,&m2,&m3,&m4); /* get button release times */ release = m2; if ((press - release) > 0) { /* LEFT_MOUSE_BUTTON_PRESS */ *event = 0x0001; kloclast = 1; str[0] = (char)(kloclast + '0'); str[1] = '\0'; awlastwasarrow = 0; /* reset */ goto check_pos; } else if ((press - release) < 0) { /* LEFT_MOUSE_BUTTON_RELEASE */ *event = 0x0010; kloclast = 1; str[0] = (char)(kloclast + '0'); str[1] = '\0'; awlastwasarrow = 0; /* reset */ goto check_pos; } m1 = 5; m2 = 1; /* right button */ MOUSECML(&m1,&m2,&m3,&m4); /* get button press times */ press = m2; m1 = 6; m2 = 1; MOUSECML(&m1,&m2,&m3,&m4); /* get button release times */ release = m2; if ((press - release) > 0) { /* RIGHT_MOUSE_BUTTON_PRESS */ *event = 0x0002; kloclast = 2; str[0] = (char)(kloclast + '0'); str[1] = '\0'; awlastwasarrow = 0; /* reset */ goto check_pos; } else if ((press - release) < 0) { /* RIGHT_MOUSE_BUTTON_RELEASE */ *event = 0x0020; kloclast = 2; str[0] = (char)(kloclast + '0'); str[1] = '\0'; awlastwasarrow = 0; /* reset */ goto check_pos; } if (mask & MOUSE_MOTION) { m1 = 11; MOUSECML(&m1,&m2,&m3,&m4); /* check if mouse moved */ if ((m3 != 0x0000) || (m4 != 0x0000)) { *event = 0x0100; m1 = 3; MOUSECML(&m1,&m2,&m3,&m4);/* get new position */ *xpxl = m3; *ypxl = m4; awlastwasarrow = 0; /* reset */ goto clean_up; } } code = bios_key(_KEYBRD_READY); /* get keyboard status */ if (code != 0) { /* PC BIOS CANNOT distinguish between KEY_PRESS and KEY_RELEASE, SUPPRESS_KEYRELEASE is ALWAYS active. */ *event = 0x0088; kloclast = bios_key(_KEYBRD_READ); if (kloclast & 0x00ff) /* ascii key */ { str[0] = (char)kloclast; } else /* get scan code and set NON-ascii bit */ { str[0] = (char)( ((unsigned)kloclast) >> 8 ); *event = *event | 0x0200; } str[1] = '\0'; /* Some PROBLEMs with PC Arrow keys, software video drivers, and round-off in MOUSECML: see my comments in gloc_pix() */ if ((*event) & 0x0200) { switch((unsigned)str[0]) { case 0x048: ; /* up-arrow */ case 0x04d: ; /* right-arrow */ case 0x050: ; /* down-arrow */ case 0x04b: ; /* left-arrow */ *xpxl = xlocplast; /* force the issue */ *ypxl = ylocplast; awlastwasarrow = 1; goto clean_up; default: ; } /* end of switch */ } /* end of if (event.. */ if (awlastwasarrow) { *xpxl = xlocplast; /* force the issue */ *ypxl = ylocplast; awlastwasarrow = 0; /* reset */ goto clean_up; } goto check_pos; } /* end of if (code !=.. */ goto elocloop; check_pos: if (mask & MOUSE_UPDATE) { m1 = 3; MOUSECML(&m1,&m2,&m3,&m4);/* get new position */ /* *** DIAGNOSTIC *** fprintf(stdout, "\nMOUSECML(&3,&m2=%d,&m3=%d,&m4=%d) ", m2, m3, m4); fflush(stdout); */ *xpxl = m3; *ypxl = m4; } clean_up: return(0); } /* end of if (noerror) ... */ else /* an error occured */ { return(-1); } #endif } /* end of await_wk_event */ /* ----------------------------------------------------------------------- */ extern int initdef_16colors(void); /* now in xstate.c */ /* ----------------------------------------------------------------------- */ int set_defaults(void) /* This is a hardware dependent function which essentially restores the GKS defaults, specifically: PC Platform X-Workstation -------------------------------------------------------------- Calls set_all_palette() Calls set_all_palette() Sets Font Metrics Sets Font Metrics Sets Other GKS Globals Sets Other GKS Globals This function is called by: gbeginframe() only. If the GKS variable is dynamic, an initialization call is done, otherwise (static) the global variable alone is set. */ { int i; #if defined(DESQ) /* X-Workstation */ wkcode = 100; wklevel = 0; /* support code/level */ #else /* PC with Borland C++, Microsoft C */ wkcode = 10; wklevel = 0; /* PC support code/level */ #endif bitsprecision = def_bitsprecision; /* 12 bits prec. */ xvdlaxis = def_xvdlaxis; yvdlaxis = def_yvdlaxis; /* aspect ratio = 3/4 */ tabletexist = 0; /* no tablet support yet */ tablettype = 0; /* set up default palette for first 16 (VGA) color indices only */ initdef_16colors(); #if defined(DESQ) /* convert VGA_def's to X_defs for FIRST 16 color indices ONLY */ for (i = 0 ; i < 16 ; i++) { gks_exactcolors[i].red = (unsigned short) ((def_colorsarray[vdi2vga[i]] & 0x0000ffL) << 10); gks_exactcolors[i].green = (unsigned short) ((def_colorsarray[vdi2vga[i]] & 0x00ff00L) << 2); gks_exactcolors[i].blue = (unsigned short) ((def_colorsarray[vdi2vga[i]] & 0xff0000L) >> 6); gkscolors[i].red = gks_exactcolors[i].red; gkscolors[i].green = gks_exactcolors[i].green; gkscolors[i].blue = gks_exactcolors[i].blue; } #endif set_all_palette(colorsarray); /* this routine handles X-Workstation/Borland/Microsoft palette differences */ xlast = 0; ylast = 0; xpixlast = 0; ypixlast = (int)vcylong; /* pixel origin upper left */ viewattrib = 0; /* wipe index fixed at 0 */ /* pixviewext[] goes from upper_left to lower_right */ pixviewext[0] = 0; pixviewext[1] = 0; pixviewext[2] = (int)vcxlong; pixviewext[3] = (int)vcylong; /* viewext[] goes from lower_left to upper_right */ viewextent[0] = 0; viewextent[1] = 0; viewextent[2] = (int)xvdlaxis; viewextent[3] = (int)yvdlaxis; viewport[0] = 0; viewport[1] = 0; viewport[2] = (int)xvdlaxis; viewport[3] = (int)yvdlaxis; SETCLIPRGN(0,0,(int)vcxlong,(int)vcylong); /* clip region */ fullviewind = 1; /* viewport is fullscreen */ clipind = 1; /* always clip viewport */ lntype = 0; SETLINESTYLE(LINE_SOLID); lncolor = 7; SETCOLOR(COLINDEX(lncolor)); lnwidth = 1; lnwidthalign = 0; lnmode = 1; mktype = 0; mkcolor = 7; mksize = 10; mkmode = 1; flpattern[0] = 0; flpattern[1] = 7; flpattern[2] = 0; flpattern[3] = 0; prmeter[0] = 0; prmeter[1] = 0; prmeter[2] = 7; prmeter[3] = 1; /* default is one pixel width */ txcolor = 7; txsize = 10; /* 10 tenths = normal size */ #if defined(DESQ) /* X-Workstation */ cellwidth = (int)(((deffontpointer->per_char->width)*xvdlaxis)/vcxlong); /* problem on monochrome VAXstations with above */ if (cellwidth == 0) { /* *** DIAGNOSTIC *** */ fprintf(stderr, "\ncellwidth=0 in set_defaults()...correcting\n"); fflush(stderr); cellwidth = XTextWidth(deffontpointer, "m", 1); cellwidth = (int)((cellwidth*xvdlaxis)/vcxlong); } /* STRING Cell height (for COMPATIBILITY with the PC platform) will be character ascent plus one pixel */ cellheight = (int)((((deffontpointer->ascent) + 1)*yvdlaxis)/vcylong); cellspace = (int)(xvdlaxis/vcxlong); #else /* Borland C++, Microsoft C, note that XMASK=7 and YMASK=9 but cellheight equals character ascent plus (possible) 1 pixel descent */ cellwidth = (int)(((long)XMASK * xvdlaxis)/vcxlong); cellheight = (int)((((long)YMASK + 1L) * yvdlaxis)/vcylong); cellspace = (int)(xvdlaxis/vcxlong); #endif vectwidth = (int)(((long)X_BOX * xvdlaxis)/vcxlong); vectheight = (int)(( ((long)Y_BOX + 1L) * yvdlaxis)/vcylong); vectspace = (int)(xvdlaxis/vcxlong); txpath = 0; txorient = 0; txprec = 0; /* string */ txmode = 1; /* overlay */ txpixoverride = 0; for (i = 0 ; i < 10 ; i++) echostate[i] = 0; /* echo */ echostate[1] = 1; /* string echo on */ for (i = 0 ; i < 10 ; i++) promptstate[i] = 1; /* prompt on */ locactive = -1; /* generic */ kloclast = 0; xloclast = 0; yloclast = (int)yvdlaxis; xlocplast = 0; ylocplast = 0; loccursor = 0; locgrid = 0; locband = 0; xlocpband = 0; ylocpband = 0; locgrid = 0; xmodgrid = 1; ymodgrid = 1; locwindow[0] = 0; locwindow[1] = 0; locwindow[2] = (int)xvdlaxis; locwindow[3] = (int)yvdlaxis; locpwindow[0] = 0; locpwindow[1] = (int)vcylong; locpwindow[2] = (int)vcxlong; locpwindow[3] = 0; strgactive = -1; /* generic */ strgwindow[0] = 0; strgwindow[1] = 0; strgwindow[2] = (int)xvdlaxis; strgwindow[3] = (int)yvdlaxis; stkactive = -1; /* generic */ pikactive = -1; /* generic */ xpiklast = 0; ypiklast = (int)yvdlaxis; xpikplast = 0; ypikplast = 0; pikcursor = 0; pikaperture = 8; pikwindow[0] = 0; pikwindow[1] = 0; pikwindow[2] = (int)xvdlaxis; pikwindow[3] = (int)yvdlaxis; choactive = -1; /* generic F1 .. F8 */ chocursor = 0; /* function key buttons */ chopwindow[0] = 0; /* 17 pixel lines */ chopwindow[1] = (int)vcylong - 5; chopwindow[2] = (int)vcxlong; chopwindow[3] = (int)vcylong - 21; valactive = -1; /* generic */ valcursor = 4; /* vertical bar */ valwinflag = 0; /* horizontal */ valwindow[0] = 0; valwindow[1] = 0; valwindow[2] = (int)xvdlaxis; valwindow[3] = (int)160; valmin = 0.0; valstart = 0.5; valmax = 1.0; vallast = 0.5; return(0); } /* end of set_defaults */ /* -------------------------------------------------------------------- */ int stcursavearea(int cpixel_window[]) /* This function is called whenever the Client-side Image in *cursaveimage is NULL or "stale." It is always 1. NULL on a PC or on ANY workstation which has LOCAL access to screen memory and does not have to call XGetImage() or the equivalent. 2. ESSENTIAL on an X-Workstation since X-Server and X-Client are separated by a network and XGetImage TAKES TIME so this window should be chosen to be AS SMALL AS POSSIBLE. It MUST be used BEFORE calling stviscursor() and should cover the area where the Cursor will be moved. NOTE: that the array contains PIXEL coordinates in the order: xlower_left, ylower_left, xupper_right, yupper_right. */ { int i; if ( (cpixel_window[2] < cpixel_window[0]) || /* insurance */ (cpixel_window[1] < cpixel_window[3]) ) return(-1); for (i = 0 ; i < 4 ; i++) curspwindow[i] = cpixel_window[i]; #if defined(DESQ) if (cursaveimagevalid == 1) /* de-allocate "stale" XImage */ { XDestroyImage(cursaveimage); cursaveimagevalid = 0; imagedesc[CURSAVE_XINDEX].valid = 0; imagedesc[CURSAVE_XINDEX].imageptr = (XImage *)NULL; } if (cursaveimagevalid == 0) { cursaveimage = XGetImage(gksdisplay, gkswindow, curspwindow[0], curspwindow[3], curspwindow[2] - curspwindow[0], curspwindow[1] - curspwindow[3], AllPlanes, XYPixmap); cursaveimagevalid = 1; imagedesc[CURSAVE_XINDEX].valid = 1; imagedesc[CURSAVE_XINDEX].bppixel = bitsppixel; imagedesc[CURSAVE_XINDEX].imageptr = (XImage *)cursaveimage; for (i = 0 ; i < 4 ; i++) imagedesc[CURSAVE_XINDEX].pwindow[i] = curspwindow[i]; imagedesc[CURSAVE_XINDEX].pwidth = curspwindow[2] - curspwindow[0] + 1; imagedesc[CURSAVE_XINDEX].pheight = curspwindow[1] - curspwindow[3] + 1; imagedesc[CURSAVE_XINDEX].bytes_alloc = (long)(imagedesc[CURSAVE_XINDEX].pwidth) * (long)(imagedesc[CURSAVE_XINDEX].pheight); } #endif return(0); } /* end of stcursavearea */ /* -------------------------------------------------------------------- */ int stviscursor(int xbmdesc, int xpixref, int ypixref, int visib) /* This function draws a Cursor (which, could have been built previously with cursfrombitmap() or as one of our standard cursors built in gbeginframe()) when it is given a valid descriptor (SAVING the screen underneath in .save_bits[]). It is primarily used to support the VALUATOR routine: reqvaluator() If an application running on an X-Workstation uses this, then: 1. the caller MUST call stcursavearea() FIRST before any loop calling this routine (otherwise, we will check for (cursaveimagevalid == 0) here and, if true, return -1. 2. the caller MUST reinitialize with stcursavearea() before using stviscursor() AFTER any reqvaluator() call. This function uses PIXEL COORDINATES to specify a reference point at (xpixref, ypixref). The upper left corner will then be put at PIXEL COORDINATES (xpixref - .curs_xh, ypixref - .curs_yh) The foreground color (corresponding to '1''s in the bitmap) used is .curs_fg. The background color is CURRENTLY IGNORED. If all goes well, this function returns 0. */ { int i, j, k, px, py, c, rowbytes, index, curcolor; unsigned char tb; /* Check Descriptor and Associated Cursor */ if ((xbmdesc < 0) || (xbmdesc >= max_descript)) return(-1); if (descript[xbmdesc].active == 0) return(-1); if (descript[xbmdesc].type != 2) return(-1); if (descript[xbmdesc].assoccurs == 0) return(-1); #if defined(DESQ) if (cursaveimagevalid == 0) return(-1); /* stcursavearea() has NOT been called FIRST and CURS_GETPIXEL below would fail BADLY. */ #endif /* Borland C++, Microsoft C */ px = xpixref - descript[xbmdesc].curs_xh; py = ypixref - descript[xbmdesc].curs_yh; if (descript[xbmdesc].curs_fg > 15) c = descript[xbmdesc].curs_fg; else c = vdi2vga[ descript[xbmdesc].curs_fg ]; SETCOLOR(c); curcolor = c; /* need to record current color */ rowbytes = (descript[xbmdesc].width)/8; for (i = 0 ; i < (descript[xbmdesc].height) ; i++) for (j = 0 ; j < rowbytes ; j++) { tb = descript[xbmdesc].bits[(i * rowbytes) + j]; /* byte */ for (k = 0 ; k < 8 ; k++) { if (visib) /* save and post */ { #if defined(DESQ) descript[xbmdesc].save_bits[(i * rowbytes * 8) + (j * 8) + k] = (char)CURS_GETPIXEL(px + (j * 8) + k, py + i); if ((tb & 0x01) != 0x00) SETPIXEL(px + (j * 8) + k, py + i); #else descript[xbmdesc].save_bits[(i * rowbytes * 8) + (j * 8) + k] = (char)GETPIXEL(px + (j * 8) + k, py + i); if ((tb & 0x01) != 0x00) SETPIXEL(px + (j * 8) + k, py + i); #endif } else /* restore */ { if ((tb & 0x01) != 0x00) { index = descript[xbmdesc].save_bits[(i * rowbytes * 8) + (j * 8) + k]; if (index != curcolor) { SETCOLOR(index); /* change color */ curcolor = index; /* current color */ } SETPIXEL(px + (j * 8) + k, py + i); } } /* end of if (visib) ... else ... */ tb = (unsigned char)(tb >> 1); /* next bit */ } /* end of for (k = 0 ; ... */ } /* end of for (j = 0 ; ... */ /* Restore Color */ SETCOLOR(COLINDEX(lncolor)); return(0); } /* end of stviscursor */ /* ======================================================================= Virtual Device Layer with GKS primitives: (* = not fully functional, ** = not functional) PRELIMINARY: cmdline_startup(cargc, cargv) reportstatus(array_size,report_array) FIRST: initvdi(code,level) enqdispres(&x_pixels(long),&y_pixels(long)) enqlocstate(&type,&last_xvdl,&last_yvdl) enqvideo(&type) initcoor(max_x_vdl(long),max_y_vdl(long)) **gviewattributes(background_color_index) **gviewextent(x_ll,y_ll,x_ur,y_ur) **gviewport(x_ll,y_ll,x_ur,y_ur) setcliprect(x_ll,y_ll,x_ur,y_ur) fullview = enqcliprect(&xll,&yll,&xur,&yur) grgbmap(color_index,red,green,blue) enqrgb(color_index,&red,&green,&blue) rgb2hls(red,green,blue,&hue,&lite,&sat) hls2rgb(hue,lite,sat,&red,&green,&blue) ghlsmap(color_index,hue,lightness,saturation) enqhls(color_index,&hue,&lite,&sat) START FRAME - RESET ALL DEFAULTS: gbeginframe(name_of_frame) gclearscreen() gpolyline(x_array,y_array,number_of_points) glinecolor(color_index) glinetype(type_index) glinewidth(width_in_pixels, width_alignment) glinemode(mode) gmove(x_vdl,y_vdl) gdraw(x_vdl,y_vdl) gpolymarker(x_array,y_array,number_of_points) gmarkercolor(color_index) gmarkertype(type_index) gmarkersize(size_in_tenths_of_normal_size) gmarkermode(mode) gmark(x_vdl,y_vdl) enqcharcell(&width,&height,&space) enqvectcell(&width,&height,&space) enqtextwidth(string) enqtextextent(x_vdl,y_vdl,string,&x_vdlend,&y_vdlend, &xll,&yll,&xur,&yur) gtext(x_vdl,y_vdl,string) gappendtext(string) (also called gputs()) gtextcolor(color_index) gtextsize(size_in_tenths_of_normal_size) gtextorient(degrees) gtextpath(degrees) gtextprecision(prec) gtextmode(mode) cellarray(xll,yll,xur,yur,xcells,ycells,ca_array) garc(center_x,center_y,rad,from,to) gellipse(ll_x,ll_y,ur_x,ur_y) grectangle(ll_x,ll_y,ur_x,ur_y) gpolygon(x_array,y_array,number_of_points) gsetpattern(patt_index, col=8, row=8, col_array) gfillpattern(intstyle,color_index,pattern,hatch) gperimeter(~visibility,type,color_index,width) ggetimage(ll_x,ll_y,width,height,&pixel_wd,&pixel_ht, plane_mask,format) enqimage(desc,&pixel_wd,&pixel_ht,&plane_mask,&format, &(struct _cmap )colormap) ggetimagepixel(desc,xpx,ypx) gputimage(desc,ll_x,ll_y,xmag,ymag,action) gfreeimage(desc) setechostate(echostate_array) setpromptstate(promptstate_array) initstring(idev,igwin,xll,yll,xur,yur) reqstring(idev,max_allowed,string,&actual_length) initlocator(idev,igwin,cseg,xll,yll,xur,yur,grid,band) enq_expose(clear_flag) **creatsegment(int_name,xpivot,ypivot) **closesegment() **insrtsegment(int_old) **deletsegment(int_name) **renamsegment(int_old,int_new) stvissegment(int_name,visibility_flag) **sthltsegment(int_name,highlight_flag) **stdetsegment(int_name,detectability_flag) **stprisegment(int_name,priority_level) **stpidsegment(pick_id) **sttrnsegment(int_name,(real)xscale,(real)yscale, (real)degree,new_xpivot,new_ypivot) **renewview(int_view) gloc(x_vdl,y_vdl) ggrid(xmod_vdl,ymod_vdl) gpick(x_vdl,y_vdl) gbell() reqlocator(idev,&status,&key,&x_vdl,&y_vdl) initpick(pdev,igwin,cseg,xll,yll,xur,yur,pick_apert) reqpick(pdev,&status,&key,&x_vdl,&y_vdl,&seg,&pickid) (note: seg = 0, pickid = 0 ALWAYS in above) initvaluator(vdev,igwflag,cseg,xll,yll,xur,yur, (real)xmin,(real)xstart,(real)xmax) reqvaluator(vdev,&status,(real)&value,&x_vdl,&y_vdl) initchoice(cdev,cseg) reqchoice(cdev,&function_key_number) begindialog() enddialog() mflush() flushdeviceevents() getlocator(idev,&status,&key,&x_vdl,&y_vdl) ENDFRAME: gendframe() LAST: closevdi() ========================================================================= */ int reportstatus(int arr_size, int ra[]) /* This function is the ONLY function which can be called BEFORE initvdi(). It SHOULD BE USED to try to find out the workstation_code and other information (workstation_code, workstation_level=0, colorindices, default_locator, default_string, ... ) which the user program can use first calling initvdi() and later on in using the GKS library. The array size should be AT LEAST 32 (for future expansion) and values are returned as follows: ra[0] = workstation_code = 10 (PC) or 100 (X-Workstation) ra[1] = workstation_level = 0 (NO dynamic segments) ra[2] = modified (0-40) screencode ra[3] = def_locator_dev ra[4] = def_string_dev ra[5] = def_stroke_dev ra[6] = def_pick_dev ra[7] = def_choice_dev ra[8] = def_valuator_dev ra[9] = colorindices (if 2, monochrome, otherwise 16, 256) ra[10] = mouseexist ra[11] = tabletexist This is a hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- Calls init_adapter() Calls init_adapter() Checks PC Mouse Sets colorindices Sets colorindices */ { #if defined(DESQ) /* X-Workstation */ #else /* Borland C++, Microsoft C */ int m1,m2,m3,m4; #endif if (arr_size < 12) { fprintf(stderr, "Not enough space to reportstatus. \n"); fflush(stderr); exit(-1); } #if defined(DESQ) /* X-Workstation */ wkcode = 100; wklevel = 0; /* support code/level */ #else /* PC with Borland C++, Microsoft C */ wkcode = 10; wklevel = 0; /* PC support code/level */ #endif ra[0] = wkcode; /* PC is wkcode = 10 */ ra[1] = 0; /* no dynamic segments */ dyn_segments = 0; if (init_adapter() == 0) /* set up for graphics */ { fprintf(stderr, "set graphics mode has failed \n"); fflush(stderr); exit(-2); } /* initialize the Segment/Bitmap/Image tables */ if ( (descript_initdone == 0) || (imagedesc_initdone == 0) ) init_descript(); #if defined(DESQ) /* X-Workstation */ mouseexist = 1; /* an X-Workstation ALWAYS has a mouse */ mousetype = 2; #else /* Borland C++, Microsoft C */ m1 = 0; /* get mouse locator information */ MOUSECML(&m1,&m2,&m3,&m4); if (m1 == 0) mouseexist = 0; else mouseexist = 1; if (m1 != 0) mousetype = m2; else mousetype = -1; /* mousetype is: -1 = generic 2 = (2-button) microsoft 3 = (3-button) msmouse */ #endif tabletexist = 0; /* no tablet support yet */ def_locator_dev = mousetype; def_string_dev = -1; def_stroke_dev = -2; /* not supported */ def_pick_dev = mousetype; def_choice_dev = -1; def_valuator_dev = mousetype; colorindices = 16; /* default if we CAN'T find adapter */ xormask = 0x000f; /* default */ bitsppixel = 4; /* default */ if (screencode == _HRESBW) { ra[2] = 0; colorindices = 2; bitsppixel = 1; } if (screencode == _HRES16COLOR) { ra[2] = 2; colorindices = 16;} if (screencode == _ERESCOLOR) { ra[2] = 3; colorindices = 16;} if (screencode == _VRES16COLOR) { ra[2] = 4; colorindices = 16;} if (screencode == _8514COLOR) { ra[2] = 5; colorindices = 256;} /* typical PC: a plethora of different SVGA video modes */ if ( (screencode >= 0x0100) && (screencode <= 0x0107) ) switch(screencode) { case 0x0100: ra[2] = screencode; colorindices = 256; break; case 0x0101: ra[2] = screencode; colorindices = 256; break; case 0x0102: ra[2] = screencode; colorindices = 16; break; case 0x0103: ra[2] = screencode; colorindices = 256; break; case 0x0104: ra[2] = screencode; colorindices = 16; break; case 0x0105: ra[2] = screencode; colorindices = 256; break; case 0x0106: ra[2] = screencode; colorindices = 16; break; case 0x0107: ra[2] = screencode; colorindices = 256; break; } /* end of switch */ #if defined(DESQ) if (screencode == _XDISPLAY) { ra[2] = 40; /* normally: DisplayCells = 2**DisplayPlanes */ colorindices = DisplayCells(gksdisplay, gksscreen); } if ( (Xcolorindices < colorindices) && (Xcolorindices >= 2) ) colorindices = Xcolorindices; #endif if (colorindices > 16) { xormask = 0x00ff; /* adjust */ bitsppixel = 8; } ra[3] = def_locator_dev; ra[4] = def_string_dev; ra[5] = def_stroke_dev; ra[6] = def_pick_dev; ra[7] = def_choice_dev; ra[8] = def_valuator_dev; ra[9] = colorindices; ra[10] = mouseexist; ra[11] = tabletexist; reportdone = 1; /* let initvdi() know report done */ return(0); } /* end of reportstatus */ /* ---------------------------------------------------------------------- */ int initvdi(int code, int level) /* This function begins the GKS graphics session and MUST be the FIRST GKS routine called. It returns a simplified code This is a hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- Calls reportstatus() if the Calls reportstatus() if the User Didn't User Didn't Allocates Some PC Memory Maps the GKS X-Window and waits for the Expose Event */ { int ret, tmparr[32]; if ((code != 10) && (code != 100)) { fprintf(stderr, "Use workstation code 10 for PC's, 100 for X-Workstations.\n"); fflush(stderr); exit(-1); } if (level > 0) { fprintf(stderr, "No segment support available. \n"); fflush(stderr); exit(-1); } if (reportdone == 0) /* user didn't call reportstatus() */ { ret = reportstatus(32, tmparr); if (ret < 0) { fprintf(stderr, "reportstatus() failed. \n"); fflush(stderr); exit(-1); } } #if defined(DESQ) /* X-Workstation */ /* XMapRaised() has been moved from init_adapter() to here in case reportstatus() was called first. */ XSelectInput (gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | ExposureMask ); XMapRaised(gksdisplay, gkswindow); /* Await ExposeEvent after Mapping */ do { XNextEvent(gksdisplay,(XEvent *)&gksevent); } while (gksevent.type != Expose); #endif curpage = 0; alloc_mem(); /* allocate some buffer space */ return(screencode); /* return type of PC graphics */ } /* end of initvdi */ /* ----------------------------------------------------------------------- */ int enqdispres(long *pxpixels, long *pypixels) /* This function returns the actual horizontal and vertical pixel resolution of the PC display (or window on the X-Workstation) */ { *pxpixels = vcxlong; *pypixels = vcylong; return(0); } /* end of enqdispres */ /* ---------------------------------------------------------------------- */ int enqlocstate(int *ptype, int *plast_xvdl, int *plast_yvdl) /* this function returns the type of the current ACTIVE locator as follows: -1 = unspecified 0 = tektronix-style joydisk 2 = microsoft 2-button mouse 3 = msmouse 3-button mouse 4 = arrow keys 8 = summagraphics-style tablet, and the last vdl locator coordinates */ { if (mouseexist == 0) *ptype = -1; /* generic */ else *ptype = mousetype; *plast_xvdl = xloclast; *plast_yvdl = yloclast; return(0); } /* end of enqlocstate */ /* ---------------------------------------------------------------------- */ int enqvideo(int *ptype) /* this function returns a simpler code (except for SVGA-modes) for the type of video: 0 = mda on PC 2 = l_ega on PC 3 = ega on PC 4 = vga on PC 5 = 8514 on PC ... x0102 = svga(0x0102) on PC ... x0104 = svga(0x0104) on PC ... 40 = window on X-Workstation 4100 = tektronix generic 4100 4105 = tektronix 4105 4107 = tektronix 4105 ...etc... */ { if (screencode == _HRESBW) {*ptype = 0; return(0);} if (screencode == _HRES16COLOR) {*ptype = 2; return(0);} if (screencode == _ERESCOLOR) {*ptype = 3; return(0);} if (screencode == _VRES16COLOR) {*ptype = 4; return(0);} if (screencode == _8514COLOR) {*ptype = 5; return(0);} /* typical PC: a plethora of different SVGA video modes */ if ( (screencode >= 0x0100) && (screencode <= 0x0107) ) {*ptype = screencode; return(0);} if (screencode == _XDISPLAY) {*ptype = 40; return(0);} return(-1); } /* end of enqvideo */ /* ---------------------------------------------------------------------- */ int initcoor(long max_x_vdl, long max_y_vdl) /* this changes the defaults of 4095 by 3071 for the virtual coord. system. If used, it should called BEFORE gbeginframe() */ { def_xvdlaxis = max_x_vdl; def_yvdlaxis = max_y_vdl; return(0); } /* end of initcoor */ /* ----------------------------------------------------------------------- */ int gviewattributes(int bground_index) /* This function is really a Tektronix 4100-type call. It is NON-OPERATIONAL here since index 0 which is also the 'erase' or 'wipe' index is the background color on MOST systems. It is better to LEAVE THIS INDEX AT 0 and use ghlsmap(). */ { if (bground_index < 0 || bground_index > 15) return(-1); return(-1); } /* end of gviewattributes */ /* ----------------------------------------------------------------------- */ int gviewextent(int xll, int yll, int xur, int yur) /* This function is really a Tektronix 4100-type call. It is NON-OPERATIONAL here since one CANNOT set viewextent and viewport INDEPENDENTLY. USE setcliprect() instead. */ { int i; i = xll; i = yll; i = xur; i = yur; i = -1; return(i); } /* end of gviewextent */ /* ----------------------------------------------------------------------- */ int gviewport(int xll, int yll, int xur, int yur) /* This function is is really a Tektronix 4100-type call. It is NON-OPERATIONAL here since one you CANNOT set viewextent and viewport INDEPENDENTLY. USE setcliprect() instead. */ { int i; i = xll; i = yll; i = xur; i = yur; i = -1; return(i); } /* end of gviewport */ /* ----------------------------------------------------------------------- */ int setcliprect(int xll, int yll, int xur, int yur) /* This function sets viewextent and viewport to be the SAME (i.e. it sets a clip rectangle only). WARNING: clip regions and GIN windows CAN CONFLICT -- be sure you reset clip region before using GIN. */ { int i,xpixul,ypixul,xpixlr,ypixlr; if ( (xll > xur) || (yll > yur) ) /* check corners */ { fprintf(stderr, "\nsetcliprect: required: xll=%d < xur=%d and yll=%d < yur=%d", xll, xur, yll, yur); fflush(stderr); } if ( (xll == 0) && (yll == 0) && (xur == (int)xvdlaxis) && (yur == (int)yvdlaxis) ) fullviewind = 1; else /* record whether full viewport */ fullviewind = 0; xpixul = xabspix(xll); ypixul = yabspix(yur); xpixlr = xabspix(xur); ypixlr = yabspix(yll); /* pixviewext[] goes from upper_left to lower_right */ pixviewext[0] = xpixul; pixviewext[1] = ypixul; /* record pix */ pixviewext[2] = xpixlr; pixviewext[3] = ypixlr; SETCLIPRGN(xpixul,ypixul,xpixlr,ypixlr); /* clip region */ /* viewext[] goes from lower_left to upper_right */ viewextent[0] = xll; viewextent[1] = yll; /* record vdl */ viewextent[2] = xur; viewextent[3] = yur; /* set viewport[] = viewextent[] */ for (i = 0 ; i < 4 ; i++) viewport[i] = viewextent[i]; return(0); } /* end of setcliprect */ /* ----------------------------------------------------------------------- */ int enqcliprect(int *xll, int *yll, int *xur, int *yur) /* This function allows a procedure to enquire what the current cliprectangle is. If it is fullscreen, then enqcliprect returns 1, otherwise it returns 0. */ { /* viewext[] goes from lower_left to upper_right */ *xll = viewextent[0]; *yll = viewextent[1]; *xur = viewextent[2]; *yur = viewextent[3]; return(fullviewind); } /* ----------------------------------------------------------------------- */ extern int grgbmap(int index, int red, int green, int blue); /* xstate.c */ /* ----------------------------------------------------------------------- */ int enqrgb(int index, int *pred, int *pgreen, int *pblue) /* this function gets the current rgb levels on a scale from 0 -- 99 for the color index */ { int top, hexred, hexgreen, hexblue; #if defined(DESQ) /* X-Workstation */ XColor actual_xcolor; if (colorindices > 16) top = (colorindices - 1); else top = 15; if (index < 0 || index > top) return(-1); /* out of range */ actual_xcolor.red = gkscolors[index].red; actual_xcolor.green = gkscolors[index].green; actual_xcolor.blue = gkscolors[index].blue; /* right hand sides are unsigned short */ hexred = actual_xcolor.red >> 8; hexgreen = actual_xcolor.green >> 8; hexblue = actual_xcolor.blue >> 8; if (enq99rgb[index].last99red >= 0) *pred = enq99rgb[index].last99red; else *pred = (99 * hexred)/255; if (enq99rgb[index].last99green >= 0) *pgreen = enq99rgb[index].last99green; else *pgreen = (99 * hexgreen)/255; if (enq99rgb[index].last99blue >= 0) *pblue = enq99rgb[index].last99blue; else *pblue = (99 * hexblue)/255; #else /* Borland C++, Microsoft C */ int id; long l; if (colorindices > 16) top = (colorindices - 1); else top = 15; if (index < 0 || index > top) return(-1); /* out of range */ if (index > 15) id = index; else id = vdi2vga[index]; l = colorsarray[id]; /* get setting */ hexred = (int)(l & 0x0000ffL); hexgreen = (int)((l & 0x00ff00L) >> 8); hexblue = (int)((l & 0xff0000L) >> 16); *pblue = (99 * hexblue)/63; *pgreen = (99 * hexgreen)/63; *pred = (99 * hexred)/63; #endif return(0); } /* end of enqrgb */ /* ---------------------------------------------------------------------- */ int rgb2hls(int red, int green, int blue, int *phue, int *plite, int *psat) /* this function converts the RGB color system (ranges 0 -- 99) to the HLS color system (ranges 0 -- 359 0 -- 99 0 -- 99. */ { double xr,xg,xb,max,min,hue,lite,sat,r,g,b; xr = (double)red/99.0; if (xr > 1.0) xr = 1.0; xg = (double)green/99.0; if (xg > 1.0) xg = 1.0; xb = (double)blue/99.0; if (xb > 1.0) xb = 1.0; max = 0.0; /* find max */ if (xr > max) max = xr; if (xg > max) max = xg; if (xb > max) max = xb; min = 1.0; /* find min */ if (xr < min) min = xr; if (xg < min) min = xg; if (xb < min) min = xb; if (max == min) /* case: red = green = blue */ { lite = max; sat = 0.0; hue = 0.0; } else /* case: max > min */ { r = (max - xr)/(max - min); g = (max - xg)/(max - min); b = (max - xb)/(max - min); /* note that at least one of these is 0.0 , at least one is 1.0 */ lite = (max + min)/2.0; /* lightness */ if (lite <= 0.5) /* saturation */ sat = (max - min)/(max + min); else sat = (max - min)/(2.0 - max - min); if (xr == max) /* hue */ hue = 60.0 * (2.0 + b - g); else if (xg == max) hue = 60.0 * (4.0 + r - b); else hue = 60.0 * (6.0 + g - r); } if (hue >= 359.9) hue = hue - 360.0; lite = 99.0 * lite; if (lite > 99.0) lite = 99.0; sat = 99.0 * sat; if (sat > 99.0) sat = 99.0; *phue = (int)hue; *plite = (int)lite; *psat = (int)sat; return(0); } /* end of rgb2hls */ /* ---------------------------------------------------------------------- */ extern int hls2rgb(int hue, int lite, int sat, int *pred, int *pgreen, int *pblue); /* now in xstate.c */ /* ---------------------------------------------------------------------- */ extern int ghlsmap(int index, int hue, int lite, int sat); /* xstate.c */ /* ---------------------------------------------------------------------- */ int enqhls(int index, int *phue, int *plite, int *psat) /* this function returns the current hls levels on scales 0 -- 359 0 -- 99 0 -- 99 */ { int top, hexred, hexgreen, hexblue; int red, green, blue; #if defined(DESQ) /* X-Workstation */ XColor actual_xcolor; if (colorindices > 16) top = (colorindices - 1); else top = 15; if (index < 0 || index > top) return(-1); /* out of range */ actual_xcolor.red = gkscolors[index].red; actual_xcolor.green = gkscolors[index].green; actual_xcolor.blue = gkscolors[index].blue; /* right hand sides are unsigned short */ hexred = actual_xcolor.red >> 8; hexgreen = actual_xcolor.green >> 8; hexblue = actual_xcolor.blue >> 8; blue = (99 * hexblue)/255; green = (99 * hexgreen)/255; red = (99 * hexred)/255; #else /* Borland C++, Microsoft C */ int id; long l; if (colorindices > 16) top = (colorindices - 1); else top = 15; if (index < 0 || index > top) return(-1); /* out of range */ if (index > 15) id = index; else id = vdi2vga[index]; l = colorsarray[id]; /* get setting */ hexred = (int)(l & 0x0000ffL); hexgreen = (int)((l & 0x00ff00L) >> 8); hexblue = (int)((l & 0xff0000L) >> 16); blue = (99 * hexblue)/63; green = (99 * hexgreen)/63; red = (99 * hexred)/63; #endif rgb2hls(red,green,blue,phue,plite,psat); /* convert to HLS */ return(0); } /* end of enqhls */ /* ----------------------------------------------------------------------- */ int gbeginframe(char *name) /* This function starts a new Frame (resetting all the GKS defaults and clearing the screen) with the given name and returns the page number. In the case of an X-Workstation, it also enquires (from the window manager) whether the window has been RESIZED. If it has, it CORRECTS the values of: vcxlong and vcylong and the main() program can call enqdispres() to find these new values. This is a hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- Checks vcxlong and vcylong to See if X-Window has Been Resized. Calls set_defaults() Calls set_defaults() Checks that Bitmaps and Cursors are Ready Clears the Screen Clears the Screen */ { int gclearscreen(void); #if defined(DESQ) /* X-Workstation */ int i; #endif strncpy(gframename, name, 63); #if defined(DESQ) /* Check for window resize BEFORE set_defaults */ XGetWindowAttributes(gksdisplay, gkswindow, &xwinattr); /* Don't allow ridiculously small windows */ if (xwinattr.width > 10) vcxlong = (long)xwinattr.width - 1; if (xwinattr.height > 10) vcylong = (long)xwinattr.height - 1; #endif set_defaults(); /* set all defaults before we build Cursors */ #if defined(DESQ) /* X-Workstation only */ /* Check Pattern if we have a Color Display */ if ((patt_exist == 0) && (colorindices > 2)) { tilepixmap = XCreatePixmapFromBitmapData(gksdisplay, gkswindow, &ptable[0][0], 8, 8, gkscolors[vga2xwin[0]].pixel, gkscolors[vga2xwin[0]].pixel, DisplayPlanes(gksdisplay, gksscreen)); XCopyGC(gksdisplay, gksGC, 0L, tempGC); /* update tempGC */ for (i = 0 ; i < 16 ; i++) { pattpixmap[i] = XCreatePixmapFromBitmapData(gksdisplay, gkswindow, &ptable[i][0], 8, 8, gkscolors[vga2xwin[i]].pixel, gkscolors[vga2xwin[0]].pixel, DisplayPlanes(gksdisplay, gksscreen)); pattbmp[i] = XCreateBitmapFromData(gksdisplay, gkswindow, &ptable[i][0], 8, 8); XSetClipMask(gksdisplay, tempGC, pattbmp[i]); XSetForeground(gksdisplay, tempGC , gkscolors[vga2xwin[i]].pixel); XCopyArea(gksdisplay, pattpixmap[i], tilepixmap, tempGC, 0, 0, 8, 8, 0, 0); } patt_exist = 1; } /* Check Hatch */ if (hatch_exist == 0) { for (i = 0 ; i < 8 ; i++) hatchbmp[i] = XCreateBitmapFromData(gksdisplay, gkswindow, &htable[i][0], 8, 8); hatch_exist = 1; } /* Check if main Cursors exist */ if (arrcurs_exist == 0) { arrcurs = XCreateFontCursor(gksdisplay, XC_arrow); arrcurs_exist = 1; } XDefineCursor(gksdisplay, gkswindow, arrcurs); /* DEFAULT */ if (gkscurs_exist == 0) { gkscurs = XCreateFontCursor(gksdisplay, XC_crosshair); gkscurs_exist = 1; } if (waitcurs_exist == 0) { waitcurs = XCreateFontCursor(gksdisplay, XC_watch); waitcurs_exist = 1; } if (smcross_exist == 0) { smcrossbmp = XCreateBitmapFromData(gksdisplay, gkswindow, smcross_bits, smcross_width, smcross_height); smcrosscurs = XCreatePixmapCursor(gksdisplay, smcrossbmp, smcrossbmp, &gks_exactcolors[ 7 ], &gks_exactcolors[ 0 ], 8, 7); smcross_exist = 1; } if (boldarr_exist == 0) /* "hotspot" here at bottom right */ { descript[2].xbm = XCreateBitmapFromData(gksdisplay, gkswindow, boldarrow_bits, boldarrow_width, boldarrow_height); descript[2].curs = XCreatePixmapCursor(gksdisplay, descript[2].xbm, descript[2].xbm, &gks_exactcolors[ 7 ], &gks_exactcolors[ 0 ], 15, 15); } if (squarebox_exist == 0) { descript[3].xbm = XCreateBitmapFromData(gksdisplay, gkswindow, squarebox_bits, squarebox_width, squarebox_height); descript[3].curs = XCreatePixmapCursor(gksdisplay, descript[3].xbm, descript[3].xbm, &gks_exactcolors[ 7 ], &gks_exactcolors[ 0 ], 8, 7); } if (vertbar_exist == 0) { descript[4].xbm = XCreateBitmapFromData(gksdisplay, gkswindow, vertbar_bits, vertbar_width, vertbar_height); descript[4].curs = XCreatePixmapCursor(gksdisplay, descript[4].xbm, descript[4].xbm, &gks_exactcolors[ 7 ], &gks_exactcolors[ 0 ], 8, 7); } if (horizbar_exist == 0) { descript[5].xbm = XCreateBitmapFromData(gksdisplay, gkswindow, horizbar_bits, horizbar_width, horizbar_height); descript[5].curs = XCreatePixmapCursor(gksdisplay, descript[5].xbm, descript[5].xbm, &gks_exactcolors[ 7 ], &gks_exactcolors[ 0 ], 8, 7); } /* continue .. */ #endif if (boldarr_exist == 0) /* .. continue */ { descript[2].active = 2; /* reserved */ descript[2].type = 2; descript[2].assoccurs = 1; descript[2].curs_fg = 7; descript[2].curs_bg = 0; descript[2].curs_xh = 15; descript[2].curs_yh = 15; descript[2].width = 16; descript[2].height = 16; descript[2].bits = boldarrow_bits; descript[2].save_bits = boldarrow_save_bits; boldarr_exist = 1; /* done */ } if (squarebox_exist == 0) { descript[3].active = 2; /* reserved */ descript[3].type = 2; descript[3].assoccurs = 1; descript[3].curs_fg = 7; descript[3].curs_bg = 0; descript[3].curs_xh = 8; descript[3].curs_yh = 8; descript[3].width = 16; descript[3].height = 16; descript[3].bits = squarebox_bits; descript[3].save_bits = squarebox_save_bits; squarebox_exist = 1; /* done */ } if (vertbar_exist == 0) { descript[4].active = 2; /* reserved */ descript[4].type = 2; descript[4].assoccurs = 1; descript[4].curs_fg = 7; descript[4].curs_bg = 0; descript[4].curs_xh = 8; descript[4].curs_yh = 8; descript[4].width = 16; descript[4].height = 16; descript[4].bits = vertbar_bits; descript[4].save_bits = vertbar_save_bits; vertbar_exist = 1; /* done */ } if (horizbar_exist == 0) { descript[5].active = 2; /* reserved */ descript[5].type = 2; descript[5].assoccurs = 1; descript[5].curs_fg = 7; descript[5].curs_bg = 0; descript[5].curs_xh = 8; descript[5].curs_yh = 8; descript[5].width = 16; descript[5].height = 16; descript[5].bits = horizbar_bits; descript[5].save_bits = horizbar_save_bits; horizbar_exist = 1; /* done */ } gclearscreen(); return(curpage); } /* end of gbeginframe */ /* ----------------------------------------------------------------------- */ int gclearscreen(void) /* This Function clears the graphics area */ { CLEARSCREEN(_GCLEARSCREEN); return(0); } /* end of gclearscreen */ /* ----------------------------------------------------------------------- */ int gpolyline(int xarr[], int yarr[], int npts) /* This Function draws a gks POLYLINE. NOTE that npts has a maximum value of 100. */ { int i; int gmove(int, int); int gdraw(int, int); #if defined(DESQ) /* X-Workstation */ XPoint points[100]; /* XLib uses a structure for polyline */ if (npts < 1 || npts > 100) return(-1); for (i = 0 ; i < npts ; i++) { points[i].x = xpix(xarr[i]); points[i].y = ypix(yarr[i]); } if (lnwidth != 1) { SETLINESTYLE(LINE_SOLID); /* Override */ oldXlinewidth = Xlinewidth; Xlinewidth = lnwidth; SETLINESTYLE(LINE_SOLID); } if (lnmode == 2) /* change GC function to XOR */ XSetFunction(gksdisplay, gksGC, GXxor); XPOLYLINE(points, npts); if (lnmode == 2) /* restore GC function to OVERLAY */ XSetFunction(gksdisplay, gksGC, GXcopy); if (lnwidth != 1) { Xlinewidth = oldXlinewidth; /* restore */ SETLINESTYLE(LINE_SOLID); } #else /* Borland C++, Microsoft C */ if (npts < 1 || npts > 100) return(-1); if (lnwidth == 1) { MOVETO(xpix(xarr[0]),ypix(yarr[0])); for (i = 1 ; i < npts ; i++ ) { if (lnmode != 2) { LINETO(xpix(xarr[i]),ypix(yarr[i])); } else { dda_line(lncolor, xpixlast, ypixlast, xpix(xarr[i]), ypix(yarr[i])); } xpixlast = xpix(xarr[i]); ypixlast = ypix(yarr[i]); } } else /* let gdraw() handle the (tedious) alignments */ { gmove(xarr[0], yarr[0]); for (i = 1 ; i < npts ; i++) gdraw(xarr[i], yarr[i]); } #endif xlast = xarr[npts - 1]; ylast = yarr[npts - 1]; xpixlast = xpix(xlast); ypixlast = ypix(ylast); /* update */ return(0); } /* end of gpolyline */ /* ----------------------------------------------------------------------- */ int glinecolor(int index) /* This Function sets the LINECOLOR index. Indices are assumed to run from 0 up to at least 15. Monochrome workstations map all non-zero indices to the foreground color. */ { int top; if (colorindices > 16) top = (colorindices - 1); else top = 15; if (index < 0 || index > top) return(-1); SETCOLOR(COLINDEX(index)); lncolor = index; /* update */ return(0); } /* end of glinecolor */ /* ----------------------------------------------------------------------- */ int glinetype(int type) /* This Function sets the LINETYPE as follows: 0 = solid 2 = dotted 1 = dashed 3 = dot-dash */ { if (type < 0 || type > 3) return(-1); CHKANDSETLINESTYLE(type); lntype = type; /* update */ return(0); } /* end of glinetype */ /* ----------------------------------------------------------------------- */ int glinewidth(int width_in_pixels, int width_align) /* This Function sets the LINEWIDTH (in pixels) and the LINEWIDTH_ALIGNMENT as follows: 0 CENTER the width 1 ALIGN UP 2 ALIGN LEFT 3 ALIGN DOWN 4 ALIGN RIGHT Out of range values are ignored. */ { if (width_in_pixels >= 1) lnwidth = width_in_pixels; if ( (width_align >= 0) && (width_align <= 4) ) lnwidthalign = width_align; return(0); } /* end of glinewidth */ /* ----------------------------------------------------------------------- */ int glinemode(int mode) /* This functions set the LINEMODE as follows: 1 = OVERLAY(default), 2 = XOR */ { if ((mode != 1) && (mode != 2)) return(-1); lnmode = mode; return(0); } /* end of glinemode */ /* ----------------------------------------------------------------------- */ int gmove(int xvdl, int yvdl) /* This Function changes current graphics position (CP) */ { MOVETO(xpix(xvdl), ypix(yvdl)); xlast = xvdl; ylast = yvdl; xpixlast = xpix(xlast); ypixlast = ypix(ylast); /* update */ return(0); } /* end of gmove */ /* ----------------------------------------------------------------------- */ int gdraw(int xvdl, int yvdl) /* This function draws FROM current graphics position (CP). LIMITATIONS: We currently do NOT support line widths > 1 pixel for XOR drawing */ { int i, dx, dy, xpixold, ypixold, xpixnew, ypixnew, deltax, deltay, a_deltax, a_deltay, center; if (lnmode != 2) /* not XOR */ { if (lnwidth == 1) { LINETO(xpix(xvdl), ypix(yvdl)); } else { center = 0; xpixold = xpixlast; ypixold = ypixlast; xpixnew = xpix(xvdl); ypixnew = ypix(yvdl); dx = 0; dy = 0; switch(lnwidthalign) { /* center align: this is currently a bit coarse */ case 0: deltax = xpixnew - xpixold; deltay = ypixnew - ypixold; if (deltax >= 0) a_deltax = deltax; else a_deltax = -deltax; if (deltay >= 0) a_deltay = deltay; else a_deltay = -deltay; if ( (deltax > 0) && (deltax >= a_deltay) ) { dx = 0; dy = 1; } else if ( (deltay < 0) && (a_deltay >= a_deltax) ) { dx = 1; dy = 0; } else if ( (deltax < 0) && (a_deltax > a_deltay) ) { dx = 0; dy = -1; } else { dx = -1; dy = 0; } center = lnwidth/2; break; /* center */ case 1: dy = -1; break; /* up */ case 2: dx = -1; break; /* left */ case 3: dy = 1; break; /* down */ case 4: dx = 1; break; /* right */ default: break; } /* end of switch */ /* *** DIAGNOSTIC *** fprintf("\n (deltax=%d,deltay=%d) center=%d lnwidth=%d dx=%d dy=%d ", deltax, deltay, center, lnwidth, dx, dy); fflush(stderr); */ if (center != 0) { /* corrections to center */ xpixold = xpixlast - center*dx; ypixold = ypixlast - center*dy; xpixnew = xpix(xvdl) - center*dx; ypixnew = ypix(yvdl) - center*dy; } for (i = 0 ; i < lnwidth ; i++) { MOVETO(xpixold + i*dx, ypixold + i*dy); LINETO(xpixnew + i*dx, ypixnew + i*dy); } } /* end of else */ } else { dda_line(lncolor, xpixlast, ypixlast, xpix(xvdl), ypix(yvdl)); } xlast = xvdl; ylast = yvdl; xpixlast = xpix(xlast); ypixlast = ypix(ylast); /* update */ return(0); } /* end of gdraw */ /* ----------------------------------------------------------------------- */ int gpolymarker(int xarr[], int yarr[], int npts) /* This Function draws a gks POLYMARKER. NOTE that npts has a maximum value of 100 */ { int i; int gmark(int, int); if (npts < 1 || npts > 100) return(-1); for (i = 0 ; i < npts ; i++) gmark(xarr[i],yarr[i]); return(0); } /* end of gpolymarker */ /* ----------------------------------------------------------------------- */ int gmarkercolor(int index) /* This Function sets the MARKERCOLOR index. Indices are assumed to run from 0 up to at least 15. Monochrome workstations map all non-zero indices to the foreground color. */ { int top; if (colorindices > 16) top = (colorindices - 1); else top = 15; if (index < 0 || index > top) return(-1); mkcolor = index; return(0); } /* end of gmarkercolor */ /* ----------------------------------------------------------------------- */ int gmarkertype(int type) /* This Function sets the MARKERTYPE as follows: index 0 = dot index 1 = small + index 2 = large + index 3 = * (star) index 4 = O (circle) index 5 = X indices 6,8 = squares indices 7,9 = diamonds */ { if (type < 0 || type > 9) return(-1); mktype = type; return(0); } /* end of gmarkertype */ /* --------------------------------------------------------------------- */ int gmarkersize(int tenths) /* This Function sets the MARKERSIZE in TENTHS of the base size. */ { if (tenths < 1 || tenths > 100) return(-1); mksize = tenths; return(0); } /* end of gmarkersize */ /* --------------------------------------------------------------------- */ int gmarkermode(int mode) /* This function sets the MARKERMODE as follows: 1 = OVERLAY(default), 2 = XOR */ { if ((mode != 1) && (mode != 2)) return(-1); mkmode = mode; return(0); } /* end of gmarkermode */ /* --------------------------------------------------------------------- */ int gmark(int xvdl, int yvdl) /* This Function draws a MARKer at the given position in vdl coordinates. */ { int xp, yp; xlast = xvdl; ylast = yvdl; /* update */ xpixlast = xpix(xlast); ypixlast = ypix(ylast); xp = xpixlast, yp = ypixlast; if ((mktype >= 0) && (mktype <= 9)) put_vect(&strk10[95 + mktype][0], mkmode, xp, yp, mksize, 0, mkcolor); SETCOLOR(COLINDEX(lncolor)); return(0); } /* end of gmark */ /* ----------------------------------------------------------------------- */ int enqcharcell(int *pwid, int *pht, int *pspace) /* This Function returns the size of the basic character font cell for precision STRING in vdl units. NOTE that this is an AVERAGE size if the font is PROPORTIONAL. */ { *pwid = cellwidth; *pht = cellheight; *pspace = cellspace; return(0); } /* end of enqcharcell */ /* ----------------------------------------------------------------------- */ int enqvectcell(int *pwid, int *pht, int *pspace) /* This Function returns the size of the basic character font cell for precision STROKE in vdl units. On the PC where we have only fixed fonts, this is the SAME as enqcharcell, but it DIFFERS on an X-Workstation. */ { *pwid = vectwidth; *pht = vectheight; *pspace = vectspace; return(0); } /* end of enqvectcell */ /* ----------------------------------------------------------------------- */ int enqtextwidth(char str[]) /* This Function returns the length of the designated string in the current font and text size for precision STRING. This function performs better than enqcharcell when PROPORTIONAL fonts are in use as on X-Workstations. For more detailed positioning information use enqtextextent(). */ { int index, num, pixlen, vdllen; if (str[0] == '\0') return(0); /* insurance */ num = strlen(str); index = ((txsize + 4)/10) - 1; /* We keep TEXTSIZE normally at 10 tenths (index = 0) */ if ((index < 0) || (index > 9)) index = 0; #if defined(DESQ) /* X-Workstation */ pixlen = XTextWidth(szfontpointer[index], str, num); #else /* Borland C++, Microsoft C */ pixlen = num * (index + 1) * (XMASK + 1); #endif vdllen = xinvpix(pixlen); return(vdllen); } /* end of enqtextwidth */ /* ----------------------------------------------------------------------- */ int enqtextextent(int xvdl, int yvdl, char str[], int *pxend, int *pyend, int *pxll, int *pyll, int *pxur, int *pyur) /* This function returns more DETAILED information about the placement of a non-empty text string than enqtextwidth(). It assumes that you want to position the STRING text str[] at (xvdl, yvdl) using gtext() and the current (rounded-off) STRING textsize. It returns: 1. the final position in (*pxend, *pyend) 2. the coordinates of the bounding box, lower left corner at (*pxll, *pyll), upper right corner (*pxur, *pyur). This routine assumes that the textpath is to the RIGHT. */ { #if defined(DESQ) int direction, ascent, descent; XCharStruct overall; #endif int num, index, pixlen, pixbelow, pixabove, xp, yp, lbear, rbear; num = strlen(str); if (num == 0) return(-1); /* string is empty */ xp = xpix(xvdl); yp = ypix(yvdl); /* adjust for round-off of fractional sizes */ index = ((txsize + 4)/10) - 1; /* We keep TEXTSIZE normally at 10 tenths (index = 0) */ if ((index < 0) || (index > 9)) index = 0; #if defined(DESQ) /* X-Workstation */ XTextExtents(szfontpointer[index], str, num, &direction, &ascent, &descent, &overall); pixabove = overall.ascent; pixbelow = overall.descent; pixlen = overall.width; lbear = overall.lbearing; rbear = overall.rbearing; #else /* Borland C++, Microsoft C */ pixabove = (index + 1) * YMASK; pixbelow = (index + 1); pixlen = num * (index + 1) * (XMASK + 1); lbear = 0; rbear = pixlen; #endif *pxend = xinvpix(xp + pixlen); *pyend = yvdl; *pxll = xinvpix(xp + lbear); *pyll = yinvpix(yp + pixbelow); *pxur = xinvpix(xp + rbear); *pyur = yinvpix(yp - pixabove); return(0); } /* end of enqtextextent */ /* ----------------------------------------------------------------------- */ int gtext(int xvdl, int yvdl, char string[]) /* This Function outputs TEXT startling at the GIVEN position in vdl coordinates. On an X-Workstation, font operations are used, and the fonts could be proportional. On the PC with Borland C++ or Micorsoft C we use the fixed characters masks in amr10[][] (STRING) or SHORT_PL records in strk10[][] (STROKE). */ { double dtheta,xsin,xcos,rads,xrel,yrel; int j,k,xp,yp,xv,yv,mag,wid,ht,vwid,vht,xrot,yrot; #if defined(DESQ) /* X-Workstation */ char tmpstr[8]; xsin = 0.0; xcos = 0.0; /* stop gcc "warnings" */ wid = 0; ht = 0; vwid = 0; vht = 0; #endif mag = (txsize + 4)/10; /* magnification */ if (txpixoverride) /* check for gappendtext() */ { yp = ypixlast; xp = xpixlast; txpixoverride = 0; } else { yp = ypix(yvdl); xp = xpix(xvdl); } SETCOLOR(COLINDEX(txcolor)); /* temp change color */ /* if STROKE check text orientation (ie. TEXTBASELINE) and set up for a possible rotation. */ if ((txprec == 2) && (txorient != 0)) { dtheta = (double)txorient; rads = (6.283 * dtheta)/360.0; xsin = sin(rads); xcos = cos(rads); } #if defined(DESQ) /* X-Workstation */ if ((mag > 1) && (mag <= 10)) /* change size if > 10 tenths */ XSetFont(gksdisplay, gksGC, szfont[mag - 1]); #endif switch(txpath) { case 0: break; /* alignment = left bottom */ case 90: xp = xp - (mag * XMASK)/2; break; /* alignment = center base */ case 180: xp = xp - (mag * XMASK); break; /* alignment = right bottom */ case 270: xp = xp - (mag * XMASK)/2; yp = yp + (mag * YMASK); break; /* alignment = center cap */ default: break; } /* end of switch(txpath) */ /* virtual coords for STROKE */ if (txpath == 0) { xv = xvdl; yv = yvdl; } else { xv = xinvpix(xp); yv = yinvpix(yp); } j = 0; while((k = string[j]) != '\0') { /* Insurance */ if ((k < 32) || (k > 126)) k = ' '; #if defined(DESQ) /* X-Workstation */ tmpstr[0] = k; tmpstr[1] = '\0'; if (txprec != 2) /* NOT STROKE */ { wid = XTextWidth(szfontpointer[mag - 1], tmpstr, 1); ht = (*szfontpointer[mag - 1]).ascent + (*szfontpointer[mag - 1]).descent; } else { vwid = ((vectwidth + vectspace) * txsize)/10; vht = (vectheight * txsize)/10; if (txorient != 0) { xrel = (double)(xv - xvdl); yrel = (double)(yv - yvdl); xrot = xvdl + (int)(xcos*xrel - xsin*yrel); yrot = yvdl + (int)(xsin*xrel + xcos*yrel); xp = xpix(xrot); yp = ypix(yrot); } else { xp = xpix(xv); yp = ypix(yv); } } if (txmode == 0) /* REPLACE */ { XREPSTRING(xp, yp - DEF_ALIGN_FONT, tmpstr); } else if (txmode == 1) /* OVERLAY */ { if (txprec == 0) /* STRING */ XOVRSTRING(xp, yp - DEF_ALIGN_FONT, tmpstr); else if (txprec == 2) /* STROKE */ put_vect(&strk10[k - 32][0], txmode, xp, yp, txsize, txorient, txcolor); } else if (txmode == 2) /* XOR */ { /* change GC function to XOR */ XSetFunction(gksdisplay, gksGC, GXxor); XOVRSTRING(xp, yp - DEF_ALIGN_FONT, tmpstr); /* change GC write mode back to copy */ XSetFunction(gksdisplay, gksGC, GXcopy); } #else /* Microsoft C, Borland C++ */ if (txprec != 2) /* NOT STROKE */ { wid = (XMASK + 1) * mag; ht = (YMASK + 1) * mag; put_mask(&amr10[k - 32][0], txmode, xp, yp, mag); } else { vwid = ((vectwidth + vectspace) * txsize)/10; vht = (vectheight * txsize)/10; if (txorient != 0) { xrel = (double)(xv - xvdl); yrel = (double)(yv - yvdl); xrot = xvdl + (int)(xcos*xrel - xsin*yrel); yrot = yvdl + (int)(xsin*xrel + xcos*yrel); xp = xpix(xrot); yp = ypix(yrot); } else { xp = xpix(xv); yp = ypix(yv); } /* *** DIAGOSTIC *** fprintf(stderr, "\nput_vect(\'%c\', mode=%d, xpxl=%d, ypxl=%d, mag10=%d ...)", (char)k, txmode, xp, yp, txsize); fflush(stderr); */ put_vect(&strk10[k - 32][0], txmode, xp, yp, txsize, txorient, txcolor); } #endif j++; switch(txpath) { case 0: xp = xp + wid; /* next char cell */ xv = xv + vwid; break; case 90: yp = yp - ht; yv = yv + vht; break; case 180: xp = xp - wid; xv = xv - vwid; break; case 270: yp = yp + ht; yv = yv - vht; break; default: break; } /* end of switch(txpath) */ } /* end of while */ #if defined(DESQ) /* X-Workstation */ XSetFont(gksdisplay, gksGC, deffont); /* restore deffont */ #endif SETCOLOR(COLINDEX(lncolor)); /* restore color */ xlast = xinvpix(xp); ylast = yinvpix(yp); /* update */ xpixlast = xp; ypixlast = yp; return(0); } /* end of gtext */ /* ----------------------------------------------------------------------- */ int gappendtext(char string[]) /* This Function outputs TEXT at the CURRENT position (CP). It is also called gputs() and is usually used after gtext() to ADD more TEXT. */ { int x, y; x = xlast; y = ylast; /* get dummy CP */ txpixoverride = 1; /* with this flag set, gtext() will use (xpixlast, ypixlast) and we will avoid integer roundoff */ gtext(x, y, string); return(0); } /* end of gappendtext */ /* ----------------------------------------------------------------------- */ int gtextcolor(int index) /* This function sets the TEXTCOLOR index. Indices are assumed to run from 0 up to at least 15. Monochrome workstations map all non-zero indices to the foreground color. */ { int top; if (colorindices > 16) top = (colorindices - 1); else top = 15; if (index < 0 || index > top) return(-1); txcolor = index; return(0); } /* end of gtextcolor */ /* ----------------------------------------------------------------------- */ int gtextsize(int tenths) /* This Function sets the TEXTSIZE in TENTHS of the base size. This is essentially a BUNDLED function. Full power GKS allows the user to SEPARATELY set: 1. character_height (in vdl units) 2. character_expansion_factor (width as fraction of height) 3. character_spacing_factor (space as fraction of height) Note that in the case of STRING (as opposed to STROKE) this library rounds off to sizes which are whole number multiples of the base size. The base size (in vdl units) can be found by calling enqcharcell() (STRING) or enqvectcell (STROKE). */ { if (tenths < 1 || tenths > 100) return(-1); txsize = tenths; return(0); } /* end of gtextsize */ /* ----------------------------------------------------------------------- */ int gtextorient(int degrees) /* This Function sets the TEXTBASELINE which is an integer (in degrees counter-clockwise) from 0 to 359. This routine is equivalent to the GKS routine which sets character_up_vector. Note that a non-zero TEXTBASELINE is ONLY operational when the current text precision is STROKE. */ { if ((degrees < 0) || (degrees > 359)) return(-1); txorient = degrees; return(0); } /* end of gtextorient */ /* ----------------------------------------------------------------------- */ int gtextpath(int degrees) /* This Function sets the TEXTDIRECTION (ie. the writing direction). The current allowable values are: 0(RIGHT) 90(UP) 180(LEFT) 270(DOWN) */ { if ((degrees != 0) && (degrees != 90) && (degrees != 180) && (degrees != 270)) return(-1); txpath = degrees; return(0); } /* end of gtextpath */ /* ----------------------------------------------------------------------- */ int gtextprecision(int prec) /* This function sets the GKS TEXTPRECISION as follows: 0 = STRING(default), 1 = CHAR, 2 = STROKE Note that CURRENTLY, precision = CHAR is NOT supported */ { if (prec == 0) { txprec = 0; } /* STRING */ else if (prec == 2) { txprec = 2; /* STROKE does NOT admit REPLACE mode */ if (txmode == 0) txmode = 1; } return(0); } /* end of gtextprecision */ /* ----------------------------------------------------------------------- */ int gtextmode(int mode) /* This Function sets the GKS TEXTMODE as follows: 0 = REPLACE, 1 = OVERLAY(default), 2 = XOR with the restriction that if precision = STROKE, only OVERLAY and XOR are allowed. */ { if (mode != 0 && mode != 1 && mode != 2) return(-1); if (txprec == 0) { txmode = mode; return(0); } else if ((txprec == 2) && (mode != 0)) { txmode = mode; return(0); } return(-1); } /* end of gtextmode */ /* ----------------------------------------------------------------------- */ int cellarray(int xll, int yll, int xur, int yur, int xcells, int ycells, unsigned char *ca) /* This function implements the GKS-call CELL_ARRAY which is primarily used to post a virtual bitmapped image. The rectangle whose lower left corner is at (xll, yll) and upper right corner at (xur, yur) in vdl coordinates is divided horizontally into xcells and vertically into ycells. The colorindices to be used are contained in an array of the form unsigned char ca[ycells][xcells] BUT this is passed with a typecast: (unsigned char *)ca */ { int xp, yp, r, cr, p, cp, n, m, crtimesxcells; int adx, ady, es, i, curcolor, from, run; if ( (xll > xur) || (yll > yur) ) /* check corners */ { fprintf(stderr, "\ncellarray: required: xll=%d < xur=%d and yll=%d < yur=%d", xll, xur, yll, yur); fflush(stderr); } xp = xpix(xll); /* find upper left pixel coords */ yp = ypix(yur); m = xpix(xur) - xp + 1; /* m = number of pixel columns */ n = ypix(yll) - yp + 1; /* n = number of pixel rows */ if ( (n <= 0) || (m <= 0) ) return(-1); /* Note: p = current pixel column (= 0, 1, 2, ... (m - 1)) cp = current cell column (= 0, 1, 2, ... (xcells - 1)) and cp = (xcells/m) * p also r = current pixel row (= 0, 1, 2, ... (n - 1)) cr = current cell row (= 0, 1, 2, ... (ycells - 1)) and cr = (ycells/n) * r We can therefore just use a modified BRESENHAM-type algorithm. */ /* compute relative displacements */ adx = m - 1; ady = xcells - 1; SETCOLOR(COLINDEX(7)); /* start with known color */ curcolor = 7; cr = 0; /* start with cell row = 0 */ for (r = 0 ; r < n ; r++) { cr = ((2 * ycells * r) + n)/(2 * n); if (cr >= ycells) cr = ycells - 1; crtimesxcells = cr * xcells; /* process ONE row */ if (m >= xcells) /* case of m >= ycells */ { p = 0; cp = 0; es = 2*ady - adx; run = 0; from = 0; /* use "run" and "from" to speed up setting pixels in the most common situation */ loop1: i = ca[crtimesxcells + cp];/* cell color index */ if (curcolor != i) /* change color */ { if (run > 1) { MOVETO(xp + from, yp + r); LINETO(xp + p - 1, yp + r); } else if (run == 1) { SETPIXEL(xp + p - 1, yp + r); } run = 1; from = p; curcolor = i; SETCOLOR(COLINDEX(curcolor)); } else { run++; } if (p >= adx) { if (run > 1) { MOVETO(xp + from, yp + r); LINETO(xp + p, yp + r); } else if (run == 1) { SETPIXEL(xp + p, yp + r); } goto rowdone; } if (es >= 0) { cp++; es = es - 2*adx; } es = es + 2*ady; p++; goto loop1; } else /* case of xcells > m (interchange p,cp and x,y) */ { p = 0; cp = 0; es = 2*adx - ady; loop2: i = ca[crtimesxcells + cp];/* cell color index */ if (curcolor != i) /* change color */ { curcolor = i; SETCOLOR(COLINDEX(curcolor)); } SETPIXEL(xp + p, yp + r); if (cp >= ady) goto rowdone; if (es >= 0) { p++; es = es - 2*ady; } es = es + 2*adx; cp++; goto loop2; } rowdone: ; } /* end of for ( ... */ SETCOLOR(COLINDEX(lncolor)); /* restore drawing color */ return(0); } /* end of cellarray */ /* ----------------------------------------------------------------------- */ int garc(int center_x, int center_y, int rad, int from, int to) /* This Function draws an ARC with border and fill subject to what has been set by gperimeter() and gfillpattern(). There are no longer any restrictions on the angle and perimeter widths greater than 1 pixel are now supported. REMAINING PROBLEMS: 1. If platform does fill with a FLOODFILL routine the caller is advised to ERASE the area first if there has been previous drawing in the area since stray pixels of the filling index may STOP THE FILL PREMATURELY. This is particularly a problem when using the wipe index 0. 2. You should not use PATTERN FILL with extremely thin sectors. 3. When style other than LineSolid is used with X-Workstation the perimeter is drawn INORDINATELY SLOW. I haven't been able yet to find out why. 4. Borland C++ does not allow perimeter style other than LINE_SOLID for arcs or ellipses. LIMITATIONS: 1 We currently do NOT support perimeter styles other than LINE_SOLID for arcs or ellipses. 2. Borland's pattern fill is SLOW and prone to artifacts when a clip region (smaller than fullscreen) is used */ { int gellipse(int, int, int, int); int i,j,k,pcen_x,pcen_y,dx,dy; int ll_x,ll_y,ur_x,ur_y; int ul_x,ul_y,lr_x,lr_y,halfx,halfy,x3,y3,x4,y4,midx,midy; double xcos, xsin, rads; if (rad <= 0) return(-1); /* insurance */ if ( (from == to) || ( (from == 0) && (to == 360) ) ) { #if defined(DESQ) /* X-Workstation */ if (from == to) to = from + 360; #else /* Borland C++, Microsoft C */ gellipse(center_x - rad,center_y - rad, center_x + rad,center_y + rad); return(0); #endif } #if defined(_DJGPP) /* DJGPP with BCC2GRX */ if (from < 0) from = from + 360; if (from > to) to = to + 360; #elif defined(TURBEAUX) && !defined(_DJGPP) /* Borland doesn't like this */ if (from < 0) from = from + 360; #endif /* Compute a variety of parameters */ ll_x = center_x - rad; ll_y = center_y - rad; ur_x = center_x + rad; ur_y = center_y + rad; /* convert to pixel coords */ pcen_x = xpix(center_x); pcen_y = ypix(center_y); ul_x = xpix(ll_x); ul_y = ypix(ur_y); lr_x = xpix(ur_x); lr_y = ypix(ll_y); halfx = (lr_x - ul_x)/2; halfy = (lr_y - ul_y)/2; /* convert angles to vectors for Microsoft */ rads = (6.283 * ((double)from))/360.0; xsin = sin(rads); xcos = cos(rads); dx = (int)((double)halfx * xcos); dy = (int)((double)halfx * xsin); x3 = pcen_x + dx; y3 = pcen_y - dy; /* start vector */ rads = (6.283 * ((double)to))/360.0; xsin = sin(rads); xcos = cos(rads); dx = (int)((double)halfx * xcos); dy = (int)((double)halfx * xsin); x4 = pcen_x + dx; y4 = pcen_y - dy; /* stop vector */ rads = (6.283 * ((double)to + (double)from))/720.0; xsin = sin(rads); xcos = cos(rads); dx = (int)(((double)halfx * xcos)/2.0); dy = (int)(((double)halfx * xsin)/2.0); midx = pcen_x + dx; midy = pcen_y - dy; /* mid-way vector */ #if defined(DESQ) /* X-Workstation */ if (from > to) to = to + 360; #endif if (flpattern[0] == 1) /* SOLID_FILL with flpattern[1] */ { set_solid_fill(COLINDEX(flpattern[1])); /* finish below ... */ } /* end of if (flpattern[0] == 1) */ else if (flpattern[0] == 2) /* PATTERN_FILL with flpattern[2] */ { #if defined(DESQ) set_patt_fill(flpattern[2], 0); FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); #elif defined(TURBEAUX) set_solid_fill(0); /* erase first */ if (from > to) /* Borland doesn't like this */ { SETLINESTYLE(LINE_SOLID); SETCOLOR(8); FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, 360); ARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, 360); if (flpattern[2] == ptable_num) /* fill */ { aux_flood_fill((x3 + lr_x)/2, (y3 + pcen_y)/2, 8, FL_DEPTH); } set_solid_fill(0); /* restore erase */ SETLINESTYLE(LINE_SOLID); SETCOLOR(8); FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, 0, to); ARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, 0, to); if (flpattern[2] == ptable_num) /* fill */ { aux_flood_fill((lr_x + x4)/2, (pcen_y + y4)/2, 8, FL_DEPTH); } } /* end of if (from > to) */ else /* sector is "connected" */ { SETLINESTYLE(LINE_SOLID); SETCOLOR(8); FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); ARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); if (flpattern[2] == ptable_num) /* fill */ { aux_flood_fill(midx, midy, 8, FL_DEPTH); } } #else /* Microsoft C */ set_solid_fill(0); /* erase first */ FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); for (k = 1 ; k < 16 ; k++) /* now run through VGA palette */ { if (set_patt_fill(flpattern[2], k) < 0) continue; /* test&set a fillpattern */ FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); } /* end of for (k = ... */ #endif } /* end of if (flpattern[0] == 2) */ else if (flpattern[0] == 3) /* HATCH_FILL with flpattern[3] */ { set_hatch_fill(flpattern[3], COLINDEX(flpattern[1])); /* finish below ... */ } /* end of if (flpattern[0] == 3) */ /* finish SOLID, HATCH fills */ if ( (flpattern[0] == 1) || (flpattern[0] == 3) ) { #if defined(TURBEAUX) if (from > to) /* Borland doesn't like this */ { ARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, 360); FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, 360); ARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, 0, to); FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, 0, to); } else { ARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); } #else /* X-Workstation, Microsoft C */ FILLARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); #endif } /* end of SOLID, HATCH fills */ set_solid_fill(COLINDEX(lncolor)); /* Important for X-Wk */ if (prmeter[0] == 0) /* draw PERIMETER */ { SETCOLOR(COLINDEX(prmeter[2])); j = prmeter[1]; /* get type */ CHKANDSETLINESTYLE(j); #if defined(DESQ) SETLINESTYLE(LINE_SOLID); /* Override */ oldXlinewidth = Xlinewidth; Xlinewidth = prmeter[3]; SETLINESTYLE(LINE_SOLID); ARC(ul_x, ul_y, lr_x, lr_y, pcen_x, pcen_y, halfx, halfy, x3, y3, x4, y4, from, to); Xlinewidth = oldXlinewidth; /* restore */ SETLINESTYLE(LINE_SOLID); #elif defined(TURBEAUX) if (from > to) /* Borland doesn't like this */ { for (i = 0 ; i < prmeter[3] ; i++) { ARC(ul_x - i, ul_y - i, lr_x + i, lr_y + i, pcen_x, pcen_y, halfx + i, halfy + i, x3, y3, x4, y4, from, 360); ARC(ul_x - i, ul_y - i, lr_x + i, lr_y + i, pcen_x, pcen_y, halfx + i, halfy + i, x3, y3, x4, y4, 0, to); } } else { for (i = 0 ; i < prmeter[3] ; i++) ARC(ul_x - i, ul_y - i, lr_x + i, lr_y + i, pcen_x, pcen_y, halfx + i, halfy + i, x3, y3, x4, y4, from, to); } /* supress INANE tcc warning messages */ x3 = x3 + x4; x4 = x4 + x3; y3 = y3 + y4; y4 = y4 + y3; #else for (i = 0 ; i < prmeter[3] ; i++) ARC(ul_x - i, ul_y - i, lr_x + i, lr_y + i, pcen_x, pcen_y, halfx + i, halfy + i, x3, y3, x4, y4, from, to); #endif } /* end of if (prmeter[0] == 0) */ /* restore color AND solid fill e*/ set_solid_fill(COLINDEX(lncolor)); k = lntype; CHKANDSETLINESTYLE(k); /* restore line_type */ return(0); } /* end of garc */ /* ----------------------------------------------------------------------- */ int gellipse(int ll_x, int ll_y, int ur_x, int ur_y) /* This Function draws an ELLIPSE using the bounding rectangle (see grectangle() below). The border and fill are subject to what has been set by gperimeter() and gfillpattern(). Perimeter widths greater than 1 pixel are now supported, although PC result often contains "artifacts.". REMAINING PROBLEMS: 1. When style other than LineSolid is used with X-Workstation the perimeter is drawn INORDINATELY SLOW. I haven't been able yet to find out why. 2. Borland C++ does not allow perimeter style other than LINE_SOLID for arcs or ellipses. LIMITATIONS: 1. We currently do NOT support perimeter styles other than LINE_SOLID for arcs or ellipses. 2. Borland's pattern fill is SLOW and prone to artifacts when a clip region (smaller than fullscreen) is used */ { int center_x, center_y, half_x, half_y; int i,j,k,ul_x,ul_y,lr_x,lr_y; if ( (ll_x > ur_x) || (ll_y > ur_y) ) /* check corners */ { fprintf(stderr, "\ngellipse: required: xll=%d < xur=%d and yll=%d < yur=%d", ll_x, ur_x, ll_y, ur_y); fflush(stderr); } ul_x = xpix(ll_x); ul_y = ypix(ur_y); lr_x = xpix(ur_x); lr_y = ypix(ll_y); half_x = (lr_x - ul_x)/2; half_y = (lr_y - ul_y)/2; center_x = (ul_x + lr_x)/2; center_y = (lr_y + ul_y)/2; if (flpattern[0] == 1) /* SOLID_FILL with flpattern[1] */ { #if defined(DESQ) #elif defined(TURBEAUX) #else /* This time Microsoft is the culprit: it does an ellipse with a _floodfill so index 0 won't work unless we wipe ALL traces of it with a different fill color first. As usual, we recruit index 8 for this purpose. */ if (flpattern[1] == 0) { set_solid_fill(COLINDEX(8)); FILLELLIPSE(ul_x, ul_y, lr_x, lr_y, center_x, center_y, half_x, half_y, 0, 360); } #endif set_solid_fill(COLINDEX(flpattern[1])); /* finish below ... */ } /* end of if (flpattern[0] == 1) */ else if (flpattern[0] == 2) /* PATTERN_FILL with flpattern[2] */ { #if defined(DESQ) set_patt_fill(flpattern[2], 0); FILLELLIPSE(ul_x, ul_y, lr_x, lr_y, center_x, center_y, half_x, half_y, 0, 360); #elif defined(TURBEAUX) /* Borland C++ */ set_solid_fill(0); /* erase first with index 0 */ fillellipse(center_x, center_y, half_x, half_y); SETLINESTYLE(LINE_SOLID); SETCOLOR(8); ellipse(center_x, center_y, 0, 360, half_x, half_y); if (flpattern[2] == ptable_num) aux_flood_fill(center_x, center_y, 8, FL_DEPTH); #else /* Microsoft C */ set_solid_fill(0); /* erase first with index 0 */ FILLELLIPSE(ul_x, ul_y, lr_x, lr_y, center_x, center_y, half_x, half_y, 0, 360); for (k = 1 ; k < 16 ; k++) /* now run through VGA palette */ { if (set_patt_fill(flpattern[2], k) < 0) continue; /* test&set a fillpattern */ FILLELLIPSE(ul_x, ul_y, lr_x, lr_y, center_x, center_y, half_x, half_y, 0, 360); } /* end of for (k = ... */ #endif } /* end of if (flpattern[0] == 2) */ else if (flpattern[0] == 3) /* HATCH_FILL with flpattern[3] */ { set_hatch_fill(flpattern[3], COLINDEX(flpattern[1])); /* finish below ... */ } /* end of if (flpattern[0] == 3) */ /* finish SOLID, HATCH fills */ if ( (flpattern[0] == 1) || (flpattern[0] == 3) ) { FILLELLIPSE(ul_x, ul_y, lr_x, lr_y, center_x, center_y, half_x, half_y, 0, 360); } set_solid_fill(COLINDEX(lncolor)); /* Important for X-Wk */ if (prmeter[0] == 0) /* draw PERIMETER */ { SETCOLOR(COLINDEX(prmeter[2])); j = prmeter[1]; /* get perimeter type */ /* *** TODO *** SETLINESTYLE(j); */ #if defined(DESQ) oldXlinewidth = Xlinewidth; Xlinewidth = prmeter[3]; SETLINESTYLE(LINE_SOLID); ELLIPSE(ul_x, ul_y, lr_x, lr_y, center_x, center_y, half_x, half_y, 0, 360); Xlinewidth = oldXlinewidth; /* restore */ SETLINESTYLE(LINE_SOLID); #else SETLINESTYLE(LINE_SOLID); /* OVERRIDE */ for (i = 0 ; i < prmeter[3] ; i++) ELLIPSE(ul_x - i, ul_y - i, lr_x + i, lr_y + i, center_x, center_y, half_x + i, half_y + i, 0, 360); #endif } /* end of if (prmeter[0] == 0) */ /* RESTORE color AND solid fill */ set_solid_fill(COLINDEX(lncolor)); k = lntype; /* RESTORE line_type */ CHKANDSETLINESTYLE(k); return(0); } /* end of gellipse */ /* ----------------------------------------------------------------------- */ int grectangle(int ll_x, int ll_y, int ur_x, int ur_y) /* This function draws a GKS RECTANGLE using the lower_left and upper_right corner coordinates. The border and fill are subject to what has been set by gperimeter() and gfillpattern(). Perimeter widths greater than 1 pixel are now supported. */ { int i,j,k,ul_x,ul_y,lr_x,lr_y; int poly[8]; if ( (ll_x > ur_x) || (ll_y > ur_y) ) /* check corners */ { fprintf(stderr, "\ngrectangle: required: xll=%d < xur=%d and yll=%d < yur=%d", ll_x, ur_x, ll_y, ur_y); fflush(stderr); } ul_x = xpix(ll_x); ul_y = ypix(ur_y); lr_x = xpix(ur_x); lr_y = ypix(ll_y); poly[0] = ul_x; poly[1] = ul_y; /* fill poly array for Borland */ poly[2] = lr_x; poly[3] = ul_y; poly[4] = lr_x; poly[5] = lr_y; poly[6] = ul_x; poly[7] = lr_y; if (flpattern[0] == 1) /* SOLID_FILL with flpattern[1] */ { set_solid_fill(COLINDEX(flpattern[1])); /* finish below ... */ } /* end of if (flpattern[0] == 1) */ else if (flpattern[0] == 2) /* PATTERN_FILL with flpattern[2] */ { #if defined(DESQ) /* X-Workstation */ set_patt_fill(flpattern[2], 0); FILLRECTANGLE(ul_x,ul_y,lr_x,lr_y); #elif defined(TURBEAUX) /* Borland C++ */ set_solid_fill(0); /* erase first with index 0 */ fillpoly(4, poly); SETLINESTYLE(LINE_SOLID); SETCOLOR(8); MOVETO(poly[0],poly[1]); LINETO(poly[2],poly[3]); LINETO(poly[4],poly[5]); LINETO(poly[6],poly[7]); LINETO(poly[0],poly[1]); if (flpattern[2] == ptable_num) aux_flood_fill((ul_x + lr_x)/2,(ul_y + lr_y)/2,8,FL_DEPTH); #else /* Microsoft C */ set_solid_fill(0); /* erase first with index 0 */ RECTANGLE(_GFILLINTERIOR,ul_x,ul_y,lr_x,lr_y); for (k = 1 ; k < 16 ; k++) /* now run through VGA palette */ { if (set_patt_fill(flpattern[2], k) < 0) continue; /* test&set a fillpattern */ RECTANGLE(_GFILLINTERIOR,ul_x,ul_y,lr_x,lr_y); } /* end of for (k = ... */ #endif } /* end of if (flpattern[0] == 2) */ else if (flpattern[0] == 3) /* HATCH_FILL with flpattern[3] and with color from flpattern[1] */ { set_hatch_fill(flpattern[3],COLINDEX(flpattern[1])); /* finish below ... */ } /* end of if (flpattern[0] == 3) */ /* finish SOLID, HATCH fills */ if ( (flpattern[0] == 1) || (flpattern[0] == 3) ) { #if defined(TURBEAUX) /* Borland C++ */ fillpoly(4, poly); /* Borland doesn't really have a fillrectangle(), only a fillpoly() */ #endif FILLRECTANGLE(ul_x,ul_y,lr_x,lr_y); } set_solid_fill(COLINDEX(lncolor)); /* Important for X-Wk */ if (prmeter[0] == 0) /* draw PERIMETER */ { SETCOLOR(COLINDEX(prmeter[2])); j = prmeter[1]; /* get type */ CHKANDSETLINESTYLE(j); for (i = 0 ; i < prmeter[3] ; i++) RECTANGLE(_GBORDER,ul_x - i, ul_y - i, lr_x + i, lr_y + i); } /* end of if (prmeter[0] == 0) */ /* RESTORE color AND solid fill */ set_solid_fill(COLINDEX(lncolor)); k = lntype; /* RESTORE line_type */ CHKANDSETLINESTYLE(k); return(0); } /* end of grectangle */ /* ----------------------------------------------------------------------- */ int gpolygon(int xarr[], int yarr[], int npts) /* This function draws a GKS POLYGON. The polygon SHOULD BE CONVEX if you want to fill it. The border and fill are subject to what has been set by gperimeter() and gfillpattern(). The case of an X-Workstation is fairly straightforward. With PC-based libraries (Borland C++, Microsoft C) filling itself is done by the routines fillpoly() and _polygon() respectively. LIMITATIONS: 1. We have an (artificial) requirement that 3 <= npts <= 100 since we sometimes have to make LOCAL copies. 2. Borland's pattern fill is SLOW and prone to artifacts when a clip region (smaller than fullscreen) is used */ { int i,j,k; /* Handle structural differences for Coords */ #if defined(DESQ) /* X-Workstation */ XPoint points[101]; if (npts < 3 || npts > 100) return(-1); for (i = 0 ; i < npts ; i++) { points[i].x = xpix(xarr[i]); points[i].y = ypix(yarr[i]); } points[npts].x = xpix(xarr[0]); /* for perimeter below */ points[npts].y = ypix(yarr[0]); #elif defined(TURBEAUX) /* Borland C++ */ int xbar, ybar, points[202]; long lx,ly,ln; if (npts < 3 || npts > 100) return(-1); /* barycenters needed for Borland C++ */ lx = 0L; ly = 0L; ln = (long)npts; for (i = 0 ; i < npts ; i++) /* find barycenter and also fill points[] for use with Borland Turbo C */ { points[2*i] = xpix(xarr[i]); points[2*i + 1] = ypix(yarr[i]); lx = lx + (long)xarr[i]; ly = ly + (long)yarr[i]; } xbar = (int)(lx/ln); ybar = (int)(ly/ln); #else /* Microsoft C */ struct xycoord points[101]; if (npts < 3 || npts > 100) return(-1); for (i = 0 ; i < npts ; i++) { points[i].xcoord = xpix(xarr[i]); points[i].ycoord = ypix(yarr[i]); } #endif if (flpattern[0] == 1) /* SOLID_FILL with flpattern[1] */ { set_solid_fill(COLINDEX(flpattern[1])); FILLPOLY(points, npts); } /* end of if (flpattern[0] == 1) */ else if (flpattern[0] == 2) /* PATTERN_FILL with flpattern[2] */ { #if defined(DESQ) /* X-Workstation */ set_patt_fill(flpattern[2], 0); FILLPOLY(points, npts); #elif defined(TURBEAUX) /* Borland C++ */ set_solid_fill(0); /* erase first with index 0 */ fillpoly(npts, points); MOVETO(xpix(xarr[0]),ypix(yarr[0])); /* first draw solid perimeter (needed by FLOODFILL) same color */ SETLINESTYLE(LINE_SOLID); SETCOLOR(8); for (i = 1 ; i < npts ; i++ ) { LINETO(xpix(xarr[i]),ypix(yarr[i])); } LINETO(xpix(xarr[0]),ypix(yarr[0])); /* close up */ if (flpattern[2] == ptable_num) aux_flood_fill(xpix(xbar),ypix(ybar),8,FL_DEPTH); #else /* Microsoft C */ set_solid_fill(0); /* erase first with index 0 */ FILLPOLY(points, npts); for (k = 1 ; k < 16 ; k++) /* now run through VGA palette */ { if (set_patt_fill(flpattern[2], k) < 0) continue; /* test&set a fillpattern */ FILLPOLY(points, npts); } /* end of for (k = ... */ #endif } /* end of if (flpattern[0] == 2) */ else if (flpattern[0] == 3) /* HATCH_FILL with flpattern[3] */ { set_hatch_fill(flpattern[3], COLINDEX(flpattern[1])); FILLPOLY(points, npts); } /* end of if (flpattern[0] == 3) */ set_solid_fill(COLINDEX(lncolor)); /* Important for X-Wk */ if (prmeter[0] == 0) /* draw PERIMETER */ { SETCOLOR(COLINDEX(prmeter[2])); j = prmeter[1]; /* get type */ CHKANDSETLINESTYLE(j); MOVETO(xpix(xarr[npts - 1]),ypix(yarr[npts - 1])); for (k = 0 ; k < npts ; k++) { LINETO(xpix(xarr[k]),ypix(yarr[k])); } LINETO(xpix(xarr[0]),ypix(yarr[0])); } /* end of if (prmeter[0] == 0) */ /* restore color and solid fill */ set_solid_fill(COLINDEX(lncolor)); CHKANDSETLINESTYLE(lntype); /* restore LINETYPE */ xlast = xarr[0]; ylast = yarr[0]; /* update */ xpixlast = xpix(xlast); ypixlast = ypix(ylast); return(0); } /* end of gpolygon */ /* ----------------------------------------------------------------------- */ int gsetpattern(int patt_index, int cols, int rows, unsigned char col_index[][8]) /* This function allows the caller to set a user-defined Pattern (which is also called a Tile in X). In order to keep compatibility with Borland C++ and Microsoft C, the number of columns and rows BOTH MUST BE 8. Also, patterns must NOT use index 0 (which is reserved for erase) NOR use indices < 256 (since Tektronix workstations reserve these numbers). The format of the pattern for this call is a double 8 by 8 array holding a VDI color index (0 -- (colorindices - 1)) for EACH pixel. In the case of Borland C++ and Microsoft C, this is converted to the VGA (hardware) indices stored in ptable[]. In the case of an X-Workstation, the information is converted to a 16-color, 4-plane X-style Pixmap (tilepixmap). The default pattern number 256 is pre-defined but can be changed with this call. LIMITATIONS: 1. currently NO STORING of old patterns is done. ONLY ONE user-defined pattern is retained at a time. 2. the user can ONLY use colorindices 1--15 in the pattern otherwise the fill will be RIDICULOUSLY SLOW on a PC due to having to handle each index separately. */ { int i, j, k, vcol; if ((cols != 8) || (rows != 8)) return(-1); for (i = 0 ; i < 8 ; i++) /* use of ERASE index forbidden */ for (j = 0 ; j < 8 ; j++) if (col_index[i][j] == 0) return(-1); if (patt_index < 256) return(-1); else ptable_num = patt_index; for (i = 0 ; i < 16 ; i++) /* clean pattern_table */ for (j = 0 ; j < 8 ; j++) ptable[i][j] = 0x00; for (i = 0 ; i < 16 ; i++) /* scan for each VGA col index */ { for (j = 0 ; j < 8 ; j++) /* rows of col_index[][] */ { for (k = 0 ; k < 8 ; k++) /* cols of col_index[][] */ { if (col_index[j][k] > 15) vcol = col_index[j][k]; else vcol = vdi2vga[col_index[j][k]]; /* *** OLD *** vcol = vdi2vga[col_index[j][k]]; */ if (i == vcol) /* is there a match ? if so note that the kth column of col_index[][] corresponds to kth bit of ptable[index][]*/ ptable[i][j] = (unsigned char)(ptable[i][j] | (0x80 >> k)); } /* end of for (k ... */ } /* end of for (j ... */ } /* end of for (i ... */ #if defined(DESQ) /* X-Workstation */ /* update Pixmaps */ if (colorindices == 2) return(-1); /* Monochrome */ XFreePixmap(gksdisplay, tilepixmap); tilepixmap = XCreatePixmapFromBitmapData(gksdisplay, gkswindow, &ptable[0][0], 8, 8, gkscolors[vga2xwin[0]].pixel, gkscolors[vga2xwin[0]].pixel, DisplayPlanes(gksdisplay, gksscreen)); XCopyGC(gksdisplay, gksGC, 0L, tempGC); /* update tempGC */ /* Convert ptable[] VGA (hardware) entries to VDI X-Window 16-color, 4-plane Pixmap */ for (i = 0 ; i < 16 ; i++) { XFreePixmap(gksdisplay, pattpixmap[i]); pattpixmap[i] = XCreatePixmapFromBitmapData(gksdisplay, gkswindow, &ptable[i][0], 8, 8, gkscolors[vga2xwin[i]].pixel, gkscolors[vga2xwin[0]].pixel, DisplayPlanes(gksdisplay, gksscreen)); XFreePixmap(gksdisplay, pattbmp[i]); pattbmp[i] = XCreateBitmapFromData(gksdisplay, gkswindow, &ptable[i][0], 8, 8); XSetClipMask(gksdisplay, tempGC, pattbmp[i]); XSetForeground(gksdisplay, tempGC , gkscolors[vga2xwin[i]].pixel); XCopyArea(gksdisplay, pattpixmap[i], tilepixmap, tempGC, 0, 0, 8, 8, 0, 0); } patt_exist = 1; /* insurance */ #endif return(0); } /* end of gsetpattern */ /* ----------------------------------------------------------------------- */ int gfillpattern(int istyle, int cindex, int patt, int hatch) /* this function sets the fillpattern parameters for the calls: garc() gellipse() grectangle() gpolygon(). NOTE: an entry of -1 makes no change in the setting. Interior Style = 0 means HOLLOW or NO_FILL, Interior Style = 1 means SOLID_FILL with color index obtained from Fill_Color. Interior Style = 2 means PATTERN_FILL with either default pattern 256 or a user- defined pattern set with gsetpattern(). NOTE that patterns always REPLACE. Interior Style = 3 means HATCH_FILL with color index obtained from Fill_Color and type obtained from Hatch_Index as follows: 0 - horizontal lines 3 pixels apart 1 - vertical lines 3 pixels apart 2 - -45deg. diag. lines 3 pixels apart 3 - +45deg. diag. lines 3 pixels apart 4 - cross hatch 3 pixels apart 5 - cross hatch 7 pixels apart 6 - horizontal lines 7 pixels apart 7 - vertical lines 7 pixels apart. NOTE that hatching, which is meant to be compatible with VECTOR graphics is always OVERLAY mode. */ { int top; /* Interior_Style: 0=hollow 1=SOLID 2=PATTerned 3=HATCHed */ if (istyle >= 0 && istyle <= 3) flpattern[0] = istyle; /* Fill_Color: 0 -- 15 (active: SOLID_FILL and HATCH_FILL) */ if (colorindices > 16) top = colorindices; else top = 16; if (cindex >= 0 && cindex < top) flpattern[1] = cindex; /* Pattern_Index: (pre-set patterns 0 - 255 vary CONSIDERABLY on different machines. This library also pre-sets user pattern (rainbow) 256. Other user-defined patterns made with gsetpattern() should be given indices AT or ABOVE 256) */ if (patt >= 0) flpattern[2] = patt; /* Hatch_Index: (0 -- 7 as above) */ if (hatch >= 0) flpattern[3] = hatch % 8; return(0); } /* end of gfillpattern */ /* ----------------------------------------------------------------------- */ int gperimeter(int visib, int type, int cindex, int width) /* this function sets the perimeter style parameters for the calls: garc() gellipse() grectangle() gpolygon(). NOTE: an entry of -1 makes no change in the setting. ALSO NOTE: on the PC, perimeter style of CURVED objects is ALWAYS solid (unlike TEKTRONIX workstations). */ { int top; /* Visibility: 0=VISIBLE!!! 1=not visible */ if (visib == 0 || visib == 1) prmeter[0] = visib; /* Perim_Type: 0=solid 1=dashed 2=dotted 3=dotdash */ if (type >= 0 && type <= 3) prmeter[1] = type; /* Perim_Color: 0 -- 15 */ if (colorindices > 16) top = colorindices; else top = 16; if (cindex >= 0 && cindex < top) prmeter[2] = cindex; /* Perim_Width: in pixels but CURRENTLY FIXED at 1 */ if (width > 0) prmeter[3] = width; return(0); } /* end of gperimeter */ /* ----------------------------------------------------------------------- */ int ggetimage(int ll_x, int ll_y, int width, int height, int *pixel_wd, int *pixel_ht, long plane_mask, int format) /* This function searches the imagedesc[] table for a free position. If there is an available descriptor it tries to allocate memory for the image, and, if successful, transfers the image to a client-side structure and returns the POSITIVE value of the descriptor. It also returns the pixel dimensions (*pixel_wd by *pixel_ht). Otherwise it returns: -3 No available descriptors -2 Bad Parameter(s) -1 Memory allocation failed LIMITATIONS: 1. Currently only plane_mask=~0 (ALL_PLANES_MASK) is supported. 2. Currently only format=0 (DEFAULT_FORMAT for this device) is supported. However, if malloc() fails when memory is tight on the PC, this routine will use format=3 (TMPFILE_FORMAT). Therefore, it is advisable to set an environmental variable, e.g. "set RAM=E" in autoexec.bat so that these tmpfiles can be put on the RAMdisk, e.g. "E:\tmpfile.5" 3. If we run out of memory on the PC we let .pcolormap REMAIN NULL. */ { char *cptr, pathname[64]; long imsize, l; int i, j, k, px_ll, py_ll, px_ur, py_ur, cred, cgreen, cblue, hue, lite, sat; unsigned char ukhar; #if defined(DESQ) #elif defined(TURBEAUX) size_t tsize; /* size_t is defined in stdio.h as the size returned by the operator sizeof */ short *hptr1, *hptr2; char *bptr; #else short _huge *hptr1, *hptr2; char _huge *bptr; #endif k = 1; /* 0=reserved (and 1,2) */ while ( (k < max_imagedesc) && (imagedesc[k].active >= 1) ) k++; if (k >= max_imagedesc) return(-3); /* out of descriptors */ if ( (width <= 0) || (height <= 0) || (format != 0) || ((plane_mask & 0x0ff) != 0x0ff) ) return(-2); /* bad parameter(s) */ px_ll = xabspix(ll_x); /* convert to pixels */ py_ll = yabspix(ll_y); px_ur = xabspix(ll_x + width); py_ur = yabspix(ll_y + height); /* allocate memory for colormap */ imagedesc[k].pcolormap = (struct _cmap *)malloc(sizeof(struct _cmap)); if (imagedesc[k].pcolormap == NULL) { fprintf(stderr, "\nwarning: malloc() failed, struct _cmap NOT allocated"); fflush(stderr); /* *** OLD *** return(-1); (we now let the program continue) */ } if (imagedesc[k].pcolormap != NULL) for (i = 0 ; i < CMAP256 ; i++) imagedesc[k].pcolormap->used[i] = 0; /* init */ imagedesc[k].pwidth = px_ur - px_ll + 1; imagedesc[k].pheight = py_ll - py_ur + 1; #if defined(DESQ) /* X-Workstation */ /* ok, get image */ imagedesc[k].imageptr = (XImage *)XGetImage(gksdisplay, gkswindow, px_ll, py_ur, imagedesc[k].pwidth, imagedesc[k].pheight, AllPlanes, XYPixmap); imagedesc[k].format = 1; /* default here is XIMAGE_FORMAT */ imagedesc[k].bppixel = bitsppixel; imsize = (long)(imagedesc[k].pwidth) * (long)(imagedesc[k].pheight); #elif defined(TURBEAUX) /* Borland C++ */ imagedesc[k].format = 2; /* default is PC 8-planes format */ imsize = 4 + (long)(imagedesc[k].pwidth)* (long)(imagedesc[k].pheight); /* Borland cannot handle "huge" arrays */ if (imsize <= 0x0fff0) { tsize = (size_t)imsize; /* safe */ imagedesc[k].imageptr = malloc(tsize); } else { imagedesc[k].imageptr = NULL; } if ( (imsize > 0x0fff0) || (imagedesc[k].imageptr == NULL) ) { /* out of memory, try a temporary file */ cptr = (char *)getenv("RAM"); if (cptr == NULL) sprintf(pathname, "tmpfile.%d", k); else sprintf(pathname, "%s:\\tmpfile.%d", cptr, k); imagedesc[k].ifp = fopen(pathname, "wb"); if (imagedesc[k].ifp == NULL) return(-1); /* give up */ imagedesc[k].format = 3; /* tempfile format */ rewind(imagedesc[k].ifp); /* insurance */ } else { /* set pointers to short */ hptr1 = (short *)imagedesc[k].imageptr; hptr2 = hptr1 + 1; *hptr1 = (short)imagedesc[k].pwidth; *hptr2 = (short)imagedesc[k].pheight; } imagedesc[k].bppixel = 8; /* we always use 8 */ #else /* Microsoft C */ imagedesc[k].format = 2; /* default is PC 8-planes format */ imsize = 4 + (long)(imagedesc[k].pwidth)* (long)(imagedesc[k].pheight); /* this is a "huge" allocation */ imagedesc[k].imageptr = halloc(imsize, sizeof( char)); if (imagedesc[k].imageptr == NULL) { /* out of memory, try a temporary file */ cptr = (char *)getenv("RAM"); if (cptr == NULL) sprintf(pathname, "tmpfile.%d", k); else sprintf(pathname, "%s:\\tmpfile.%d", cptr, k); imagedesc[k].ifp = fopen(pathname, "wb"); if (imagedesc[k].ifp == NULL) return(-1); /* give up */ imagedesc[k].format = 3; /* tempfile format */ rewind(imagedesc[k].ifp); /* insurance */ } else { /* set (huge) pointers to short */ hptr1 = (short _huge *)imagedesc[k].imageptr; hptr2 = hptr1 + 1; *hptr1 = (short)imagedesc[k].pwidth; *hptr2 = (short)imagedesc[k].pheight; } imagedesc[k].bppixel = 8; /* we always use 8 */ #endif imagedesc[k].bytes_alloc = (long)imsize; imagedesc[k].active = 1; imagedesc[k].valid = 1; /* malloc(or tmpfile) ok */ imagedesc[k].pwindow[0] = px_ll; imagedesc[k].pwindow[1] = py_ll; imagedesc[k].pwindow[2] = px_ur; imagedesc[k].pwindow[3] = py_ur; *pixel_wd = imagedesc[k].pwidth; *pixel_ht = imagedesc[k].pheight; #if defined(DESQ) /* X-Workstation */ /* scan XImage for colormap */ if (imagedesc[k].pcolormap != NULL) for (i = 0 ; i < imagedesc[k].pheight ; i++) { j = 0; while (j < imagedesc[k].pwidth) { ukhar = (unsigned char)(xormask & XGetPixel((XImage *)imagedesc[k].imageptr, j, i)); /* *** BAD DIAGNOSTIC *** Warning: ukhar is the X11 HARDware index according to the function i -> pseudo_index[i] = ukhar 0 <= i < colorindices but ukhar need NOT be in this range. if ( ((int)ukhar < 0) || ((int)ukhar >= colorindices) ) { fprintf(stderr, "\nXGetPixel(ukhar=0x0%x) colorindices=%d", (int)ukhar, colorindices); fflush(stderr); } */ imagedesc[k].pcolormap->used[ukhar] = 1; j++; } /* end of while (j < imagedesc[k].pwidth) */ } #elif defined(TURBEAUX) /* Borland C++ */ if (imagedesc[k].format == 2) { bptr = (char *)imagedesc[k].imageptr + 4; } for (i = 0 ; i < imagedesc[k].pheight ; i++) { j = 0; while (j < imagedesc[k].pwidth) { ukhar = (xormask & getpixel(px_ll + j, py_ur + i)); if (imagedesc[k].pcolormap != NULL) imagedesc[k].pcolormap->used[ukhar] = 1; if (imagedesc[k].format == 2) { *bptr = ukhar; bptr++; } else if (imagedesc[k].format == 3) { fputc(ukhar, imagedesc[k].ifp); } j++; } } if (imagedesc[k].format == 3) { fclose(imagedesc[k].ifp); /* close and re-open so mode is "rb" */ imagedesc[k].ifp = fopen(pathname, "rb"); } #else /* Microsoft C */ if (imagedesc[k].format == 2) { bptr = (char *)imagedesc[k].imageptr + 4; } for (i = 0 ; i < imagedesc[k].pheight ; i++) { j = 0; while (j < imagedesc[k].pwidth) { ukhar = (unsigned char)(xormask & _getpixel((short)(px_ll + j), (short)(py_ur + i)) ); if (imagedesc[k].pcolormap != NULL) imagedesc[k].pcolormap->used[ukhar] = 1; if (imagedesc[k].format == 2) { *bptr = ukhar; bptr++; } else if (imagedesc[k].format == 3) { fputc(ukhar, imagedesc[k].ifp); } j++; } } if (imagedesc[k].format == 3) { fclose(imagedesc[k].ifp); /* close and re-open so mode is "rb" */ imagedesc[k].ifp = fopen(pathname, "rb"); } #endif /* finish recording colormap at time of creation. Note that these are HARDWARE color indices. */ imagedesc[k].maxbright = 99; /* we use %-age scale */ if (imagedesc[k].pcolormap != NULL) for (i = 0 ; i < CMAP256 ; i++) { if (imagedesc[k].pcolormap->used[i] == 0) continue; /* not used */ l = colorsarray[i]; /* get setting */ cred = (int)(l & 0x0000ffL); cgreen = (int)((l & 0x00ff00L) >> 8); cblue = (int)((l & 0xff0000L) >> 16); imagedesc[k].pcolormap->r[i] = (unsigned char)((99 * cred)/63); imagedesc[k].pcolormap->g[i] = (unsigned char)((99 * cgreen)/63); imagedesc[k].pcolormap->b[i] = (unsigned char)((99 * cblue)/63); /* Also save approx value of "hue" for ease of use with image routines (note: 1 <= used[] <= 91) */ rgb2hls(cred, cgreen, cblue, &hue, &lite, &sat); imagedesc[k].pcolormap->used[i] = (unsigned char)((hue + 4) >> 2); } return(k); } /* end of ggetimage */ /* ----------------------------------------------------------------------- */ extern int enqimage(int desc, int *pixel_wd, int *pixel_ht, long *plane_mask, int *format, struct _cmap *pcolmap); /* in xstate.c */ /* ----------------------------------------------------------------------- */ int ggetimagepixel(int desc, int xpx, int ypx) /* This function accepts a descriptor of a (previously gotten) image, and pixel coordinates (origin is in UPPER LEFT corner), and returns the hardware color index (i.e. 0 <= index < colorindices: note that X11 has an ADDITIONAL permutation of i -> pseudo_index[i] which is the X11 HARDware (squared?) unsigned long pixel index) that the pixel was set to at the time of image creation. This HARDWARE color index is always correct but the relationship between vdi and hardware indices is a permutation: if (vdi > 15) hardware = vdi else hardware = vdi2vga[vdi] or if (hardware > 15) vdi = hardware else vdi = vga2vdi[hardware] Anyway, if you use images a lot it is strongly recommended that you reserve the first 16 color indices (0--15) for your menu colors, etc. Note: THIS CALL DOES NOT GET A PIXEL FROM THE SCREEN unless you first use ggetimage() to capture a portion of the screen as an image. It returns -3 Bad Descriptor -2 Bad Parameter(s) -1 Descriptor Not (Active and Valid) 0 ok, and pertinent color index was returned. */ { int index, ondisk; #if defined(DESQ) int i; unsigned long pixel; #endif if ( (desc <= 0) || (desc >= max_imagedesc) ) return(-3); /* out of range */ if ( (imagedesc[desc].active <= 0) || (imagedesc[desc].valid <= 0) ) return(-1); /* not (active & valid) */ if ( (xpx >= imagedesc[desc].pwidth) || (xpx < 0) || (ypx >= imagedesc[desc].pheight) || (ypx < 0) ) return(-2); /* bad parameter(s) */ /* check format */ if ( (imagedesc[desc].format == 1) || (imagedesc[desc].format == 2) ) { ondisk = 0; /* in memory */ } else if ( (imagedesc[desc].format == 3) && (imagedesc[desc].ifp != (FILE *)NULL) ) { ondisk = 1; /* in a temporary file */ rewind(imagedesc[desc].ifp); } else { return(-1); /* invalid format */ } #if defined(DESQ) if (imagedesc[desc].format == 1) /* Ximage */ { pixel = XGetPixel((XImage *)imagedesc[desc].imageptr, xpx, ypx); /* *** OLD *** index = (int)pixel & xormask; return(index); */ /* X11 has another HARDware (squared?) layer of abstraction: i -> vdi_index -> pseudo_index[vdi_index] so for now we search for i given pseudo_index[i] */ for (i = 0 ; i < colorindices ; i++) if (gkscolors[i].pixel == pixel) break; if (gkscolors[i].pixel == pixel) { return(i); } else { /* *** DIAGNOSTIC *** */ fprintf(stderr, "\nggetimagepixel(pixel=0x0%lx) NOT found in search: colorindices=%d", pixel, colorindices); fflush(stderr); return(0); } } #endif if (imagedesc[desc].format == 2) /* PC format */ { /* damn vax "signed" characters! */ index = xormask & (*((char *)imagedesc[desc].imageptr + 4 + (ypx*imagedesc[desc].pwidth) + xpx)); } else if (ondisk) { /* (long)'s below important for PC'S */ fseek(imagedesc[desc].ifp, (long)(((long)ypx*(long)imagedesc[desc].pwidth) + xpx), SEEK_SET); index = fgetc(imagedesc[desc].ifp) & xormask; } return(index); } /* end of ggetimagepixel */ /* ----------------------------------------------------------------------- */ int gputimage(int desc, int ll_x, int ll_y, int xmag, int ymag, int action) /* This function puts a (previously) gotten image at the new location (ll_x, ll_y) drawing with action 0=Copy ONLY at this time, and with positive integer magnifications in the x and y directions. It returns -3 Bad Descriptor -2 Bad Parameter(s) -1 Descriptor Not (Active and Valid) 0 ok, and pertinent image was transferred */ { int px_ul, py_ul, ondisk, starti; #if defined(DESQ) int i, j, k, l; unsigned long pixel; #elif defined(TURBEAUX) char *bptr; int i, j, k, l, col; #else short col, lastcol; char _huge *bptr; int i, j, k, l; #endif if ( (desc <= 0) || (desc >= max_imagedesc) ) return(-3); /* out of range */ if ( (xmag <= 0) || (ymag <= 0) || (action != 0) ) return(-2); /* bad parameter(s) */ if ( (imagedesc[desc].active <= 0) || (imagedesc[desc].valid <= 0) ) return(-1); /* not (active & valid) */ /* compute upper left in pixels */ px_ul = xabspix(ll_x); py_ul = yabspix(ll_y) - (imagedesc[desc].pheight * ymag) + 1; /* check format */ if ( (imagedesc[desc].format == 1) || (imagedesc[desc].format == 2) ) { ondisk = 0; /* in memory */ } else if ( (imagedesc[desc].format == 3) && (imagedesc[desc].ifp != (FILE *)NULL) ) { ondisk = 1; /* in a temporary file */ rewind(imagedesc[desc].ifp); } else { return(-1); /* invalid format */ } #if defined(DESQ) /* try to save some time for large mag's */ if ( (py_ul < pixviewext[1]) && (ymag > 0) ) { starti = (pixviewext[1] - py_ul)/ymag; if (ondisk) fseek(imagedesc[desc].ifp, (long)((long)starti*(long)imagedesc[desc].pwidth), SEEK_SET); } else { starti = 0; } for (i = starti ; i < imagedesc[desc].pheight ; i++) { for (k = 0 ; k < ymag ; k++) { j = 0; while (j < imagedesc[desc].pwidth) { if (ondisk) /* unusual */ { pixel = fgetc(imagedesc[desc].ifp) & xormask; } else { if (imagedesc[desc].format == 2) /* PC format */ /* damn vax "signed" characters! */ pixel = 0x00ff & (*((char *)imagedesc[desc].imageptr + 4 + (i*imagedesc[desc].pwidth) + j)); else if (imagedesc[desc].format == 1) /* get pixel FROM XImage */ pixel = XGetPixel((XImage *)imagedesc[desc].imageptr, j, i); } /* *** DIAGNOSTIC *** Warning: pixel is the X11 HARDware index according to the function i -> pseudo_index[i] = pixel 0 <= i < colorindices but pixel need NOT be in this range. */ if ( (imagedesc[desc].format != 1) && ( (pixel < 0L) || (pixel >= (long)colorindices) ) ) { fprintf(stderr, "\ngputimage: .format=%d pixel=0x0%lx BUT colorindices=%d", imagedesc[desc].format, pixel, colorindices); fflush(stderr); } /* X11 has another HARDware (squared?) layer of abstraction: i -> vdi_index -> pseudo_index[vdi_index] */ if (imagedesc[desc].format == 1) SET_HARD_COLOR(pixel); else SETCOLOR(pixel); for (l = 0 ; l < xmag ; l++) { /* set "l" duplicate pixels */ SETPIXEL(px_ul + (j*xmag) + l, py_ul + (i*ymag) + k); } j++; } /* end of for (j = ... */ if (k < (ymag - 1)) { /* reset for duplicate line */ if (ondisk) fseek(imagedesc[desc].ifp, (long)(-imagedesc[desc].pwidth), SEEK_CUR); } } /* end of for (k = ... */ } /* end of for (i = ... */ #elif defined(TURBEAUX) /* Borland C++ */ /* try to save some time for large mag's */ if ( (py_ul < pixviewext[1]) && (ymag > 0) ) { starti = (pixviewext[1] - py_ul)/ymag; if (ondisk) fseek(imagedesc[desc].ifp, (long)((long)starti*(long)imagedesc[desc].pwidth), SEEK_SET); else bptr = (char *)imagedesc[desc].imageptr + 4 + starti*imagedesc[desc].pwidth; } else { starti = 0; if (!ondisk) bptr = (char *)imagedesc[desc].imageptr + 4; } for (i = starti ; i < imagedesc[desc].pheight ; i++) { for (k = 0 ; k < ymag ; k++) { j = 0; while (j < imagedesc[desc].pwidth) { if (ondisk) col = fgetc(imagedesc[desc].ifp) & xormask; else col = (*bptr) & xormask; /* Borland's putpixel sets color index as well (whereas Microsoft's _setpixel sets in the current color) */ for (l = 0 ; l < xmag ; l++) /* set "l" duplicate pixels but allow for a clip rectangle (which forces damn "relative" coordinates) */ if (fullviewind != 0) putpixel( px_ul + (j*xmag) + l, py_ul + (i*ymag) + k, col); else putpixel( px_ul + (j*xmag) + l - pixviewext[0], py_ul + (i*ymag) + k - pixviewext[1], col); if (!ondisk) bptr++; j++; } /* end of for (j = ... */ if (k < (ymag - 1)) { /* reset for duplicate line */ bptr = bptr - imagedesc[desc].pwidth; if (ondisk) fseek(imagedesc[desc].ifp, (long)(-imagedesc[desc].pwidth), SEEK_CUR); } } /* end of for (k = ... */ } /* end of for (i = ... */ #else /* Microsoft C++ */ /* try to save some time for large mag's */ if ( (py_ul < pixviewext[1]) && (ymag > 0) ) { starti = (pixviewext[1] - py_ul)/ymag; if (ondisk) fseek(imagedesc[desc].ifp, (long)((long)starti*(long)imagedesc[desc].pwidth), SEEK_SET); else bptr = (char _huge *)imagedesc[desc].imageptr + 4 + starti*imagedesc[desc].pwidth; } else { starti = 0; if (!ondisk) bptr = (char _huge *)imagedesc[desc].imageptr + 4; } if (ondisk) lastcol = 0; else lastcol = (*bptr) & xormask; _setcolor(lastcol); for (i = starti ; i < imagedesc[desc].pheight ; i++) { for (k = 0 ; k < ymag ; k++) { j = 0; while (j < imagedesc[desc].pwidth) { if (ondisk) col = fgetc(imagedesc[desc].ifp) & xormask; else col = (*bptr) & xormask; if (col != lastcol) { _setcolor(col); lastcol = col; } for (l = 0 ; l < xmag ; l++) /* set "l" duplicate pixels */ _setpixel(px_ul + (j*xmag) + l, py_ul + (i*ymag) + k); if (!ondisk) bptr++; j++; } /* end of for (j = ... */ if (k < (ymag - 1)) { /* reset/partial rewind for duplicate line */ bptr = bptr - imagedesc[desc].pwidth; if (ondisk) fseek(imagedesc[desc].ifp, (long)(-imagedesc[desc].pwidth), SEEK_CUR); } } /* end of for (k = ... */ } /* end of for (i = ... */ #endif return(0); } /* end of gputimage */ /* ----------------------------------------------------------------------- */ int gfreeimage(int desc) /* This function frees a (previously) gotten image */ { if ( (desc <= 0) || (desc >= max_imagedesc) ) return(-3); /* out of range */ if ( (imagedesc[desc].active <= 0) || (imagedesc[desc].valid <= 0) ) return(-1); /* not (active & valid) */ #if defined(DESQ) if (imagedesc[desc].active <= 1) /* not reserved */ { if (imagedesc[desc].format == 2) /* PC format */ { free((void *)imagedesc[desc].imageptr); imagedesc[desc].imageptr = (void *)NULL; } else if (imagedesc[desc].format == 1) /* XImage */ { XDestroyImage((XImage *)imagedesc[desc].imageptr); imagedesc[desc].imageptr = (XImage *)NULL; } imagedesc[desc].active = 0; imagedesc[desc].valid = 0; } #elif defined(TURBEAUX) if (imagedesc[desc].active <= 1) /* not reserved */ { if (imagedesc[desc].format == 2) free(imagedesc[desc].imageptr); else if (imagedesc[desc].format == 3) fclose(imagedesc[desc].ifp); imagedesc[desc].imageptr = NULL; imagedesc[desc].active = 0; imagedesc[desc].valid = 0; } #else if (imagedesc[desc].active <= 1) /* not reserved */ { if (imagedesc[desc].format == 2) /* pointer is "huge" here */ hfree(imagedesc[desc].imageptr); else if (imagedesc[desc].format == 3) fclose(imagedesc[desc].ifp); imagedesc[desc].imageptr = NULL; imagedesc[desc].active = 0; imagedesc[desc].valid = 0; } #endif return(0); } /* end of gfreeimage */ /* ----------------------------------------------------------------------- */ int setechostate(int echo_array[]) /* This sets flags for echo (1-default) or no echo (0) for echo_array[1] = string LIMITATIONS: The other input devices currently have echostate FIXED at 1: locator pick stroke choice valuator */ { if (echo_array[1] == 0) echostate[1] = 0; else if (echo_array[1] == 1) echostate[1] = 1; return(0); } /* end of setechostate */ /* ----------------------------------------------------------------------- */ int setpromptstate(int prompt_array[]) /* This sets flags for prompt (1-default) or no prompt (0) for prompt_array[1] = string LIMITATIONS: The other input devices currently have echostate FIXED at 1: locator pick stroke choice valuator */ { if (prompt_array[1] == 0) promptstate[1] = 0; else if (prompt_array[1] == 1) promptstate[1] = 1; return(0); } /* end of setpromptstate */ /* ----------------------------------------------------------------------- */ int initstring(int idev, int igwin, int xll, int yll, int xur, int yur) /* This function initilizes string input (via reqstring()) as follows: idev sets the ACTIVE string input device (this is almost always "keyboard" but you can use -1 for "generic") if igwin = -1 then string window is fullscreen else if igwin = 0 then window is (xll,yll,xur,yur) else (other values are for future expansion) */ { strgactive = idev; if (igwin < 0) { strgwindow[0] = 0; strgwindow[1] = 0; strgwindow[2] = (int)xvdlaxis; strgwindow[3] = (int)yvdlaxis; } else if ((igwin == 0) && (xll < xur) && (yll < yur)) { strgwindow[0] = xll; strgwindow[1] = yll; strgwindow[2] = xur; strgwindow[3] = yur; } return(0); } /* end of initstring */ /* ----------------------------------------------------------------------- */ int reqstring(int idev, int max_allowed, char strng[], int *pact_length) /* This function REQUESTS_INPUT on the GKS STRING. The default idev is ALWAYS the console but one can use idev = -1 for GENERIC. The default is for a prompt to appear (unless promptstate[] has been reset) and for characters to be echoed as typed (unless echostate[1] has been reset). */ { char str[16]; int xp,yp,i,j,k,xroom,xpxl,ypxl,event,ret; unsigned mask; if (idev != strgactive); /* do nothing for now */ if (max_allowed < 1) /* protection */ { strng[0] = '\0'; *pact_length = 0; return(0); } xp = xpixlast; yp = ypixlast; SETCOLOR(COLINDEX(txcolor)); /* temp change color */ i = 0; xroom = xpix(strgwindow[2]) - XMASK - 2; mask = SUPPRESS_KEYRELEASE; /* important for X-Workstation */ while (i < max_allowed) { if (promptstate[1] == 1 && xroom > xp) /* show cursor */ put_mask(&amr10[63][0],0,xp,yp,1); /* call await_wk_event() to handle PC and X-Workstation differences */ ret = 0; event = 0x0000; /* no keyboard press yet */ while( (!(event & 0x0008)) && (ret == 0) ) ret = await_wk_event(mask, &event, str, &xpxl, &ypxl); if (ret < 0) { i = 0; goto cleanup; /* failure in await_wk_event() */ } for (k = 0 ; k < (int)strlen(str) ; k++) { j = (int)str[k]; if (j == '\n' || j == 13 || j == EOF) goto cleanup; if (j == 127 || j == 8) /* delete or backspace */ { /* remove */ if (promptstate[1] == 1 && xroom > xp) put_mask(&amr10[0][0],0,xp,yp,1); if (i > 0) xp = xp - XMASK - 1; /* move back */ if (promptstate[1] == 0 && xroom > xp) put_mask(&amr10[0][0],0,xp,yp,1); if (xp < 0) xp = 0; i--; if (i < 0) i = 0; } else { if ((echostate[1] == 1) && (xroom > xp) && (j >= 32) && (j < 127) ) /* add one char */ put_mask(&amr10[j - 32][0],0,xp,yp,1); xp = xp + XMASK + 1; /* move to next char cell */ strng[i] = (char)j; i++; } } /* end of for (k = 0 ... */ } /* end of while (i < max_allowed) */ cleanup: if (promptstate[1] == 1 && xroom > xp) /* remove */ put_mask(&amr10[0][0],0,xp,yp,1); strng[i] = '\0'; *pact_length = i; SETCOLOR(COLINDEX(lncolor)); /* restore color */ xpixlast = xp; ypixlast = yp; /* update */ xlast = xinvpix(xp); ylast = yinvpix(yp); return(0); } /* end of reqstring */ /* ----------------------------------------------------------------------- */ int initlocator(int idev, int igwin, int cseg, int xll, int yll, int xur, int yur, int grid, int band) /* This function initializes locator input as follows: idev sets the ACTIVE locator (you can ALWAYS use -1 for "generic") if on X-Workstation, ginwindow is ALWAYS fullscreen for obvious reasons, otherwise: if igwin = -1 locator window is fullscreen else if igwin = 0 locator window is (xll,yll,xur,yur) else (other values are for future expansion) cseg must be a valid descriptor for the locator cursor such as 1 small cross (+) in BrightWhite 0 large tektronix-style crosshairs in XOR 2 boldarrow X11-type 16 x 16 bitmap cursor 3 squarebox X11-type 16 x 16 bitmap cursor grid, when set, activates GIN snap grid (computing locator coords to nearest grid point) band, when set, activates GIN rubberbanding: 0 no band 1,2 rubberband 3,4 enclosing rectangle */ { locactive = idev; if (igwin < 0) { locwindow[0] = 0; locwindow[1] = 0; locwindow[2] = (int)xvdlaxis; locwindow[3] = (int)yvdlaxis; locpwindow[0] = 0; locpwindow[1] = (int)vcylong; locpwindow[2] = (int)vcxlong; locpwindow[3] = 0; } else if ((igwin == 0) && (xll < xur) && (yll < yur)) { locwindow[0] = xll; locwindow[1] = yll; locwindow[2] = xur; locwindow[3] = yur; locpwindow[0] = xabspix(locwindow[0]); locpwindow[2] = xabspix(locwindow[2]); locpwindow[3] = yabspix(locwindow[3]); locpwindow[1] = yabspix(locwindow[1]); } if ( (cseg >= 0) && (cseg < max_descript) && (descript[cseg].active >= 1) && (descript[cseg].assoccurs == 1) ) loccursor = cseg; if (grid == 0) locgrid = 0; if (grid == 1) locgrid = 1; if ((band >= 0) && (band <= 4)) locband = band; return(0); } /* end of initlocator */ /* ======================================================================= The next call will report Expose events (window was partially obscured the exposed) found during await_wk_event(): ======================================================================= */ int enq_expose(int clear_flag) /* This function checks if there has been an Expose event since last clearing the expose_flag. It returns the expose flag and if clear_flag is set, also clears the expose flag */ { int k; k = expose_flag; if (clear_flag) expose_flag = 0; return(k); } /* end of enq_expose */ /* ======================================================================= The next 12 calls are (mostly dummy) segment operations which will allow linkage of programs which run on a variety of platforms: ======================================================================= */ int creatsegment(int iname, int xpiv, int ypiv) { if (iname < 100); /* do nothing for now */ if ((xpiv < 0) || (ypiv < 0)); return(-1); } /* end of creatsegment */ /* ----------------------------------------------------------------------- */ int closesegment(void) { int dummy; dummy = -1; /* do nothing for now */ return(dummy); } /* end of closesegment */ /* ------------------------------------------------------------------------ */ int insrtsegment(int iold) { if (iold < 100); /* do nothing for now */ return(-1); } /* end of insrtsegment */ /* ----------------------------------------------------------------------- */ int deletsegment(int iname) { if (iname < 100); /* do nothing for now */ return(-1); } /* end of deletsegment */ /* ----------------------------------------------------------------------- */ int renamsegment(int iold, int inew) { if ((iold < 0) || (inew < 0)); /* do nothing */ return(-1); } /* end of renamsegment */ /* ---------------------------------------------------------------------- */ int stvissegment(int iname, int ivisib) /* This function sets segment visibility when given a valid descriptor for either a SEGMENT or XBITMAP/Cursor, such as: segment 1 = small crosshairs (BRIGHT_WHITE) segment 0 = tektronix-style crosshairs (XOR) 2 = boldarrow X11-type 16 x 16 bitmap cursor 3 = squarebox X11-type 16 x 16 bitmap cursor 4 = vertical_bar X11-type 16 x 16 bitmap cursor 5 = horizontal_bar X11-type 16 x 16 bitmap cursor with any associated banding (RUBBERBAND or RECTANGLE_BAND). A top-end Workstation supporting dynamic segments usually allows one to use any moderately sized segment for a cursor. */ { int xp,yp; #if defined(DESQ) /* X-Workstation */ int gapl_x, gapr_x, gapt_y, gapb_y; #else /* Borland C++, Microsoft C */ int i, j, k, px, py, c, rowbytes, index, curcolor; unsigned char tb; #endif xp = xlocplast; yp = ylocplast; /* Check for any banding (ivisib == 1) */ if ( (ivisib) && ((locband == 1) || (locband == 2)) ) dda_line(7, xlocpband,ylocpband,xp,yp); else if ( (ivisib) && ((locband == 3) || (locband == 4)) ) dda_rect(7, xp, yp, xlocpband, ylocpband); #if defined(DESQ) /* X-Workstation */ /* DESCRIPTORS 1, 2, ... : Automatic with X-Workstation */ #else /* Borland C++, Microsoft C */ if (iname == 1) { if (ivisib == 1) /* save screen */ { for (i = 0 ; i < SMCROSS_DIM ; i++) { savehorz[i] = GETPIXEL(xp+i - SMCROSS_HALF,yp); savevert[i] = GETPIXEL(xp,yp+i - SMCROSS_HALF); } SETCOLOR(COLINDEX(7)); for (i = 0 ; i < SMCROSS_DIM ; i++) { SETPIXEL(xp+i - SMCROSS_HALF,yp); SETPIXEL(xp,yp+i - SMCROSS_HALF ); } } else if (ivisib == 0) /* restore screen */ { for (i = 0 ; i < SMCROSS_DIM ; i++) { if ((k = savehorz[i]) != -1) { SETCOLOR(k); SETPIXEL(xp+i - SMCROSS_HALF,yp); } if ((k = savevert[i]) != -1) { SETCOLOR(k); SETPIXEL(xp,yp+i - SMCROSS_HALF); } } } goto stvdone; /* end of SEGMENT 1 */ } /* end of if (iname == 1) */ else if (iname > 1) { /* Check Descriptor and Associated Cursor */ if ((iname < 0) || (iname >= max_descript)) return(-1); if (descript[iname].active == 0) return(-1); if (descript[iname].assoccurs == 0) return(-1); px = xp - descript[iname].curs_xh; py = yp - descript[iname].curs_yh; if ((unsigned)descript[iname].curs_fg > 15) c = (unsigned)descript[iname].curs_fg; else c = vdi2vga[ (unsigned)descript[iname].curs_fg ]; SETCOLOR(c); curcolor = c; /* need to record current color */ rowbytes = (descript[iname].width)/8; for (i = 0 ; i < (descript[iname].height) ; i++) for (j = 0 ; j < rowbytes ; j++) { tb = descript[iname].bits[(i * rowbytes) + j]; /* byte */ for (k = 0 ; k < 8 ; k++) { if (ivisib) /* save and post */ { descript[iname].save_bits[(i * rowbytes * 8) + (j * 8) + k] = (char)GETPIXEL(px + (j * 8) + k, py + i); if ((tb & 0x01) != 0x00) SETPIXEL(px + (j * 8) + k, py + i); } else /* restore */ { if ((tb & 0x01) != 0x00) { index = descript[iname].save_bits[(i * rowbytes * 8) + (j * 8) + k]; if (index != curcolor) { SETCOLOR(index); /* change color */ curcolor = index; /* current color */ } SETPIXEL(px + (j * 8) + k, py + i); } } /* end of if (ivisib) ... else ... */ tb = (unsigned char)(tb >> 1); /* next bit */ } /* end of for (k = 0 ; ... */ } /* end of for (j = 0 ; ... */ goto stvdone; } /* end of if (iname > 1) */ #endif /* SEGMENT 0: Tektronic style LARGE CROSSHAIRS in XOR */ if (iname != 0) goto stvdone; /* Others are already DONE */ #if defined(DESQ) /* Some setup here */ if (xp >= 8) gapl_x = xp - 8; else gapl_x = 0; if (xp <= (short)vcxlong - 9) gapr_x = xp + 8; else gapr_x = vcxlong - 1; if (yp >= 8) gapt_y = yp - 8; else gapt_y = 0; if (yp <= (short)vcylong - 9) gapb_y = yp + 8; else gapb_y = vcylong - 9; #endif #if defined(DESQ) /* X-Workstation */ dda_line(7, xp, 0, xp, gapt_y); dda_line(7, xp, gapb_y, xp, (int)(vcylong - 1)); dda_line(7, 0, yp, gapl_x, yp); dda_line(7, gapr_x, yp, (int)(vcxlong - 1), yp); #elif defined(TURBEAUX) /* Borland C++ */ if (screencode == _VRES16COLOR) { SETCOLOR(COLINDEX(7)); setwritemode(XOR_PUT); /* fast, BUT a hardware index XOR which is VGA specific. Don't use this mode with screencode == _8514COLOR (try it if you don't believe me!) */ MOVETO(0, yp); LINETO((int)(vcxlong-1), yp); MOVETO(xp, 0); LINETO(xp, (int)(vcylong-1)); setwritemode(COPY_PUT); } else /* for _8514COLOR */ { dda_line(7, 0, yp, (int)(vcxlong-1), yp); dda_line(7, xp, 0, xp, (int)(vcylong-1)); } #else /* Microsoft C */ SETCOLOR(COLINDEX(7)); _setwritemode(_GXOR); /* fast, BUT again a hardware index XOR */ MOVETO(0, yp); LINETO((int)(vcxlong-1), yp); MOVETO(xp, 0); LINETO(xp, (int)(vcylong-1)); _setwritemode(_GPSET); #endif stvdone: /* Check for any banding (ivisib == 0) */ if ( (ivisib == 0) && ((locband == 1) || (locband == 2)) ) dda_line(7, xlocpband,ylocpband,xp,yp); else if ( (ivisib == 0) && ((locband == 3) || (locband == 4)) ) dda_rect(7, xp, yp, xlocpband, ylocpband); SETCOLOR(COLINDEX(lncolor)); /* restore color */ return(0); /* end of SEGMENT 0 */ } /* end of stvissegment */ /* ----------------------------------------------------------------------- */ int sthltsegment(int iname, int hl_flag) { if (iname < 100); /* do nothing for now */ if ((hl_flag != 0) && (hl_flag != 1)); return(-1); } /* end of sthltsegment */ /* ----------------------------------------------------------------------- */ int stdetsegment(int iname, int dt_flag) { if (iname < 100); /* do nothing for now */ if ((dt_flag != 0) && (dt_flag != 1)); return(-1); } /* end of stdetsegment */ /* ----------------------------------------------------------------------- */ int stprisegment(int iname, int pr_level) { if (iname < 100); /* do nothing for now */ if (pr_level == 0); return(-1); } /* end of stprisegment */ /* ---------------------------------------------------------------------- */ int stpidsegment(int pick_id) { if (pick_id < 0); /* do nothing for now */ return(-1); } /* end of stpidsegment */ /* --------------------------------------------------------------------- */ int sttrnsegment(int iname, double xsc, double ysc, double deg, int new_x, int new_y) { if (iname < 100); /* do nothing for now */ if ((xsc < 0.0) || (ysc < 0.0)); if (deg == 0.0); if ((new_x < 0) || (new_y < 0)); return(-1); } /* end of sttrnsegment */ /* ---------------------------------------------------------------------- */ int renewview(int iview) { if (iview != 0); /* do nothing for now */ return(-1); } /* end of renewview */ /* ----------------------------------------------------------------------- */ int gloc(int xvdl, int yvdl) /* This function moves the current locator position, given virtual device coordinates. It also updates (xloclast, yloclast) */ { xloclast = xvdl; yloclast = yvdl; gloc_pix(xabspix(xvdl), yabspix(yvdl)); return(0); } /* end of gloc */ /* ----------------------------------------------------------------------- */ int ggrid(int xm_vdl, int ym_vdl) /* This function sets the GIN (snap) grid, i.e. this computes locator coordinates to the nearest xm_vdl and nearest ym_vdl if gridding has been activated in initlocator() . SIDE EFFECT: Gridding rounds off (modulo the grid spacing) so, for example, it may return 3100 (for 3071) and this is offscreen. */ { if (xm_vdl <= 1) xmodgrid = 1; /* normal */ else xmodgrid = xm_vdl; if (ym_vdl <= 1) ymodgrid = 1; /* normal */ else ymodgrid = ym_vdl; return(0); } /* end of ggrid */ /* ----------------------------------------------------------------------- */ int gpick(int xvdl, int yvdl) /* This function sets the position at which the pick cursor will appear, if it is not used, then the last pick position will be used. */ { xpiklast = xvdl; ypiklast = yvdl; xpikplast = xabspix(xvdl); ypikplast = yabspix(yvdl); return(0); } /* end of gpick */ /* ------------------------------------------------------------------------ */ int gbell(void) /* This Function rings the workstation bell */ { #if defined(DESQ) /* X-Workstation */ XBell(gksdisplay, 75); #else putchar('\a'); #endif return(0); } /* end of gbell */ /* ----------------------------------------------------------------------- */ int reqlocator(int idev, int *statptr, char *keyptr, int *xptr, int *yptr) /* This function REQUESTS_INPUT on the GKS LOCATOR. One can use idev = -1 for GENERIC. This function returns -1 if the device is non-existent, otherwise it returns 0. Note: char *keyptr */ { char str[16]; int code; int xpxl,ypxl,event,ret,reset,xpixul,xpixlr,ypixul,ypixlr; unsigned mask; #if defined(DESQ) /* X-Workstation */ /* Change to Crosshairs */ if ( (loccursor == 1) || (loccursor == 0) ) XDefineCursor(gksdisplay, gkswindow, smcrosscurs); else { /* Check Descriptor and Associated Cursor */ if ( (loccursor >= 0) && (loccursor < max_descript) && (descript[loccursor].active >= 1) && (descript[loccursor].assoccurs == 1) ) XDefineCursor(gksdisplay, gkswindow, descript[loccursor].curs); } #endif if ( (idev >= 0) && (idev != 2) && (idev != 3) ) return(-1); /* bad device number */ code = 0; /* expect no more errors */ mask = 0x0000; if ( (locband) /* check for banding */ || (!loccursor) /* or for large crosshairs */ #if defined(DESQ) ) #else || (loccursor) ) /* PC: always check motion */ #endif { mask = MOUSE_MOTION; /* update position on a continuous basis */ xlocpband = xlocplast; ylocpband = ylocplast; } /* always update position on button */ mask = mask | MOUSE_UPDATE | SUPPRESS_KEYRELEASE; if (fullviewind == 0) /* check if cliprgn enabled since this will interfere with GIN window and we would have the ADDITIONAL COMPLICATION OF RELATIVE COORDINATES with the Borland viewport. */ { xpixul = xabspix(0); ypixul = yabspix((int)yvdlaxis); xpixlr = xabspix((int)xvdlaxis); ypixlr = yabspix(0); SETCLIPRGN(xpixul,ypixul,xpixlr,ypixlr); } reset = 0; /* check if adjust of (xlocplast,ylocplast) is needed so that cursor will appear in GIN window */ if (xloclast < locwindow[0]) { xloclast = locwindow[0]; reset = 1; } if (xloclast > locwindow[2]) { xloclast = locwindow[2]; reset = 1; } if (yloclast < locwindow[1]) { yloclast = locwindow[1]; reset = 1; } if (yloclast > locwindow[3]) { yloclast = locwindow[3]; reset = 1; } if (reset) /* set cursor */ { /* next also recomputes xlocplast, ylocplast */ gloc(xloclast, yloclast); } else { gloc_pix(xlocplast, ylocplast); } segvisib: stvissegment(loccursor, 1); /* show cursor at (xlocplast, ylocplast) */ /* call await_wk_event() to handle PC and X-Workstation differences */ ret = await_wk_event(mask, &event, str, &xpxl, &ypxl); /* *** DIAGNOSTIC *** fprintf(stdout, "\nawait_wk_event: ev=0x0%x str[0]=%c xpx=%d ypx=%d xlocp=%d ylocp=%d", event, str[0], xpxl, ypxl, xlocplast, ylocplast); fflush(stdout); */ stvissegment(loccursor, 0); /* hide cursor */ *statptr = event; if (ret < 0) { code = -1; goto cleanup; /* failure in await_wk_event() */ } /* Arrow Keys on PC now move cursor in ONE PIXEL increments */ if (event & 0x0200) { /* *** DIAGNOSTIC *** fprintf(stderr, "\nscan code=0x0%x ", (unsigned)str[0]); */ xlocplast = xpxl; ylocplast = ypxl; switch((unsigned)str[0]) { case 0x048: --ylocplast; /* up-arrow */ break; case 0x04d: ++xlocplast; /* right-arrow */ break; case 0x050: ++ylocplast; /* down-arrow */ break; case 0x04b: --xlocplast; /* left-arrow */ break; default: /* jump-over, not an Arrow Key */ goto notarrow; } /* end of switch */ if (xlocplast < locpwindow[0]) xlocplast = locpwindow[0]; if (xlocplast > locpwindow[2]) xlocplast = locpwindow[2]; if (ylocplast < locpwindow[3]) ylocplast = locpwindow[3]; if (ylocplast > locpwindow[1]) ylocplast = locpwindow[1]; gloc_pix(xlocplast, ylocplast); goto segvisib; } /* end of if (event & 0x0200) */ notarrow: if (event & 0x0100) /* mouse motion */ { xlocplast = xpxl; /* update coordinates */ ylocplast = ypxl; goto segvisib; /* try again */ } if (event & 0x0007) /* button press/release */ { *keyptr = str[0]; while(!(event & 0x0070))/* wait for button release */ ret = await_wk_event(mask, &event, str, &xpxl, &ypxl); } else if (event & 0x0008) /* keyboard press */ { *keyptr = str[0]; /* SUPPRESS_KEYRELEASE */ } else if (event & 0x00f0) /* throw away spurious release */ { goto segvisib; } xlocplast = xpxl; /* compute new vdl coordinates */ ylocplast = ypxl; xloclast = xabsinvpix(xlocplast); yloclast = yabsinvpix(ylocplast); /* *** DIAGNOSTIC *** fprintf(stdout, "\nreqlocator(%c): xlocp=%d ylocp=%d xloclast=%d yloclast=%d", str[0], xlocplast, ylocplast, xloclast, yloclast); fflush(stdout); */ if (locgrid) /* handle GIN snap grid */ { *xptr = (xloclast + xmodgrid/2) - ((xloclast + xmodgrid/2) % xmodgrid); *yptr = (yloclast + ymodgrid/2) - ((yloclast + ymodgrid/2) % ymodgrid); } else /* return pure vdl coords */ { *xptr = xloclast; *yptr = yloclast; } *statptr = 0; cleanup: #if defined(DESQ) /* X-Workstation */ /* Back to Arrow */ XDefineCursor(gksdisplay, gkswindow, arrcurs); #endif if (fullviewind == 0) /* restore cliprgn */ SETCLIPRGN(pixviewext[0], pixviewext[1], pixviewext[2], pixviewext[3]); return(code); } /* end of reqlocator */ /* ---------------------------------------------------------------------- */ int initpick(int pdev, int igwin, int cseg, int xll, int yll, int xur, int yur, int papert) /* this function initializes pick input as follows: pdev sets the ACTIVE pick device (you can use -1 for "generic") if igwin = -1 then pick window is fullscreen else if igwin = 0 then (xll,yll,xur,yur) else (other values for future expansion) cseg sets the pick cursor and CURRENTLY MUST BE 1 (small +) or 0 (tektronix crosshairs). papert sets the pick aperture in vdl units. Note that if the Workstation does not support dynamic segments (e.g. the PC) then PICK functions like LOCATOR and SEGMENT = 0, PICK_ID = 0 always. */ { pikactive = pdev; if (igwin < 0) { pikwindow[0] = 0; pikwindow[1] = 0; pikwindow[2] = (int)xvdlaxis; pikwindow[3] = (int)yvdlaxis; } else if ((igwin == 0) && (xll < xur) && (yll < yur)) { pikwindow[0] = xll; pikwindow[1] = yll; pikwindow[2] = xur; pikwindow[3] = yur; } if (cseg == 0) pikcursor = 0; if (cseg == 1) pikcursor = 1; pikaperture = papert; return(0); } /* end of initpick */ /* ---------------------------------------------------------------------- */ int reqpick(int pdev, int *statptr, char *keyptr, int *xptr, int *yptr, int *segptr, int *pidptr) /* This function REQUESTS_INPUT on the GKS PICK routine and it returns -1 if device is non-existent. NOTE: char *keyptr . LIMITATIONS: Since the PC DOES NOT SUPPORT dynamic segments this call functions like reqlocator() except that *segptr = 0 , *pidptr = 0 ALWAYS. */ { int i; int tmp_xloclast,tmp_yloclast,tmp_xlocplast,tmp_ylocplast; int tmp_window[4],tmp_kloclast,tmp_loccursor; int tmp_locgrid,tmp_locband; if (pdev < 0 || pdev == 2 || pdev == 3) { if (mouseexist == 0) { *statptr = -1; return(-1); } /* save locator status */ tmp_xloclast = xloclast; tmp_yloclast = yloclast; tmp_xlocplast = xlocplast; tmp_ylocplast = ylocplast; tmp_kloclast = kloclast; for (i = 0 ; i < 4 ; i++) tmp_window[i] = locwindow[i]; tmp_loccursor = loccursor; tmp_locgrid = locgrid; tmp_locband = locband; /* temporarily set pick variables in place of loc variables */ xloclast = xpiklast; yloclast = ypiklast; xlocplast = xpikplast; ylocplast = ypikplast; loccursor = pikcursor; locgrid = 0; /* no grid */ locband = 0; /* no band */ /* call reqlocator() */ reqlocator(pdev,statptr,keyptr,xptr,yptr); *segptr = 0; *pidptr = 0; /* no segments found */ /* update pick status */ xpiklast = *xptr; ypiklast = *yptr; xpikplast = xlocplast; ypikplast = ylocplast; /* restore locator status */ xloclast = tmp_xloclast; yloclast = tmp_yloclast; xlocplast = tmp_xlocplast; ylocplast = tmp_ylocplast; kloclast = tmp_kloclast; for (i = 0 ; i < 4 ; i++) locwindow[i] = tmp_window[i]; loccursor = tmp_loccursor; locgrid = tmp_locgrid; locband = tmp_locband; return(0); } /* end of if (pdev < 0 ... */ return(-1); } /* end of reqpick */ /* ---------------------------------------------------------------------- */ int initvaluator(int vdev, int igwflag, int cseg, int xll, int yll, int xur, int yur, double vmin, double vstart, double vmax) /* This function initializes valuator input as follows: vdev sets the ACTIVE valuator (you can ALWAYS use -1 for "generic") if igwin = 0 valuator window is HORIZONTAL (default) else if igwin = 1 valuator window is VERTICAL else (other values are for future expansion) cseg must be a valid descriptor for the valuator cursor such as 4 vertical bar in BrightWhite (default) 5 horizontal bar in BrightWhite vmin/vstart/vmax set the minimum/starting/maximum (real) value */ { valactive = vdev; if (igwflag == 0) /* horizontal */ valwinflag = 0; else if (igwflag == 1) valwinflag = 1; /* vertical */ /* check for at least 1 pixel difference */ if ( (xabspix(xur) - xabspix(xll) > 0) && (yabspix(yll) - yabspix(yur) > 0) ) { valpwindow[0] = xabspix(xll); valpwindow[1] = yabspix(yll); valpwindow[2] = xabspix(xur); valpwindow[3] = yabspix(yur); valpxrange = valpwindow[2] - valpwindow[0]; valpyrange = valpwindow[1] - valpwindow[3]; /* *** DIAGNOSTIC *** fprintf(stderr, "\ninitvaluator: valpwindow=[%d,%d,%d,%d] valpxrange=%d valpyrange=%d", valpwindow[0], valpwindow[1], valpwindow[2], valpwindow[3], valpxrange, valpyrange); fflush(stderr); */ valwindow[0] = xll; valwindow[1] = yll; valwindow[2] = xur; valwindow[3] = yur; } if ( (cseg >= 4) && (cseg <= 5) ) valcursor = cseg; if ( (vmin < vmax) && (vmin <= vstart) && (vstart <= vmax) ) { valmin = vmin; valstart = vstart; valmax = vmax; } return(0); } /* end of initvaluator */ /* ---------------------------------------------------------------------- */ int reqvaluator(int vdev, int *statptr, double *rval, int *xptr, int *yptr) /* This function REQUESTS_INPUT on the GKS VALUATOR. One can use vdev = -1 for GENERIC. This function returns -1 if the device is non-existent, otherwise it returns 0. Note type: double *rval. LIMITATIONS: When valuator device is MOUSE based (usual case) then the current locator position (xloclast, yloclast) will change. If this causes problems, one will have to call gloc() to reset these values before using the locator. */ { char str[16]; int code; int xpxl, ypxl, event, ret, xpixul, xpixlr, ypixul, ypixlr, xpxl_cen, ypxl_cen; unsigned mask; double percent; #if defined(DESQ) /* X-Workstation */ if ( (valcursor == 4) || (valcursor == 5) ) { /* Check Descriptor and Associated Cursor */ if ( (valcursor >= 0) && (valcursor < max_descript) && (descript[valcursor].active >= 1) && (descript[valcursor].assoccurs == 1) ) /* Temporarily back to (parent's) cursor) */ XDefineCursor(gksdisplay, gkswindow, None); } #endif if ( (vdev >= 0) && (vdev != 2) && (vdev != 3) ) return(-1); /* bad device number */ code = 0; /* expect no more errors */ mask = MOUSE_MOTION; /* due to the problem of keeping the cursor "centered," on an X-Workstation we must update position on a(n almost) continuous basis (see VAL_APERTURE below) */ /* always update position on button */ mask = mask | MOUSE_UPDATE | SUPPRESS_KEYRELEASE; if (fullviewind == 0) /* check if cliprgn enabled since this will interfere with GIN window and we would have the ADDITIONAL COMPLICATION OF RELATIVE COORDINATES with the Borland viewport. */ { xpixul = xabspix(0); ypixul = yabspix((int)yvdlaxis); xpixlr = xabspix((int)xvdlaxis); ypixlr = yabspix(0); SETCLIPRGN(xpixul,ypixul,xpixlr,ypixlr); } /* adjust (xlocplast,ylocplast) so that cursor will appear in GIN window CENTERED at midline */ percent = (double)(valstart - valmin)/(valmax - valmin); if (valwinflag == 0) /* horizontal */ { yloclast = (valwindow[1] + valwindow[3])/2; xloclast = (int)( (double)valwindow[0] + percent*(double)(valwindow[2] - valwindow[0]) ); } if (valwinflag == 1) /* vertical */ { xloclast = (valwindow[0] + valwindow[2])/2; yloclast = (int)( (double)valwindow[1] + percent*(double)(valwindow[3] - valwindow[1]) ); } xlocplast = xabspix(xloclast); ylocplast = yabspix(yloclast); gloc_pix(xlocplast, ylocplast); /* Warp mouse to starting position */ /* Convert part of drawable to a (Client-side) XImage so that the call stviscursor() can do a save and restore */ #if defined(DESQ) stcursavearea(valpwindow); #endif segvisib: /* show cursor at (xlocplast, ylocplast) */ stviscursor(valcursor, xlocplast, ylocplast, 1); /* call await_wk_event() to handle PC and X-Workstation differences */ ret = await_wk_event(mask, &event, str, &xpxl, &ypxl); /* hide cursor */ stviscursor(valcursor, xlocplast, ylocplast, 0); *statptr = event; if (ret < 0) { code = -1; goto cleanup; /* failure in await_wk_event() */ } if (event & 0x0100) /* mouse motion */ { if (valwinflag == 0) /* horizontal */ { ypxl_cen = (valpwindow[1] + valpwindow[3])/2; if (xpxl < valpwindow[0]) xpxl = valpwindow[0]; else if (xpxl > valpwindow[2]) xpxl = valpwindow[2]; ypxl = ypxl_cen; } else if (valwinflag == 1) { xpxl_cen = (valpwindow[0] + valpwindow[2])/2; if (ypxl < valpwindow[3]) ypxl = valpwindow[3]; else if (ypxl > valpwindow[1]) ypxl = valpwindow[1]; xpxl = xpxl_cen; } xlocplast = xpxl; /* update coordinates */ ylocplast = ypxl; goto segvisib; /* try again */ } if (event & 0x0007) /* button press/release */ { while(!(event & 0x0070))/* wait for button release */ ret = await_wk_event(mask, &event, str, &xpxl, &ypxl); } else if (event & 0x0008) /* keyboard press */ { ; } else if (event & 0x00f0) /* throw away spurious release */ { goto segvisib; } xlocplast = xpxl; /* compute new vdl coordinates */ ylocplast = ypxl; xloclast = xabsinvpix(xlocplast); yloclast = yabsinvpix(ylocplast); /* compute new real value */ if ( (valwinflag == 0) && /* horizontal */ (valpxrange != 0) ) { percent = (double)(xlocplast - valpwindow[0])/ (double)(valpxrange); *statptr = 0; } else if ( (valwinflag == 1) && /* vertical */ (valpyrange != 0) ) { /* note valpwindow[1] = minimum */ percent = (double)(valpwindow[1] - ylocplast)/ (double)(valpyrange); *statptr = 0; } else /* error */ { *statptr = -1; } vallast = valmin + (percent * (valmax - valmin)); if (vallast > valmax) vallast = valmax; if (vallast < valmin) vallast = valmin; valstart = vallast; /* update */ *xptr = xloclast; /* return vdl coords */ *yptr = yloclast; *rval = vallast; /* return real value */ cleanup: #if defined(DESQ) /* X-Workstation */ /* Back to (parent's) Arrow */ XDefineCursor(gksdisplay, gkswindow, arrcurs); #endif if (fullviewind == 0) /* restore cliprgn */ SETCLIPRGN(pixviewext[0], pixviewext[1], pixviewext[2], pixviewext[3]); return(code); } /* end of reqvaluator */ /* ---------------------------------------------------------------------- */ int initchoice(int cdev, int cseg) /* This function initializes the choice device as follows: cdev sets the active choice (-1 for "generic") cseg sets the type of cursor and CURRENTLY MUST BE 0 for function key buttons F1 .. F8 Because the screen MUST be saved under the choice cursor the choice of cursor automatically determines the GIN window. */ { choactive = cdev; if (cseg == 0) chocursor = 0; return(0); } /* end of initchoice */ /* ----------------------------------------------------------------------- */ int reqchoice(int cdev, int *pfunc_key) /* This function REQUESTS_INPUT on the GKS CHOICE routine and brings up a menu with a number of function key buttons. When the operator pushes one of the function keys from F1 to F8 the number (1 ... 8) is returned in *pfunc_key. If the key pushed was invalid, *pfunc_key is set to 0. LIMITATIONS: Some X-Workstations have a SPECIAL use for the F1 key and choosing it will return 0, not 1 */ { int j, xp, yp, xvdl, yvdl, event, ret; unsigned mask; char keys[16], *cptr; #if defined(DESQ) int i; #elif defined(TURBEAUX) /* Borland C++ */ int poly[8]; #endif if (cdev != choactive); /* do nothing for now */ /* save the choice window */ #if defined(DESQ) /* X-Workstation */ /* smaller delay now but still put up the "watch" for insurance */ XDefineCursor(gksdisplay, gkswindow, waitcurs); if (choiceimagevalid == 1) /* de-allocate "stale" XImage */ { XDestroyImage(choiceimage); choiceimagevalid = 0; imagedesc[CHOICE_XINDEX].valid = 0; imagedesc[CHOICE_XINDEX].imageptr = (XImage *)NULL; } if (choiceimagevalid == 0) { /* *** DEBUG *** fprintf(stderr, "\nXGetImage(gksdisp,gkswin,x=%d,y=%d,width=%d,height=%d,planes=%ld", chopwindow[0], chopwindow[3], chopwindow[2] - chopwindow[0] + 1, chopwindow[1] - chopwindow[3] + 1, AllPlanes); */ choiceimage = XGetImage(gksdisplay, gkswindow, chopwindow[0], chopwindow[3], chopwindow[2] - chopwindow[0] + 1, chopwindow[1] - chopwindow[3] + 1, AllPlanes, XYPixmap); choiceimagevalid = 1; imagedesc[CHOICE_XINDEX].valid = 1; imagedesc[CHOICE_XINDEX].bppixel = bitsppixel; imagedesc[CHOICE_XINDEX].imageptr = (XImage *)choiceimage; for (i = 0 ; i < 4 ; i++) imagedesc[CHOICE_XINDEX].pwindow[i] = chopwindow[i]; imagedesc[CHOICE_XINDEX].pwidth = chopwindow[2] - chopwindow[0] + 1; imagedesc[CHOICE_XINDEX].pheight = chopwindow[1] - chopwindow[3] + 1; imagedesc[CHOICE_XINDEX].bytes_alloc = (long)(imagedesc[CHOICE_XINDEX].pwidth) * (long)(imagedesc[CHOICE_XINDEX].pheight); } /* Back to Arrow */ XDefineCursor(gksdisplay, gkswindow, arrcurs); #else /* Borland C++, Microsoft C */ GETIMAGE(0,(short)vcylong - 20, (short)vcxlong,(short)vcylong - 5, image_buf); /* 16 lines */ #endif /* draw function key buttons */ set_solid_fill(COLINDEX(7)); /* bright white */ #if defined(TURBEAUX) /* Borland GRAPHICS.LIB */ poly[0] = 0; poly[1] = (short)vcylong - 20; poly[2] = (short)vcxlong; poly[3] = (short)vcylong - 20; poly[4] = (short)vcxlong; poly[5] = (short)vcylong - 5; poly[6] = 0; poly[7] = (short)vcylong - 5; fillpoly(4, poly); /* Handles interior */ #endif FILLRECTANGLE(0, (short)vcylong - 20, (short)vcxlong, (short)vcylong - 5); SETCOLOR(0); for (j = 0 ; j < 8 ; j++) { cptr = chotags[j]; xp = ((int)vcxlong * (2*j+1))/17; yp = (int)vcylong - 8; while(*cptr != '\0') { /* X-Workstation can use put_mask() now */ put_mask(&amr10[(*cptr) - 32][0],1,xp,yp,1); xp = xp + (XMASK + 1); /* next cell */ cptr++; } /* end of while( ) */ } /* end of for (j = .. */ mask = SUPPRESS_KEYRELEASE; waitkey: ret = await_wk_event(mask, &event, keys, &xvdl, &yvdl); if (ret) { *pfunc_key = 0; /* failure in await_wk_event() */ goto cleanup; } if (!(event & 0x008)) goto waitkey; if (event & 0x0200) /* NON-ascii key */ { if ((keys[0] >= 59) && (keys[0] <= 66)) *pfunc_key = (int)keys[0] - 58; } else { *pfunc_key = 0; } /* error in selection */ /* restore the screen */ cleanup: #if defined(DESQ) /* X-Workstation */ /* *** DEBUG *** fprintf(stderr, "\nXPutImage(gksdisp,...,0,0,x=%d,y=%d,width=%d,height=%d", chopwindow[0], chopwindow[3], chopwindow[2] - chopwindow[0] + 1, chopwindow[1] - chopwindow[3] + 1); */ /* restore screen area */ XPutImage(gksdisplay, gkswindow, gksGC, choiceimage, 0, 0, /* source */ chopwindow[0], chopwindow[3], /* dest */ chopwindow[2] - chopwindow[0] + 1, /* width */ chopwindow[1] - chopwindow[3] + 1); /* height */ #else /* Borland C++, Microsoft C */ PUTIMAGE(0,(short)vcylong - 20, (short)vcxlong,(short)vcylong - 5,image_buf,_GPSET); #endif SETCOLOR(COLINDEX(lncolor)); /* restore color */ return(0); } /* end of reqchoice */ /* ----------------------------------------------------------------------- */ int begindialog(void) /* This is a COMPLETELY hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- UnMaps GKS X-Window(gkswindow) Calls rest_adapter() On a PC (Borland C++, Microsoft C) this function temporarily suspends graphics and puts the display back into text mode. On an X-Workstation you always have the original dialog window (Xterm) from which the program was invoked so that rest_adapter() is NOT called, it is only necessary to UnMap the GKS X-Window. */ { #if defined(DESQ) /* X-Workstation */ /* XLowerWindow(gksdisplay, gkswindow); doesn't work here since it ONLY lowers the window with respect to its siblings, and both the DOS invocation window and the gkswindow are grandchildren of the RootWindow by different parents. */ XUnmapWindow(gksdisplay, gkswindow); XSync(gksdisplay, False); XFlush(gksdisplay); #else /* Borland C++, Microsoft C */ rest_adapter(); #endif return(0); } /* end of begindialog */ /* ----------------------------------------------------------------------- */ int enddialog(void) /* This is a COMPLETELY hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- Calls init_adapter() Calls set_all_palette() (Re)computes cellheight, cellspace, cellwidth (Re)computes vectheight, vectspace, vectwidth (Re)Initializes linecolor, linetype, & mouse Maps the GKS X-Window and waits for the Expose Event On a PC (Borland C++, Microsoft C) this function deactivates any dialog plane and resumes graphics. Note that palette will be re-initialized. On an X-Workstation the graphics window is UnMapped, but still present, going into this call (see begindialog() above). In ANY case, the previous graphics will need to be REDRAWN. */ { #if defined(DESQ) /* X-Workstation */ XSelectInput (gksdisplay, gkswindow, ButtonPressMask | KeyPressMask | ExposureMask ); XMapRaised(gksdisplay, gkswindow); /* Await ExposeEvent after Mapping */ do { XNextEvent(gksdisplay,(XEvent *)&gksevent); } while (gksevent.type != Expose); #else /* Borland C++, Microsoft C */ int m1,m2,m3,m4; init_adapter(); /* note that init_adapter() computes vcxlong and vcylong */ /* note that we can CHANGE video modes between begindialog()...enddialog() so we have to (re)set character/vector metrics */ cellwidth = (int)(((long)XMASK * xvdlaxis)/vcxlong); cellheight = (int)((((long)YMASK + 1L) * yvdlaxis)/vcylong); cellspace = (int)(xvdlaxis/vcxlong); vectwidth = (int)(((long)X_BOX * xvdlaxis)/vcxlong); vectheight = (int)(( ((long)Y_BOX + 1L) * yvdlaxis)/vcylong); vectspace = (int)(xvdlaxis/vcxlong); /* reinitialize palette (colorsarray[] is current) */ set_all_palette(colorsarray); /* reinitialize linecolor */ SETCOLOR(COLINDEX(lncolor)); /* reinitialize line_type */ CHKANDSETLINESTYLE(lntype); m1 = 0; /* re-initialize mouse */ MOUSECML(&m1,&m2,&m3,&m4); if (m1 == 0) mouseexist = 0; else mouseexist = 1; if (m1 != 0) mousetype = m2; else mousetype = 0; #endif return(0); } /* end of enddialog */ /* ----------------------------------------------------------------------- */ int mflush(void) /* This is NOT really needed at present but with other workstations (added in future) it may be necessary. */ { #if defined(DESQ) /* X-Workstation */ XSync(gksdisplay, False); XFlush(gksdisplay); #endif fflush(stdout); return(0); } /* end of mflush */ /* ---------------------------------------------------------------------- */ int flushdeviceevents(void) /* This function clears all events from the event queue. It is most often used BEFORE an AWAIT_INPUT_EVENT type call, such as getlocator(). */ { #if defined(DESQ) XSync(gksdisplay, True); #else /* Borland C++, Microsoft C */ unsigned code; int m1, m2, m3, m4; m1 = 0; MOUSECML(&m1, &m2, &m3, &m4); /* RESET mouse */ m1 = 4; m3 = xlocplast; m4 = ylocplast; MOUSECML(&m1,&m2,&m3,&m4); /* (re)SET cursor position */ code = bios_key(_KEYBRD_READY); while (code != 0) /* CLEAR keyboard buffer */ { code = bios_key(_KEYBRD_READ); code = bios_key(_KEYBRD_READY); } #endif return(0); } /* ---------------------------------------------------------------------- */ int getlocator(int idev, int *statptr, char *keyptr, int *xptr, int *yptr) /* This function AWAITS_INPUT_EVENT on the GKS LOCATOR. In contrast to reqlocator(), which makes a REQUEST and blocks until a key or mouse button is pressed, this function will get several types of distinct events. On an X-Workstation, the events reported will be IN ORDER; on a PC the events will be reported in the following PRIORITY and keyboard key press/release will NOT be distinguished: (status & 0x0001) != 0 left mouse button is down (status & 0x0002) != 0 right mouse button is down (status & 0x0004) != 0 middle (if any) mouse button is down (status & 0x0008) != 0 keyboard key (in *keyptr) is down (status & 0x0010) != 0 left mouse button has been released (status & 0x0020) != 0 right mouse button has been released (status & 0x0040) != 0 middle (if any) mouse button has been released (status & 0x0080) != 0 keyboard key (in *keyptr) has been released (status & 0x0100) != 0 mouse position (in (*xptr,*yptr)) has changed In addition, if a keyboard key event has occurred, the ASCII character will be returned in *keyptr UNLESS ((status & 0x0200) != 0), in which case a NON-ASCII key has been pressed (for example, a function key). In this case, the SCAN_CODE will be returned in *keyptr instead. One can set idev = -1 for GENERIC. This function returns -1 if the device is non-existent, otherwise it returns 0. Note: char *keyptr */ { char str[16]; int xpixul,ypixul,xpixlr,ypixlr,xpxl,ypxl,event,ret; unsigned mask; if ( (idev >= 0) && (idev != 2) && (idev != 3) ) return(-1); /* bad device number */ mask = MOUSE_MOTION | MOUSE_UPDATE; /* update position on a continuous basis and always update after press/release */ if (fullviewind == 0) /* check if cliprgn enabled since this will interfere with GIN window and we would have the ADDITIONAL COMPLICATION OF RELATIVE COORDINATES with the Borland viewport. */ { xpixul = xabspix(0); ypixul = yabspix((int)yvdlaxis); xpixlr = xabspix((int)xvdlaxis); ypixlr = yabspix(0); SETCLIPRGN(xpixul,ypixul,xpixlr,ypixlr); } /* call await_wk_event() to handle PC and X-Workstation differences */ ret = await_wk_event(mask, &event, str, &xpxl, &ypxl); *statptr = event; if (ret < 0) return(-1); /* failure in await_wk_event() */ if (event & 0x0077) /* button press/release */ { *keyptr = str[0]; } if (event & 0x0088) /* keyboard press/release */ { *keyptr = str[0]; } if (event & 0x0100) /* mouse motion */ { *xptr = xabsinvpix(xpxl); *yptr = yabsinvpix(ypxl); } if (fullviewind == 0) /* restore cliprgn */ SETCLIPRGN(pixviewext[0], pixviewext[1], pixviewext[2], pixviewext[3]); return(0); } /* end of getlocator */ /* ---------------------------------------------------------------------- */ int gendframe(void) /* This function ends the graphics frame and returns the next page no. If the workstation does not support multiple pages, 0 is always returned.*/ { curpage = 0; return(curpage); } /* gendframe */ /* ----------------------------------------------------------------------- */ int closevdi(void) /* This is a hardware dependent function which does the following: PC Platform X-Workstation -------------------------------------------------------------- Calls rest_adapter() Calls rest_adapter() This function ends the current graphics session and returns the PC video to text mode CO80, or, in the case of an X-Workstation, to the original dialog window (Xterm). */ { rest_adapter(); /* restore text mode */ return(0); } /* end of closevdi */