aboutsummaryrefslogtreecommitdiff
path: root/plotlib/win32/W32win.c
diff options
context:
space:
mode:
Diffstat (limited to 'plotlib/win32/W32win.c')
-rw-r--r--plotlib/win32/W32win.c1709
1 files changed, 1709 insertions, 0 deletions
diff --git a/plotlib/win32/W32win.c b/plotlib/win32/W32win.c
new file mode 100644
index 0000000..c3982d6
--- /dev/null
+++ b/plotlib/win32/W32win.c
@@ -0,0 +1,1709 @@
+/***********************************************************************
+ W32win.c - FORTRAN/C interface for Windows NT/95 Xplot11
+
+ Copyright (C) 1999 Harold Youngren, Mark Drela
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Report problems to: guppy@maine.rr.com
+ or drela@henry.mit.edu
+***********************************************************************/
+
+/***********************************************************************
+* Xplot11 C-level Win32 interface
+C Version 4.43 3/5/99
+*
+* Status: This code is still pretty rough, it works but there are some
+* rough edges (some of which result from problems with the Win32
+* API). This is the interface code to create, draw to, refresh,
+* destroy a graphics window on a Win32 machine running a Fortran
+* application (like XFOIL) making Pltlib calls.
+*
+* The refresh problem for Win32 (as the Xwindows option for a
+* automatic refresh using the server's backing store startup
+* option is not available under Win32) is dealt with by creating
+* a plot thread that monitors the Windoze events and does window
+* refresh. This is done by doing plotting to a memory bitmap and
+* writing the bitmap to the screen whenever the window needs
+* refresh.
+*
+* Note that several problems arise in supporting the Xwindows
+* plotting functionality under Win32. Colors are handled differently
+* than under Xwindows, for color name compatibility I have included
+* a color table lookup routine that maps Xwindows color names into
+* RGB values. A more serious problem is the inconsistency of the
+* Win32 API itself, specifically the functionality varies with the
+* version of the Microsoft OS you are running. The most serious
+* problem showed up in drawing lines with arbitrary patterns and
+* widths. The Win32 API apparently does not support drawing these
+* types of lines (used in Pltlib for background grids, among other
+* things) satisfactorily. There appears to be no way to draw a line
+* with an arbitrary pattern and width. Also it appears that drawing
+* patterned lines with transparent background color is not supported.
+*
+* Harold Youngren 10/01
+***********************************************************************/
+
+
+/***********************************************************************
+* Defines graphics primitives for window management and line drawing
+* Primitives include:
+* gwxrevflag - checks environment variables for background color
+* gwxopen - initializes X display and returns size and depth of display
+* gwxwinopen - opens X plotting window with specified x,y size and position
+* gwxclear - clears plotting window
+* gwxstatus - gets current window size and location
+* gwxresize - resizes current window to specified size
+
+* gwxreset - resets plotting defaults for window
+* gwxclose - closes plotting to X display
+* gwxflush - flushes out graphics primitives in buffers
+* gwxline - plots line segment
+
+* gwxdash - sets line pattern from integer mask
+* gwxcurs - gets graphics cursor position and key pressed
+* gwxpen - sets line width in pixels
+*
+* More advanced routines beyond the original PLOT-10 requirements
+* gwxdestroy - closes plot window
+* gwxlinez - plots polyline
+* gwxpoly - plots filled polygon
+* gwxstring - plots string
+*
+* Color routines
+* gwxsetcolor - sets foreground color from color map
+* gwxsetbgcolor - sets background color from color map
+* gwxcolorname2rgb - find color components of color specified by name string
+* gwxallocrgbcolor - allocate a color specified by r,g,b components
+* gwxfreecolor - frees an allocated color from colormap
+*
+* Utility routines
+* mskbits - converts integer mask into dot/dash array
+*
+* Double-buffer routines
+* gwxdisplaybuffer - switches background buffer with foreground window
+* gwxdrawtobuffer - sets drawing to background buffer
+* gwxdrawtowindow - sets drawing to foreground window
+************************************************************************/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <windows.h>
+#include <process.h>
+
+#include "rgbtbl.h"
+#include "Xdefs.h"
+
+typedef struct {
+ HWND window;
+ HPEN pen;
+ HBRUSH fgbrush;
+ HBRUSH bgbrush;
+ int fg;
+ int bg;
+ int font;
+ int fun;
+} GC;
+
+typedef struct {
+ int ic;
+ int rgb;
+ HPEN pen;
+ HBRUSH brush;
+} COLTBL;
+
+typedef struct Event {
+ HWND window;
+ int type;
+ int x;
+ int y;
+ int state;
+ struct Event *next;
+} Event;
+
+
+/* Calling convention, Intel Fortran is simple, call is same as Unix
+ CVF requires Microsoft call */
+#ifdef _CVF
+#define W32CALL __stdcall
+#else
+#define W32CALL
+#endif
+
+
+/* Maximum number of polyline points per polyline call,
+ increase if necessary */
+#define MAXPTS 1000
+
+/* Maximum number of colors */
+#define MAXCOLS 256
+
+static char *gwxClass = "PltLib";
+static char *gwxName = "PltLib";
+
+/*
+BYTE ANDMask[128], ORNMask[128], ORWMask[128];
+static BYTE ANDMsk16[] = { 0xfe, 0x00,
+ 0xfe, 0x00,
+ 0xfe, 0x00,
+ 0xff, 0x80,
+ 0xff, 0x80,
+ 0xff, 0x00,
+ 0xfe, 0x00,
+ 0xfc, 0x18,
+ 0xf8, 0x38,
+ 0xf0, 0x7f,
+ 0xe0, 0xff,
+ 0xc1, 0xff,
+ 0x83, 0xff,
+ 0x07, 0xff,
+ 0x0f, 0xff,
+ 0x1f, 0xff };
+ static BYTE ORNMsk16[] = { 0x00, 0x00,
+ 0x00, 0xfe,
+ 0x00, 0x7e,
+ 0x00, 0x3e,
+ 0x00, 0x3e,
+ 0x00, 0x7e,
+ 0x00, 0xe6,
+ 0x01, 0xc2,
+ 0x03, 0x80,
+ 0x07, 0x00,
+ 0x0e, 0x00,
+ 0x1c, 0x00,
+ 0x38, 0x00,
+ 0x70, 0x00,
+ 0x60, 0x00,
+ 0x00, 0x00 };
+ static BYTE ORWMsk16[] = { 0x01, 0xff,
+ 0x01, 0x01,
+ 0x01, 0x01,
+ 0x00, 0x41,
+ 0x00, 0x41,
+ 0x00, 0x81,
+ 0x01, 0x19,
+ 0x02, 0x25,
+ 0x04, 0x47,
+ 0x08, 0x80,
+ 0x11, 0x00,
+ 0x22, 0x00,
+ 0x44, 0x00,
+ 0x88, 0x00,
+ 0x90, 0x00,
+ 0xe0, 0x00 };
+*/
+
+/* Window and graphics global data */
+HWND gwxWin;
+HDC gwxHDC, gwxmemHDC;
+HBITMAP gwxBMAP;
+HCURSOR gwxNormalC, gwxWaitC, gwxCurrentC;
+
+GC *gwxGC;
+
+COLTBL RGBmap[MAXCOLS];
+int nRGBmap;
+
+/* int xcsize,ycsize; */
+int wxstart,wystart,wxsize,wysize;
+int xrootsize, yrootsize, rootdepth;
+int gwxSize[5];
+int gwxXmatte, gwxYmatte, gwxYbar;
+int reversevideo;
+int initthread;
+int penwidth, penpattern, ndash, pendash[16];
+
+HINSTANCE gwxInstance;
+ATOM gwxRegister;
+WNDCLASSEX gwxWndClass;
+MSG Message;
+
+Event *gwxEvents, *gwxLEvent, gwxLast;
+
+/*static PARAMS params;*/
+
+void MSKBITS(int*,int*,int*);
+int gwxlookupcolor (char*,int*);
+
+
+
+/**********************************************************************/
+/************************Internal Event Code***************************/
+
+/*These routines simulate the Xwindows XEvents to do user interaction.
+ This is done here by collecting a list of relevant events from Windoze
+ and managing these for the user who deals only with the simulated XEvents.
+ This is probably a grungy hack (it was copied from Bob Haimes Visual3 and
+ pV3 ports to Win32) but it works. It may be better to get rid of the
+ extra event layer and deal directly with Win32 events.
+ HHY */
+
+void
+gwxAddEvent(int type, int x, int y, int state)
+{
+ Event *event;
+
+ event = (Event *) malloc(sizeof(Event));
+ if (event == NULL) return;
+
+ event->window = gwxWin;
+ event->type = type;
+ event->x = x;
+ event->y = y;
+ event->state = state;
+ event->next = NULL;
+
+ if (gwxLEvent != NULL) gwxLEvent->next = event;
+ gwxLEvent = event;
+ if (gwxEvents == NULL) gwxEvents = event;
+ gwxLast = *event;
+}
+
+void
+gwxRemEvent(int *type, int *x, int *y, int *state)
+{
+ Event *event;
+
+ if (gwxEvents == NULL) {
+ printf("Warning: No Events to remove!\n");
+ return;
+ }
+
+ event = gwxEvents;
+ if (event == gwxLEvent) gwxLEvent = NULL;
+ gwxEvents = event->next;
+
+ *type = event->type;
+ *x = event->x;
+ *y = event->y;
+ *state = event->state;
+ free(event);
+}
+
+/**********************************************************************/
+/**********************************************************************/
+
+
+
+LRESULT CALLBACK
+gwxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ int i, ix, iy;
+ PAINTSTRUCT paint;
+ HDC hdc;
+ POINT point;
+ RECT rect;
+
+ switch (message) {
+
+ case WM_USER:
+ return 0;
+
+ case WM_SIZE:
+ if (hWnd == gwxWin) {
+ if (gwxSize[4]) {
+ ix = LOWORD(lParam);
+ iy = HIWORD(lParam);
+ if ((ix != gwxSize[0]) || (iy != gwxSize[1])) {
+ gwxSize[0] = ix;
+ gwxSize[1] = iy;
+ gwxAddEvent(XExpose, ix, iy, 1);
+ }
+ } else {
+ ix = gwxSize[0] + 2*gwxXmatte;
+ iy = gwxSize[1] + 2*gwxYmatte + gwxYbar;
+ SetWindowPos(hWnd, HWND_TOP, gwxSize[2], gwxSize[3],
+ ix, iy, SWP_NOMOVE|SWP_NOZORDER);
+ }
+ return 0;
+ }
+ return 0;
+
+ case WM_MOVE:
+ if (hWnd == gwxWin) {
+ gwxSize[2] = LOWORD(lParam);
+ gwxSize[3] = HIWORD(lParam);
+ return 0;
+ }
+ return 0;
+
+ case WM_PAINT:
+ /* printf("WM_PAINT\n"); */
+ /*
+ * Validate the region even if there are no DisplayFunc.
+ * Otherwise, USER will not stop sending WM_PAINT messages.
+ */
+ hdc = BeginPaint(hWnd, &paint);
+ BitBlt(hdc,0,0,xrootsize,yrootsize,gwxmemHDC,0,0,SRCCOPY);
+ EndPaint(hWnd, &paint);
+ if (hWnd == gwxWin) {
+ gwxAddEvent(XExpose, gwxSize[0], gwxSize[1], 1);
+ return 0;
+ }
+ return 0;
+
+ case WM_PALETTECHANGED:
+ printf("WM_PALETTECHANGED\n");
+ return 0;
+
+ case WM_ACTIVATE:
+ break;
+
+ case WM_MOUSEMOVE:
+/* printf("mousemove active %d focus %d\n",GetActiveWindow(),GetFocus()); */
+ if (GetActiveWindow() != hWnd) {
+ SetForegroundWindow(hWnd);
+ SetActiveWindow(hWnd);
+ }
+ if (GetFocus() != hWnd) SetFocus(hWnd);
+/* printf("mousemove %d %d\n",hWnd,gwxWin); */
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ if (GetAsyncKeyState(VK_RBUTTON) < 0) {
+ gwxAddEvent(XButtonPress, LOWORD(lParam), HIWORD(lParam), 2);
+ } else {
+ gwxAddEvent(XButtonPress, LOWORD(lParam), HIWORD(lParam), 1);
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ if (GetAsyncKeyState(VK_RBUTTON) < 0) {
+ gwxAddEvent(XButtonRelease, LOWORD(lParam), HIWORD(lParam), 2);
+ } else {
+ gwxAddEvent(XButtonRelease, LOWORD(lParam), HIWORD(lParam), 1);
+ }
+ return 0;
+
+ case WM_MBUTTONDOWN:
+ gwxAddEvent(XButtonPress, LOWORD(lParam), HIWORD(lParam), 2);
+ return 0;
+
+ case WM_MBUTTONUP:
+ gwxAddEvent(XButtonRelease, LOWORD(lParam), HIWORD(lParam), 2);
+ return 0;
+
+ case WM_RBUTTONDOWN:
+ if (GetAsyncKeyState(VK_LBUTTON) < 0) {
+ gwxAddEvent(XButtonPress, LOWORD(lParam), HIWORD(lParam), 2);
+ } else {
+ gwxAddEvent(XButtonPress, LOWORD(lParam), HIWORD(lParam), 3);
+ }
+ return 0;
+
+ case WM_RBUTTONUP:
+ if (GetAsyncKeyState(VK_LBUTTON) < 0) {
+ gwxAddEvent(XButtonRelease, LOWORD(lParam), HIWORD(lParam), 2);
+ } else {
+ gwxAddEvent(XButtonRelease, LOWORD(lParam), HIWORD(lParam), 3);
+ }
+ return 0;
+
+ case WM_KEYDOWN:
+ GetCursorPos(&point);
+ GetWindowRect(hWnd, &rect);
+ ix = point.x - rect.left - gwxXmatte;
+ iy = point.y - rect.top - gwxYmatte - gwxYbar;
+ /* gwxAddEvent(XKeyPress, ix, iy, wParam+256); */
+ return 0;
+
+ case WM_KEYUP:
+ GetCursorPos(&point);
+ GetWindowRect(hWnd, &rect);
+ ix = point.x - rect.left - gwxXmatte;
+ iy = point.y - rect.top - gwxYmatte - gwxYbar;
+ i = wParam+256;
+ /* if (i == 300) gwxAddEvent(XKeyPress, ix, iy, i);
+ gwxAddEvent(XKeyRelease, ix, iy, i); */
+ return 0;
+
+ case WM_CHAR:
+ if (wParam == 27) return 0;
+ if ((gwxLast.type != 2) || (gwxLast.state < 352) ||
+ (gwxLast.state > 361) || (gwxLast.state-wParam != 304)) {
+ GetCursorPos(&point);
+ GetWindowRect(hWnd, &rect);
+ ix = point.x - rect.left - gwxXmatte;
+ iy = point.y - rect.top - gwxYmatte - gwxYbar;
+ gwxAddEvent(XKeyPress, ix, iy, wParam);
+ } else {
+ printf("Double Hit: state = %d\n", wParam);
+ }
+ return 0;
+
+ case WM_SYSCOMMAND:
+ /* special code for F10 */
+ if ((lParam == 0) && (wParam == 61696)) {
+ GetCursorPos(&point);
+ GetWindowRect(hWnd, &rect);
+ ix = point.x - rect.left - gwxXmatte;
+ iy = point.y - rect.top - gwxYmatte - gwxYbar;
+ gwxAddEvent(XKeyPress, ix, iy, 377);
+ return 0;
+ }
+ break;
+
+ case WM_CLOSE:
+ gwxAddEvent(XKeyPress, 0, 0, 283);
+ exit;
+ return 0;
+
+ case WM_DESTROY:
+ PostQuitMessage (0) ;
+ return 0 ;
+ }
+ return DefWindowProc( hWnd, message, wParam, lParam);
+}
+
+
+int
+rgb2winrgb(int acol)
+{
+ int col, r, g, b;
+
+ col = acol & 0x00ffffff;
+ r = col >> 16;
+ g = (col >> 8) & 0xff;
+ b = col & 0xff;
+ col = b << 16 | g << 8 | r;
+ return col;
+}
+
+
+
+/* gwxrevflag
+ Get XPLOT11 background default from users environment
+ Parameters:
+ revflag (int*) reverse video flag (0 for white, 1 for black)
+*/
+void W32CALL
+GWXREVFLAG(revflag)
+ int *revflag;
+{
+ char *bufp, *tmp;
+/* check environment variable XPLOT11_BACKGROUND for background color
+ XPLOT11_BACKGROUND = white gives black on white plotting (like paper)
+ XPLOT11_BACKGROUND != white gives white on black plotting (reverse video)
+*/
+ *revflag = 1;
+ bufp = getenv("XPLOT11_BACKGROUND");
+
+/* check lowercased environment for "black" to reverse video */
+ if(bufp) {
+ for(tmp = bufp; *tmp; tmp++)
+ *tmp = tolower(*tmp);
+ *revflag = (strcmp(bufp,"white")!=0);
+ }
+}
+
+
+
+/* gwxopen
+ Open X window display and get size and depth of root window
+ Parameters:
+ xsize,ysize (int*) root window size
+ depth (int*) screen color depth (pixel depth)
+*/
+void W32CALL
+GWXOPEN(int *xsize, int *ysize, int *depth)
+{
+ int i, j, k;
+
+/* set depth arbitrarily to 8 bits to work like Xwindows colormaps */
+ rootdepth = 8;
+ xrootsize = GetSystemMetrics(SM_CXSCREEN);
+ yrootsize = GetSystemMetrics(SM_CYSCREEN);
+
+ *depth = rootdepth;
+ *xsize = xrootsize;
+ *ysize = yrootsize;
+
+ gwxXmatte = GetSystemMetrics(SM_CXFRAME);
+ gwxYmatte = GetSystemMetrics(SM_CYFRAME);
+ gwxYbar = GetSystemMetrics(SM_CYCAPTION) -
+ GetSystemMetrics(SM_CYBORDER);
+ /*
+ printf("Screen is %d x %d\n", *xsize, *ysize);
+ if (gwxXmatte == gwxYmatte) {
+ printf("Window matte is %d\n",gwxXmatte);
+ } else {
+ printf("Window matte is %d x %d\n", gwxXmatte, gwxYmatte);
+ }
+ printf("Title bar height = %d\n", gwxYbar);
+ */
+
+/* check environment variables for default background color
+ XPLOT11_BACKGROUND != black gives black on white plotting (like paper)
+ XPLOT11_BACKGROUND = black gives white on black plotting (reverse video) */
+ GWXREVFLAG(&reversevideo);
+
+/* set up cursor bitmap arrays */
+ /* xcsize = GetSystemMetrics(SM_CXCURSOR);
+ ycsize = GetSystemMetrics(SM_CYCURSOR);
+ if ((xcsize != 16) && (xcsize != 32)) {
+ printf("Unkown Xcursor Size %d\n", xcsize);
+ exit(1);
+ }
+ if ((ycsize != 16) && (ycsize != 32)) {
+ printf("Unkown Ycursor Size %d\n", ycsize);
+ exit(1);
+ }
+ for (i = 0; i < 128; i++) {
+ ANDMask[i] = 0xff;
+ ORNMask[i] = 0;
+ ORWMask[i] = 0;
+ }
+ j = 3;
+ if (xcsize == 16) j = 1;
+ for (k = i = 0; i < 16; i++) {
+ ANDMask[k] = ANDMsk16[i*2];
+ ORNMask[k] = ORNMsk16[i*2];
+ ORWMask[k] = ORWMsk16[i*2];
+ k++;
+ ANDMask[k] = ANDMsk16[i*2+1];
+ ORNMask[k] = ORNMsk16[i*2+1];
+ ORWMask[k] = ORWMsk16[i*2+1];
+ k += j;
+ }
+ */
+
+/* set cursor */
+ gwxWaitC = LoadCursor(NULL, IDC_WAIT);
+ gwxNormalC = LoadCursor(NULL, IDC_CROSS);
+/* gwxNormalC = CreateCursor( gwxInstance, 14, 1, xcsize, ycsize,
+ ANDMask, ORNMask); */
+/* gwxInputC = CreateCursor( gwxInstance, 14, 1, xcsize, ycsize,
+ ANDMask, ORWMask); */
+ gwxCurrentC = gwxNormalC;
+
+
+/* Define window class */
+ gwxInstance = GetModuleHandle(NULL);
+
+ gwxWndClass.cbSize = sizeof(gwxWndClass);
+ gwxWndClass.style = CS_HREDRAW | CS_VREDRAW;
+ gwxWndClass.lpfnWndProc = (WNDPROC)gwxWndProc;
+ gwxWndClass.cbClsExtra = 0;
+ gwxWndClass.cbWndExtra = 0;
+ gwxWndClass.hInstance = gwxInstance;
+ gwxWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ gwxWndClass.hCursor = gwxNormalC;
+ if(reversevideo) {
+ gwxWndClass.hbrBackground = GetStockObject(BLACK_BRUSH); }
+ else {
+ gwxWndClass.hbrBackground = GetStockObject(WHITE_BRUSH); }
+ gwxWndClass.lpszMenuName = NULL;
+ gwxWndClass.lpszClassName = (LPCSTR)gwxClass;
+
+ /* Register the window class */
+ gwxRegister = RegisterClassEx(&gwxWndClass);
+
+ /* Check for window register, bomb if no joy... */
+ if(gwxRegister == 0) {
+ printf("Failed to register window class\n");
+ exit(1);
+ }
+
+/* initialize private Xevents loop pointers */
+ gwxEvents = NULL;
+ gwxLEvent = NULL;
+
+}
+
+
+
+
+
+GC*
+gwxgc(HWND *window, int *fontsize)
+{
+ GC *gc;
+ int r, g, b, ic;
+
+ gc = (GC *) malloc(sizeof(GC));
+
+ gc->window = *window;
+ if(reversevideo) {
+ gc->fg = RGB(255,255,255);
+ gc->bg = RGB(0 ,0 ,0 );
+ }
+ else {
+ gc->fg = RGB(0 ,0 ,0 );
+ gc->bg = RGB(255,255,255);
+ }
+ gc->pen = CreatePen(PS_SOLID, penwidth, gc->fg);
+ gc->fgbrush = CreateSolidBrush(gc->fg);
+ gc->bgbrush = CreateSolidBrush(gc->bg);
+ gc->font = *fontsize;
+ gc->fun = GXcopy; /* copy */
+
+ return gc;
+}
+
+
+void
+gwxfreegc(GC **gc)
+{
+ GC *gcontext;
+
+ gcontext = *gc;
+ DeleteObject(gcontext->pen);
+ DeleteObject(gcontext->fgbrush);
+ DeleteObject(gcontext->bgbrush);
+ free(*gc);
+}
+
+
+void
+gwxgcfun(int *fun)
+{
+ GC *gcontext;
+
+ gcontext = gwxGC;
+ gcontext->fun = *fun;
+}
+
+
+
+void
+Thread1(PVOID pvoid)
+{
+ HWND winFocus, winFG, win;
+// HWND winF77;
+ RECT WinRect ,oldrect;
+ POINT point;
+ int fontsize;
+// int lunit;
+
+ /* printf("\nEntering display thread\n"); */
+ /*
+ * Make window large enough to hold a client area compensating for borders
+ */
+ WinRect.left = wxstart;
+ WinRect.right = wxstart + wxsize + 2*gwxXmatte;
+ WinRect.top = wystart;
+ WinRect.bottom = wystart + wysize + 2*gwxYmatte + gwxYbar;
+
+ /*
+ printf("\nwxstart %d wystart %d \n",wxstart,wystart);
+ printf("\nwxsize %d wysize %d \n",wxsize,wysize);
+
+ printf("\nsetting rectangle left %d right %d \n",WinRect.left,WinRect.right);
+ printf("\nsetting rectangle top %d bot %d \n",WinRect.top,WinRect.bottom);
+ */
+
+ winFG = GetForegroundWindow();
+ winFocus = GetActiveWindow();
+ GetWindowRect(winFG, &oldrect);
+ /*
+ printf("Entry conditions:\n foreground %d/n orig focus %d\n",winFG,winFocus);
+ printf("\nold rectangle left %d right %d \n",oldrect.left,oldrect.right);
+ printf("\nold rectangle top %d bot %d \n",oldrect.top,oldrect.bottom);
+ */
+
+ /* lunit = 5;
+ winF77 = fgethwndqq(&lunit);
+ printf("\nEntry conditions DVF window: %d/n",winF77);
+ */
+
+/* Must use WS_CLIPCHILDREN and WS_CLIPSIBLINGS styles. */
+
+ gwxWin = CreateWindow( gwxClass, gwxClass,
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ WinRect.left, WinRect.top,
+ WinRect.right - WinRect.left, WinRect.bottom - WinRect.top,
+ NULL, NULL, gwxInstance, NULL );
+
+ if (gwxWin == NULL) {
+ fprintf(stderr, "Error: NULL window handle.\n");
+ exit(1);
+ }
+
+ ShowWindow(gwxWin, SW_SHOWDEFAULT);
+ UpdateWindow(gwxWin);
+
+ gwxHDC = GetDC(gwxWin);
+ if (gwxHDC == NULL) {
+ fprintf(stderr, "Error: NULL window DC.\n");
+ exit(1);
+ }
+
+ /* Create compatible window bitmap */
+ gwxmemHDC = CreateCompatibleDC(gwxHDC);
+ gwxBMAP = CreateCompatibleBitmap(gwxHDC,xrootsize,yrootsize);
+ SelectObject(gwxmemHDC, gwxBMAP);
+
+ SelectObject(gwxmemHDC, GetStockObject(ANSI_VAR_FONT));
+ SetTextAlign(gwxmemHDC, TA_LEFT | TA_BASELINE | TA_NOUPDATECP);
+ SetBkMode(gwxmemHDC, TRANSPARENT);
+
+ gwxSize[0] = wxsize;
+ gwxSize[1] = wysize;
+ gwxSize[2] = wxstart + 2*gwxXmatte;
+ gwxSize[3] = wystart + 2*gwxYmatte + gwxYbar;
+ gwxSize[4] = 1;
+ SetWindowPos(gwxWin, HWND_TOP, gwxSize[2], gwxSize[3],
+ wxsize, wysize, SWP_NOMOVE|SWP_NOZORDER);
+
+ /* SetWindowPos(gwxWin, HWND_TOP, 0,0, 0,0, SWP_NOMOVE | SWP_NOSIZE ); */
+ SetForegroundWindow(gwxWin);
+
+
+ nRGBmap = 0;
+ penwidth = 0;
+ penpattern = -1;
+ ndash = 0;
+ fontsize = 1;
+
+ gwxGC = gwxgc(&gwxWin, &fontsize);
+ SelectObject(gwxmemHDC, gwxGC->pen);
+
+ /* initially clear the background bitmap */
+ SelectObject(gwxmemHDC, gwxGC->bgbrush);
+ PatBlt(gwxmemHDC, 0, 0, xrootsize, yrootsize, PATCOPY);
+
+ SelectObject(gwxmemHDC, gwxGC->fgbrush);
+
+ /* allocate black and white colors */
+/* r = 0;
+ g = 0;
+ b = 0;
+ GWXALLOCRGBCOLOR(&r,&g,&b,&ic);
+ r = 0;
+ g = 0;
+ b = 0;
+ GWXALLOCRGBCOLOR(&r,&g,&b,&ic);
+*/
+
+ /* printf("entering message loop\n\n"); */
+
+ initthread = 1;
+
+ /* while (GetMessage(&Message, NULL, 0, 0)) { */
+
+ /* Custom message loop to check cursor window to do X-style focus */
+
+ while (1) {
+ if(PeekMessage(&Message, gwxWin, 0, 0, PM_REMOVE)) {
+
+ if(Message.message==WM_QUIT)
+ break;
+
+ TranslateMessage(&Message);
+ DispatchMessage(&Message);
+ Sleep(1);
+ }
+ else {
+ GetCursorPos(&point);
+ win = WindowFromPoint(point);
+ /* printf("pos x %d y %d win %d\n",point.x,point.y,win); */
+
+ /* if(win==winF77) {
+ SetActiveWindow(win);
+ SetFocus(win);
+ SetForegroundWindow(win);
+ } */
+ /* if(win == winFG) {
+ printf("pos x %d y %d win %d winFG %d\n",point.x,point.y,win,winFG);
+ SetActiveWindow(winFG);
+ SetFocus(winFG);
+ SetForegroundWindow(winFG);
+ } */
+ Sleep(1);
+ }
+ }
+
+ /* printf("window thread ending\n"); */
+/* return Message.wParam;
+ exit; */
+
+ _endthread();
+}
+
+
+/* gwxwinopen
+ Open window of specified size and position, return size and depth
+ Parameters:
+ xstart,ystart (int*) upper left corner coordinates in root
+ xsize,ysize (int*) desired window size
+*/
+
+void W32CALL
+GWXWINOPEN (int *xstart, int *ystart, int *xsize, int *ysize)
+{
+ /*
+ printf("GWXOPEN\nxstart %d\nystart %d\nxsize %d\nysize %d\n",*xstart,*ystart,*xsize,*ysize);
+ */
+ wxstart = *xstart;
+ wystart = *ystart;
+ wxsize = *xsize;
+ wysize = *ysize;
+
+ /* Start the window thread */
+ initthread = 0;
+ _beginthread(Thread1,0,NULL);
+ /* printf("beginthread called\n"); */
+
+ while(!initthread) {
+ Sleep(5);
+ }
+
+
+}
+
+
+
+
+void W32CALL
+GWXDESTROY()
+{
+ ReleaseDC( gwxWin, gwxHDC );
+ ReleaseDC( gwxWin, gwxmemHDC );
+}
+
+
+void W32CALL
+GWXCLOSE()
+{
+ PostQuitMessage (0) ;
+ /* DestroyCursor(gwxNormalC);
+ DestroyCursor(gwxInputC); */
+ UnregisterClass((LPCSTR)gwxClass, gwxInstance);
+}
+
+
+void W32CALL
+GWXFLUSH()
+{
+ BitBlt(gwxHDC,0,0,xrootsize,yrootsize,gwxmemHDC,0,0,SRCCOPY);
+ /* InvalidateRect(gwxWin,NULL,1); */
+}
+
+
+/* gwxreset
+ Reset graphics context to default
+ Parameters: None
+*/
+void W32CALL
+GWXRESET()
+{
+}
+
+
+/* getPEN
+ Creates pen using type, color, width, pattern
+*/
+HPEN
+makenewpen()
+{
+ HPEN newpen;
+ LOGBRUSH lb;
+ GC *gcontext;
+
+ gcontext = gwxGC;
+
+ /* printf("makenewpen\n ndash %d\n lmask %d\n fg %d\n width %d\n",ndash,penpattern,gcontext->fg,penwidth); */
+
+ if(ndash == 0) {
+ if(penpattern == 0) {
+ /* printf("making penpattern 0\n"); */
+ newpen = CreatePen(PS_SOLID, penwidth, gcontext->bg);
+ }
+ if (penpattern == -1) {
+ /* printf("making penpattern -1\n"); */
+ newpen = CreatePen(PS_SOLID, penwidth, gcontext->fg);
+ }
+ }
+ else {
+ /* printf("making dash pen\n"); */
+ newpen = CreatePen(PS_DOT, 0, gcontext->fg);
+/*
+ lb.lbStyle = BS_SOLID;
+ lb.lbColor = gcontext->fg;
+ lb.lbHatch = 0;
+ newpen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE,
+ penwidth, &lb, ndash, pendash);
+ */
+ }
+ return newpen;
+}
+
+int
+GWXNUMEVENTS()
+{
+ int stat;
+
+ stat = 1;
+ if (gwxEvents == NULL) stat = 0;
+ return stat;
+}
+
+
+void
+GWXEVENT(int *type, int *x, int *y, int *state)
+{
+ gwxRemEvent(type, x, y, state);
+}
+
+
+int
+GWXGETEVENT(int *type, int *x, int *y, int *state)
+{
+ int stat;
+ Event *event;
+
+ stat = -1;
+ event = gwxEvents;
+ gwxLEvent = NULL;
+ while (event != NULL) {
+ if ((*type == event->type) && (stat == -1)) {
+ *x = event->x;
+ *y = event->y;
+ *state = event->state;
+ stat = 0;
+ if (gwxLEvent == NULL) {
+ gwxEvents = event->next;
+ } else {
+ gwxLEvent->next = event->next;
+ }
+ free(event);
+ event = NULL;
+ if (gwxLEvent != NULL) event = gwxLEvent->next;
+ } else {
+ gwxLEvent = event;
+ event = event->next;
+ }
+ }
+ return stat;
+}
+
+
+
+
+
+
+/* gwxstatus
+ Return current window status (position, size)
+ Parameters:
+ xstart,ystart (int*) upper left corner coordinates in root
+ xsize,ysize (int*) desired window size
+*/
+void W32CALL
+GWXSTATUS(int *xstart, int *ystart, int *xsize, int *ysize)
+
+{
+ RECT rect;
+
+ /*
+ GetClientRect(gwxWin, &rect);
+ printf("\nstatus rectangle left %d right %d \n",rect.left,rect.right);
+ printf("\n top %d bot %d \n",rect.top,rect.bottom);
+ */
+ GetWindowRect(gwxWin, &rect);
+ *xstart = rect.left;
+ *ystart = rect.top;
+ *xsize = rect.right - rect.left - 2*gwxXmatte;
+ *ysize = rect.bottom - rect.top - 2*gwxYmatte - gwxYbar;
+
+ /*
+ printf("\nstatus xstart %d ystart %d \n",*xstart,*ystart);
+ printf("\n xsize %d ysize %d \n",*xsize,*ysize);
+ printf("\nstatus rectangle left %d right %d \n",rect.left,rect.right);
+ printf("\n top %d bot %d \n",rect.top,rect.bottom);
+ */
+}
+
+
+
+/* gwxresize
+ Resize screen window to x width, y height
+ Parameters:
+ x (int*) new width
+ y (int*) new height
+*/
+void W32CALL
+GWXRESIZE(x, y)
+ int *x, *y;
+{
+ int ix, iy;
+
+ gwxSize[0] = *x;
+ gwxSize[1] = *y;
+ ix = gwxSize[0] + 2*gwxXmatte;
+ iy = gwxSize[1] + 2*gwxYmatte + gwxYbar;
+ SetWindowPos(gwxWin, HWND_TOP, gwxSize[2], gwxSize[3],
+ ix, iy, SWP_NOMOVE|SWP_NOZORDER);
+}
+
+
+/* gwxclear
+ Clear current plot window
+ Parameters: None
+*/
+void W32CALL
+GWXCLEAR()
+{
+ int i;
+ RECT WinRect;
+
+ WinRect.left = 0;
+ WinRect.right = gwxSize[0] + 2*gwxXmatte;
+ WinRect.top = 0;
+ WinRect.bottom = gwxSize[1] + 2*gwxYmatte + gwxYbar;
+ FillRect(gwxmemHDC, &WinRect, gwxGC->bgbrush);
+ return;
+}
+
+
+/* gwxdisplaybuffer
+ Switches background buffer onto foreground window, displaying accumulated
+ graphics
+ Parameters: None
+*/
+void W32CALL
+GWXDISPLAYBUFFER()
+{
+}
+
+
+/* gwxdrawtobuffer
+ Switches graphics to draw to the background buffer
+ Parameters: None
+*/
+void W32CALL
+GWXDRAWTOBUFFER()
+{
+/* printf("called gwxdrawtobuffer\n"); */
+}
+
+/* gwxdrawtowindow
+ Switches graphics to draw to the foreground window
+ Parameters: None
+*/
+void W32CALL
+GWXDRAWTOWINDOW()
+{
+/* printf("called gwxdrawtowindow\n"); */
+}
+
+
+void W32CALL
+GWXSTRING(int *x, int *y, char *text, int *length)
+{
+ int i, xs, ys;
+ GC *gcontext;
+
+ xs = *x + gwxXmatte;
+ ys = *y + gwxYmatte;
+
+ gcontext = gwxGC;
+ if (gcontext->font != 3) {
+ SelectObject(gwxmemHDC, GetStockObject(ANSI_VAR_FONT));
+ } else {
+ SelectObject(gwxmemHDC, GetStockObject(SYSTEM_FONT));
+ }
+ SetTextColor(gwxmemHDC, gcontext->fg);
+ SetBkColor (gwxmemHDC, TRANSPARENT);
+ TextOut(gwxmemHDC, xs, ys, text, *length);
+}
+
+
+/* gwxline
+ Draw line from x1,y1 to x2,y2
+ Parameters:
+ x1,y1 (int*) starting position for line
+ x2,y2 (int*) ending position for line
+*/
+void W32CALL
+GWXLINE(int *x1, int *y1, int *x2, int *y2)
+{
+ int i, xs, ys;
+
+ xs = *x1;
+ ys = *y1;
+ MoveToEx(gwxmemHDC, xs, ys, NULL);
+ xs = *x2;
+ ys = *y2;
+ LineTo(gwxmemHDC, xs, ys);
+}
+
+
+/* gwxlinez
+ Draw polyline on window in current color and pen
+ Parameters:
+ ix (int*) array of x coordinates on polyline
+ iy (int*) array of y coordinates on polyline
+ n (int*) number of coordinate points
+ (see define for MAXPTS at start of this file)
+*/
+void W32CALL
+GWXLINEZ(int *ix, int *iy, int *n)
+{
+ int i, xs, ys;
+
+ POINT points[MAXPTS];
+
+ if (*n > MAXPTS) {
+ fprintf(stderr,"Xplot11.gwxlinez: Too many points in polyline\n");
+ printf("Xplot11.gwxlinez: Too many points in polyline\n");
+ return;
+ }
+
+ for(i=0; i < *n; i++) {
+ points[i].x = ix[i];
+ points[i].y = iy[i];
+/* printf("gwxlinez x %d y %d \n",ix[i],iy[i]); */
+ }
+ Polyline(gwxmemHDC, points, *n);
+}
+
+
+/* gwxpoly
+ Draw filled polyline on window in current color and pen
+ Parameters:
+ x_coord (int*) array of x coordinates on polyline
+ y_coord (int*) array of y coordinates on polyline
+ n_coord (int*) number of coordinate points
+ (see define for MAXPTS at start of this file)
+*/
+void W32CALL
+GWXPOLY(x_coord, y_coord, n_coord)
+ int *x_coord, *y_coord, *n_coord;
+
+{ POINT points[MAXPTS];
+ int i,n;
+
+ if (*n_coord >= MAXPTS) {
+ fprintf(stderr,"Xplot11.gwxpoly: Too many points in polyline\n");
+ printf("Xplot11.gwxpoly: Too many points in polyline\n");
+ return;
+ }
+
+ for (i=0; i < *n_coord; i++) {
+ points[i].x = x_coord[i];
+ points[i].y = y_coord[i];
+
+ }
+ n = *n_coord;
+/* if the polyline is not closed, duplicate first point to ensure closed
+
+ perimeter (speeds up X graphics drastically) */
+ if ( (points[n-1].x != points[0].x) ||
+ (points[n-1].y != points[0].y) ) {
+ points[n].x = points[0].x;
+ points[n].y = points[0].y;
+ n++;
+ }
+ Polygon(gwxmemHDC, points, n);
+}
+
+
+void W32CALL
+GWXARC(int *xc, int *yc,
+ int *xr, int *yr, float *alpha, float *beta)
+{
+ int i, j, xs, ys;
+
+ /* only does circles! */
+
+ xs = *xc + *xr;
+ ys = *yc;
+ MoveToEx(gwxmemHDC, xs, ys, NULL);
+ for (j = 2; j <= 360; j += 2) {
+ xs = (int) ((double)*xc + (double)*xr*cos((double)j*0.017453292));
+ ys = (int) ((double)*yc + (double)*yr*sin((double)j*0.017453292));
+ LineTo(gwxmemHDC, xs, ys);
+ }
+}
+
+void W32CALL
+GWXCURS(int *x, int *y, int *state)
+{
+int type;
+
+/* Eat up all the current events first */
+
+ while(GWXNUMEVENTS()) {
+ GWXEVENT(&type, x, y, state);
+ /* printf("eat up event %d\n",type); */
+ }
+/* Now run an event loop until a buttonpress or keypress is found */
+
+ while(1) {
+ if(GWXNUMEVENTS()) {
+ GWXEVENT(&type, x, y, state);
+ /* printf("get event %d\n",type); */
+ switch (type) {
+ case XKeyPress:
+ return;
+
+ case XButtonPress:
+ return;
+ }
+ }
+ }
+}
+
+
+void W32CALL
+GWXCURS2(int *x, int *y, int *state)
+{
+ int i, key;
+ POINT point;
+
+ key = 0;
+ if (GetAsyncKeyState(VK_SHIFT) < 0) key += 1;
+ if (GetAsyncKeyState(VK_CONTROL) < 0) key += 4;
+ if (GetAsyncKeyState(VK_MENU) < 0) key += 8;
+ if (GetAsyncKeyState(VK_LBUTTON) < 0) key += 256;
+ if (GetAsyncKeyState(VK_MBUTTON) < 0) key += 512;
+ if (GetAsyncKeyState(VK_RBUTTON) < 0) key += 1024;
+ if ((GetAsyncKeyState(VK_LBUTTON) < 0) &&
+ (GetAsyncKeyState(VK_RBUTTON) < 0)) key -= 768;
+
+ GetCursorPos(&point);
+
+ *x = -1;
+ *y = -1;
+ *state = 0;
+ *x = point.x - gwxSize[2];
+ *y = point.y - gwxSize[3];
+ *state = key;
+}
+
+
+HWND W32CALL
+GWXCURRENTPOINTER(int *x, int *y)
+{
+ POINT point;
+ RECT rect;
+ HWND win;
+
+ GetCursorPos(&point);
+ win = WindowFromPoint(point);
+ GetWindowRect(win, &rect);
+ *x = point.x - rect.left;
+ *y = point.y - rect.top;
+ return win;
+}
+
+
+void W32CALL
+GWXSETPOINTER(HWND win, int *x, int *y)
+{
+ int ix, iy;
+ RECT rect;
+
+ if (GetActiveWindow() != win) SetActiveWindow(win);
+ if (GetFocus() != win) SetFocus(win);
+ if (GetForegroundWindow() != win) SetForegroundWindow(win);
+ GetWindowRect(win, &rect);
+ ix = *x + rect.left;
+ iy = *y + rect.top;
+ SetCursorPos(ix, iy);
+}
+
+
+
+
+/* gwxdash
+ Set line drawing pattern to mask pattern
+ Parameters:
+ mask (int*) integer mask value (bits set pen pattern for lines)
+*/
+void W32CALL
+GWXDASH(int* lmask)
+{
+GC *gcontext;
+int i, ndsh;
+HPEN oldpen;
+
+ penpattern = *lmask;
+ gcontext = gwxGC;
+
+ if(*lmask==0) {
+ ndash = 0;
+ }
+ else if(*lmask==-1) {
+ ndash = 0;
+ }
+ else {
+ (void) MSKBITS(lmask,pendash,&ndsh);
+ ndash = ndsh;
+/* for(i=1; i<=ndash; i++) printf("%d dashes %d\n",i,pendash[i-1]); */
+ }
+ oldpen = gcontext->pen;
+ gcontext->pen = makenewpen();
+ oldpen = SelectObject(gwxmemHDC, gcontext->pen);
+ DeleteObject(oldpen);
+}
+
+
+
+/* gwxpen
+ Set pen width for line drawing
+ Parameters:
+ ipen (int*) integer pen width
+*/
+void W32CALL
+GWXPEN(int* ipen)
+{
+GC *gcontext;
+HPEN oldpen;
+
+ penwidth = *ipen;
+ gcontext = gwxGC;
+ oldpen = gcontext->pen;
+ gcontext->pen = makenewpen();
+ oldpen = SelectObject(gwxmemHDC, gcontext->pen);
+ DeleteObject(oldpen);
+}
+
+
+/* mskbits
+ Utility routine to convert lower 16 bits of pattern mask
+ into pattern array of on/off bit lengths. The 16
+ bits of ipat can contain up to 16 on/off bit lengths.
+ i.e. 0XAAAAAAA produces ibits=(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
+ i.e. 0XCCCCCCC produces ibits=(2,2,2,2,2,2,2,2)
+ The output pattern stored in integer array ibits=(#on,#off,#on,#off,etc.)
+ Parameters:
+ mask (int*) input mask
+ ibits (int*) output pattern string (#on, #off...)
+ ndash (int*) number of entries in pattern array
+*/
+void
+MSKBITS(int* mask, int* ibits, int* ndash)
+{
+#define BITSINMASK 16 /* use only lower 16 bits of mask word */
+
+int i,ic,ibit,ibitold;
+int nbits, nshft;
+unsigned short lmask;
+
+/* shift mask until low bit is 1, filling high bits with 0's */
+ lmask = *mask;
+ nshft = 0;
+
+ if(lmask!=0) {
+ while (!(ibitold = (lmask & 0x01)))
+ lmask >>= 1;
+ nshft++;
+ }
+/* if no 1 bits just exit with no dashes set */
+ if(ibitold==0) {
+ *ndash = 0;
+ exit;
+ }
+
+/* cycle through the lower 'length-nshft' bits
+ checking for number of contiguous same bits,
+ store into ibits array */
+ nbits = ic = 0;
+
+ for (i=0; i<(BITSINMASK-nshft); ++i) {
+
+ ibit=(lmask & 0x01);
+
+ if(ibit != ibitold) {
+ ibits[ic++] = nbits;
+ nbits = 0;
+ }
+
+ ibitold = ibit;
+ nbits++;
+
+ lmask >>= 1;
+ }
+
+/* add bits at end of shifted bits including any initial shift
+ to find the first 1 in the low bit */
+ if(ibit==1) {
+
+ ibits[ic++] = nbits;
+ if(nshft>0)
+ ibits[ic++] = nshft;
+
+ }
+ else
+ ibits[ic++] = nbits + nshft;
+
+ *ndash = ic;
+}
+
+
+
+
+/* gwxsetcolor
+ Set foreground color to stored colormap pixel value
+ Parameters:
+ icol (int*) index of pixel value (mapped in colormap)
+*/
+void W32CALL
+GWXSETCOLOR(icol)
+ int *icol;
+{
+ int ic, n, fg;
+ GC *gcontext;
+ HPEN oldpen;
+
+/* is the color index in range for stored colormap data? */
+ ic = *icol;
+/* find the color in the table */
+ for (n=0; n < nRGBmap; n++) {
+ if(ic == RGBmap[n].ic) {
+ fg = RGBmap[n].rgb;
+ gcontext = gwxGC;
+ gcontext->fg = rgb2winrgb(fg);
+/* printf("gwxsetfgcolor fg %d wfg %d\n",*fg,gcontext->fg); */
+ gcontext->pen = makenewpen();
+ gcontext->fgbrush = RGBmap[n].brush;
+ oldpen = SelectObject(gwxmemHDC, gcontext->pen);
+ DeleteObject(oldpen);
+ SelectObject(gwxmemHDC, gcontext->fgbrush);
+ return;
+ }
+ }
+ fprintf(stderr,"Xplot11.gwxsetcolor: color index %d out of range\n",*icol);
+
+ printf("Xplot11.gwxsetcolor: color index %d out of range\n",*icol);
+}
+
+
+
+/* gwxsetbgcolor
+ Set background color to pixel value
+ Parameters:
+ pixel (int*) pixel value (mapped in colormap)
+*/
+void W32CALL
+GWXSETBGCOLOR(icol)
+ int *icol;
+{
+ int ic, n, bg;
+ GC *gcontext;
+/* is the color index in range for stored colormap data? */
+ ic = *icol;
+/* find the color in the table */
+ for (n=0; n < nRGBmap; n++) {
+ if(ic == RGBmap[n].ic) {
+ bg = RGBmap[n].rgb;
+ gcontext = gwxGC;
+ gcontext->bg = rgb2winrgb(bg);
+ gcontext->bgbrush = RGBmap[n].brush;
+ return;
+ }
+ }
+ fprintf(stderr,"Xplot11.gwxsetbgcolor: color index %d out of range\n",*icol);
+ printf("Xplot11.gwxsetbgcolor: color index %d out of range\n",*icol);
+}
+
+
+
+/* gwxcolorname2rgb
+ Find r,g,b components for color specified by name string
+ Parameters:
+ red,grn,blu (int*) output color components (0-255)
+ nc (int*) string length (# of chars)
+ colorname (char*) string containing name of valid color
+ Note: color names are not case sensitive
+ len (int) fortran appended string length (passed by value)
+
+ Valid color names are any color name that is known to X11 color database
+ Examples are "Black","White","Yellow","Orange","Red","Green",
+ "Cyan","Blue","Magenta", "ivory", etc.
+*/
+void W32CALL
+GWXCOLORNAME2RGB(int *red, int *grn, int *blu,
+ int *nc, char *colorname, int len)
+{
+ char cname[32];
+ int i,n;
+ int irgb;
+
+ n = *nc;
+ /* copy string to avoid overwriting possibly static input string
+ Note that string length is explicitly passed to avoid compatibility
+ problems with by fortran character arg length */
+ if(n>31) {
+ n = 31;
+ fprintf(stderr,"Xplot11.gwxcolorname2rgb: color name '%s' truncated\n",
+ cname);
+ printf("Xplot11.gwxcolorname2rgb: color name '%s' truncated\n",cname);
+ }
+ strncpy(cname,colorname,n);
+ cname[n] = '\0';
+
+ *red = -1;
+ *grn = -1;
+ *blu = -1;
+ if (!gwxlookupcolor(cname,&irgb)) {
+ fprintf(stderr,"Xplot11.gwxcolorname2rgb: color name '%s' not found\n",
+ cname);
+ printf("Xplot11.gwxcolorname2rgb: color name '%s' not found\n",cname);
+ return;
+ }
+ *red = 0x000000ff & (irgb >> 16);
+ *grn = 0x000000ff & (irgb >> 8);
+ *blu = 0x000000ff & (irgb);
+
+ /*
+ printf("gwxcolorname2rgb red = %d\ngrn = %d\nblu = %d\n",*red,*grn,*blu);
+ */
+}
+
+
+int
+gwxlookupcolor (char *colorname, int *irgb)
+{
+ int IC,ic,ncolors;
+ int i;
+ char cname[32], *ctmp;
+
+ IC = sizeof(Colordef);
+ ic = sizeof(colordef);
+ ncolors = ic/IC;
+
+ /*
+ printf("Colordef %d\n",IC);
+ printf("colordef %d\n",ic);
+ printf("#entries %d\n",ncolors);
+ */
+
+ if(ctmp=strcpy(cname,colorname)) {
+ for(ctmp = cname; *ctmp; ctmp++)
+ *ctmp = tolower(*ctmp);
+ }
+ /* printf("cname %s\n",cname); */
+
+ for (i=0; i < ncolors; i++) {
+ if(!strcmp(colordef[i].name,cname)) {
+ /* printf("found string %s code %d\n",colordef[i].name,colordef[i].rgb); */
+ *irgb = colordef[i].rgb;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+
+/* gwxallocrgbcolor
+ Allocate a color in colormap specified by r,g,b components
+
+ Parameters:
+ red,grn,blu (int*) input color components (0-255)
+ ic (int*) returned color index or pixel value
+*/
+void W32CALL
+GWXALLOCRGBCOLOR(int *red, int *grn, int *blu, int *ic)
+{
+ int rgb,col;
+ int i;
+
+ rgb = ((0xff & *red) << 16) | ((0xff & *grn) << 8) | (0xff & *blu);
+ *ic = -1;
+
+ /* printf("red %d\ngrn %d\nblu %d\nrgb %d\n",*red,*grn,*blu,rgb); */
+
+/* check for rgb color already allocated in table */
+
+ if(nRGBmap > 0) {
+ for (i=0; i < nRGBmap; i++) {
+ if(rgb == RGBmap[i].rgb) {
+ *ic = RGBmap[i].ic;
+ /* printf("found color %d in table at %d index %d\n",rgb,i+1,*ic); */
+ return;
+ }
+ }
+ }
+/* this color's RGB was not in table, allocate it to table
+ if there is room allocate a new color */
+
+ if(nRGBmap < MAXCOLS) {
+ RGBmap[nRGBmap].rgb = rgb;
+ RGBmap[nRGBmap].ic = nRGBmap+1;
+ col = rgb2winrgb(rgb);
+ RGBmap[nRGBmap].pen = NULL;
+ RGBmap[nRGBmap].brush = CreateSolidBrush(col);
+ nRGBmap++;
+ *ic = nRGBmap;
+ /* printf("allocating color table entry %d at %d\n",*ic,nRGBmap-1); */
+ }
+ else {
+ fprintf (stderr,"Xplot11.gwxallocrgbcolor: can't allocate color.\n");
+ printf ("Xplot11.gwxallocrgbcolor: can't allocate color.\n");
+ }
+}
+
+
+/* gwxfreecolor
+ Free a color from color map
+ Parameters:
+ pix (int*) pixel in colormap
+*/
+void W32CALL
+GWXFREECOLOR(int *icol)
+{
+ int i,ic,n;
+
+/* is the color index in range for stored colormap data? */
+ ic = *icol;
+/* printf("color to delete %d\n",ic); */
+ if((ic > 0) && (ic <= MAXCOLS)) {
+
+/* find the color in the table */
+/* printf("checking colortable of size %d\n",nRGBmap); */
+ for (n=0; n < nRGBmap; n++) {
+/* printf("comparing RGBmap %d with %d to %d\n",n,RGBmap[n].ic,ic); */
+ if(ic == RGBmap[n].ic) {
+/* delete the table entry */
+/* printf("found color %d to delete at %d\n",ic,n); */
+
+ if(RGBmap[n].pen) DeleteObject(RGBmap[n].pen);
+ if(RGBmap[n].brush) DeleteObject(RGBmap[n].brush);
+
+ if(n < nRGBmap-1) {
+ for (i=n; i < nRGBmap; i++) {
+ RGBmap[i-1].rgb = RGBmap[i].rgb;
+ RGBmap[i-1].ic = RGBmap[i].ic;
+ RGBmap[i-1].pen = RGBmap[i].pen;
+ RGBmap[i-1].brush = RGBmap[i].brush;
+ }
+ }
+ nRGBmap--;
+/* printf("deleted color %d\n",*icol); */
+ return;
+ }
+ }
+ }
+ fprintf(stderr,"Xplot11.gwxfreecolor: color index %d out of range\n",*icol);
+ printf("Xplot11.gwxfreecolor: color index %d out of range\n",*icol);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+