/* $Id: xdriv.cc,v 1.3 1996/10/08 08:17:45 roitzsch Exp $ (C)opyright 1996 by Konrad-Zuse-Center, Berlin All rights reserved. Part of the Kaskade distribution */ #include "drivers.h" #include "driversimp.h" // #define NeedFunctionPrototypes 0 #define K180PI 57.29578 #define TRANSX(X) ((X)*(graph->xScal)+(graph->xTrans)) #define TRANSY(Y) ((graph->wdHght)-(Y)*(graph->yScal)-(graph->yTrans)) #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define STDCOLORS 32 #define GRAYS 24 #define not_Null 1L static const unsigned lineWidth[3] = { 1, 2, 4 }; static const int length[] = { 2, 2, 2, 2, 4, 6 }; static const char pattern[6][7] = { { 1, 2 }, { 1, 4 }, { 3, 3 }, { 6, 3 }, { 5, 3, 1, 3 }, { 5, 3, 1, 3, 1, 3 } }; static char *mrkfontName[2] = { "-adobe-symbol-medium-r-normal--14-140-75-75-p-85-adobe-fontspecific", "8x13" }; static char *fontName[2][3] = { { "-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1", "-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1", "-adobe-helvetica-medium-r-normal--14-140-75-75-p-77-iso8859-1" }, { "6x10", "8x13", "9x15" } }; #define MAXXMARKERS 7 static const char XMarkers[2][MAXXMARKERS] = { { ' ', '*', 180, '+', 183, 196, 197 }, { ' ', '*', 'x', '+', 'o', ' ', ' ' } }; static const int dxMarker[MAXXMARKERS] = { 0, -3, -3, -3, -3, -5, -5 }; static const int dyMarker[2][MAXXMARKERS] = { { 0, 5, 4, 4, 4, 5, 5 }, { 0, 4, 3, 4, 2, 0, 0 } }; /*-------------------------------------------------------------------------*/ int XDriverImp:: OpenPort(GRAPHIC *graph) { int no = graph->wdNo; XWMHints wmhints; XSizeHints hint; XEvent event; XSetWindowAttributes attribute; if (graph->ready) return False; /* graph->wdWdth -= 8; graph->wdHght -= 36; */ hint.height = graph->wdHght; hint.width = graph->wdWdth; hint.x = graph->wdOrgX; hint.y = graph->wdOrgY - hint.height - 31; hint.flags = PPosition | PSize; window[no] = XCreateSimpleWindow(display, DefaultRootWindow(display), hint.x, hint.y, hint.width, hint.height, 0, BlackPixel(display, screen), pixels[graph->backgrCol]); gc[no] = XCreateGC(display, window[no], (unsigned long)0, 0); wmhints.flags = InputHint; wmhints.input = True; XSetWMHints(display, window[no], &wmhints); /* XSetBackground(display, gc[no], BlackPixel(display, screen)); */ XSetForeground(display, gc[no], WhitePixel(display, screen)); if (graph->linestyle != SOLID) { XSetDashes(display, gc[no], 0, pattern[graph->linestyle], length[graph->linestyle]); XSetLineAttributes(display, gc[no], lineWidth[graph->drPenSz], LineOnOffDash, CapButt, 0); } else XSetLineAttributes(display, gc[no], lineWidth[graph->drPenSz], LineSolid, CapButt, 0); XSetFillRule(display, gc[no], WindingRule); XSetStandardProperties(display, window[no], graph->caption, graph->caption, None, 0, 0, &hint); XSelectInput(display, window[no], ExposureMask); XMapRaised(display, window[no]); do XWindowEvent(display, window[no], ExposureMask, &event); while (event.xexpose.count != 0); attribute.backing_store = Always; XChangeWindowAttributes(display, window[no], CWBackingStore, &attribute); XSelectInput(display, window[no], ButtonPressMask | KeyPressMask); graph->ready = True; if (fonttyp != -1) SelFont(graph); return True; } int XDriverImp::NewPict(GRAPHIC *graph) { int no = graph->wdNo; if (no < 0) return False; if (graph->ready) { XClearWindow(display, window[no]); XFlush (display); } return True; } int XDriverImp::Close(GRAPHIC *graph) { int no = graph->wdNo; if (no < 0) return False; if (graph->ready && window[no] != 0) { XDestroyWindow(display, window[no]); XFlush (display); } window[no] = 0; return True; } int XDriverImp::Color(int col_no, int rVal, int gVal, int bVal) { XColor col; XFreeColors(display, colormap, &pixels[col_no], 1, 0); col.red = rVal * 257; col.green = gVal * 257; col.blue = bVal * 257; col.flags = DoRed | DoGreen | DoBlue; if (!XAllocColor(display, colormap, &col)) { printf("MiniGraphic - color : failure to allocate color !\n"); return False; } pixels[col_no] = col.pixel; return True; } /*-------------------------------------------------------------------------*/ int XDriverImp::PLine(GRAPHIC *graph, double* xx, double* yy, int n) { int ind = graph->wdNo, k; double x, y, a, b; XPoint pt[MAX_POINTS]; for (k = 0; k < n; k++) { x = xx[k]; y = yy[k]; a = TRANSX(x); pt[k].x = (int) a; b = TRANSY(y); pt[k].y = (int) b; } XSetForeground(display, gc[ind], pixels[graph->penCol]); XDrawLines(display, window[ind], gc[ind], pt, n, 0); return True; } int XDriverImp::PLine(GRAPHIC *graph, float* xx, float* yy, int n) { int ind = graph->wdNo, k; float x, y, a, b; XPoint pt[MAX_POINTS]; for (k = 0; k < n; k++) { x = xx[k]; y = yy[k]; a = TRANSX(x); pt[k].x = (int) a; b = TRANSY(y); pt[k].y = (int) b; } XSetForeground(display, gc[ind], pixels[graph->penCol]); XDrawLines(display, window[ind], gc[ind], pt, n, 0); return True; } /*-------------------------------------------------------------------------*/ int XDriverImp::PMarker(GRAPHIC *graph, float*xx, float* yy, int n) { int no = graph->wdNo, k, px, py; float x, y; char s[2]; if (mrkFont == 0) { printf("MiniGraphic - marker : no markers on screen !\n"); return False; } XSetFont(display, gc[no], mrkFont); XSetForeground(display, gc[no], pixels[graph->mrkCol]); s[0] = XMarkers[mrk_fonttyp][graph->mark]; s[1] = '\0'; for (k=0; kmark]; py = (int) TRANSY(y)+dyMarker[mrk_fonttyp][graph->mark]; XDrawString(display, window[no], gc[no], px, py, s, 1); } if (fonttyp != -1) XSetFont(display, gc[no], font[no]); return True; } int XDriverImp::PMarker(GRAPHIC *graph, double*xx, double* yy, int n) { int no = graph->wdNo, k, px, py; double x, y; char s[2]; if (mrkFont == 0) { printf("MiniGraphic - marker : no markers on screen !\n"); return False; } XSetFont(display, gc[no], mrkFont); XSetForeground(display, gc[no], pixels[graph->mrkCol]); s[0] = XMarkers[mrk_fonttyp][graph->mark]; s[1] = '\0'; for (k=0; kmark]; py = (int) TRANSY(y)+dyMarker[mrk_fonttyp][graph->mark]; XDrawString(display, window[no], gc[no], px, py, s, 1); } if (fonttyp != -1) XSetFont(display, gc[no], font[no]); return True; } /*-------------------------------------------------------------------------*/ int XDriverImp:: Text(GRAPHIC *graph, double x, double y, char *s) { int no = graph->wdNo; int px = (int) TRANSX(x), py = (int) TRANSY(y); if (fonttyp == -1) return False; XSetForeground(display, gc[no], pixels[graph->fntCol]); if (graph->FntProp == TRANSPARENT) XDrawString(display, window[no], gc[no], px, py, s, strlen(s)); else XDrawImageString(display, window[no], gc[no], px, py, s, strlen(s)); return True; } /*-------------------------------------------------------------------------*/ int XDriverImp::Fill(GRAPHIC *graph, float* xx, float* yy, int n) { int no = graph->wdNo, k; float x, y; XPoint pt[MAX_POINTS]; for (k=0; kfllCol]); XFillPolygon(display, window[no], gc[no], pt, n, Complex, CoordModeOrigin); return True; } //------------------------------------------------------------------------- int XDriverImp::Fill(GRAPHIC *graph, double* xx, double* yy, int n) { int no = graph->wdNo, k; double x, y; XPoint pt[MAX_POINTS]; for (k=0; kfllCol]); XFillPolygon(display, window[no], gc[no], pt, n, Complex, CoordModeOrigin); return True; } /*-------------------------------------------------------------------------*/ int XDriverImp::Settings(GRAPHIC *graph, int type, int iVal) { int no = graph->wdNo; switch (type) { case WDORGX : if ((iVal >= 0) && (iVal <= graph->right)) graph->wdOrgX = iVal; else { printf("MiniGraphic - set : wrong value for WDORGX %d !\n", iVal); return False; } return True; case WDORGY : if ((iVal >= 0) && (iVal <= graph->bottom)) graph->wdOrgY = iVal; else { printf("MiniGraphic - set : wrong value for WDORGY %d !\n", iVal); return False; } return True; case WDWDTH : if ((iVal >= 0) && (iVal + graph->wdOrgX <= graph->right)) graph->wdWdth = iVal; else { printf("MiniGraphic - set : wrong value for WDWDTH %d !\n", iVal); return False; } return True; case WDHGHT : if ((iVal >= 0) && (iVal <= graph->wdOrgY)) graph->wdHght = iVal; else { printf("MiniGraphic - set : wrong value for WDHGHT %d !\n", iVal); return False; } return True; case PENSIZE: if ((iVal >= SMALL) && (iVal <= BIG)) graph->drPenSz = iVal; else { printf("MiniGraphic - set : wrong value for PENSIZE %d !\n", iVal); return False; } if (graph->ready) XSetLineAttributes(display, gc[no], lineWidth[graph->drPenSz], graph->linestyle == SOLID ? LineSolid : LineOnOffDash, CapButt, 0); return True; case LINESTYLE : if ((iVal >= DOTTED) && (iVal <= SOLID)) graph->linestyle = iVal; else { printf("MiniGraphic - set : wrong value for LINESTYLE %d !\n", iVal); return False; } if (graph->ready) if (iVal != SOLID) { XSetDashes(display, gc[no], 0, pattern[iVal], length[graph->linestyle]); XSetLineAttributes(display, gc[no], lineWidth[graph->drPenSz], LineOnOffDash, CapButt, 0); } else XSetLineAttributes(display, gc[no], lineWidth[graph->drPenSz], LineSolid, CapButt, 0); return True; case FONTSIZE : if (fonttyp == -1) return False; if ((iVal >= SMALL) && (iVal <= BIG)) graph->drFntSz = iVal; else { printf("MiniGraphic - set : wrong value for FONTSIZE %d !\n", iVal); return False; } SelFont(graph); return True; case FONTPROP : if ((iVal == TRANSPARENT) || (iVal == OPAQUE)) graph->FntProp = iVal; else { printf("MiniGraphik - set : wrong value for FNTPROP %d !\n", iVal); return False; } return True; case MARKER: if ((iVal >= 0) && (iVal < MAXXMARKERS)) graph->mark = iVal; else { printf("MiniGraphic - set : unkown marker %d !\n", iVal); return False; } return True; case FILLCOL: if ((iVal >= 0) && (iVal < graph->maxCol)) graph->fllCol = iVal; else { printf("MiniGraphic - set : unkown fill-color %d !\n", iVal); return False; } return True; case MARKCOL: if ((iVal >= 0) && (iVal < graph->maxCol)) graph->mrkCol = iVal; else { printf("MiniGraphic - set : unkown marker-color %d !\n", iVal); return False; } return True; case FONTCOL: if ((iVal >= 0) && (iVal < graph->maxCol)) graph->fntCol = iVal; else { printf("MiniGraphic - set : unkown font-color %d !\n", iVal); return False; } return True; case PENCOL: if ((iVal >= 0) && (iVal < graph->maxCol)) graph->penCol = iVal; else { printf("MiniGraphic - set : unkown pen-color %d !\n", iVal); return False; } return True; case BACKGRCOL: if ((iVal >= 0) && (iVal < graph->maxCol)) graph->backgrCol = iVal; else { printf("MiniGraphic - set : unkown background-color %d !\n", iVal); return False; } return True; // printf("MiniGraphic - set: unkown type %d !\n", type); } return False; } int XDriverImp::Settings(GRAPHIC *graph, int type, char* str) { int n; switch (type) { case CAPTION: delete graph->caption; n = strlen(str); graph->caption = new char[n+1]; strcpy(graph->caption, str); return True; /* case BUFFER : iVal = *((int*)valAdr); if ((iVal == ON) || (iVal == OFF)) { graph->buffer = iVal; XSynchronize(display, !iVal); } else if (iVal == FLUSH) XFlush(display); else { printf("MiniGraphic - set : unkown buffer status %d !\n", iVal); return False; } return True; */ default: printf("MiniGraphic - set: unkown type %d !\n", type); } return False; } /*-------------------------------------------------------------------------*/ void XDriverImp::geometric(GRAPHIC *graph, int geo, coor org, coor vec) { int ind = graph->wdNo, radius; XPoint points[5]; XSegment segments[2]; switch (geo) { case STRAIGHTLINE: XDrawLine(display, window[ind], gc[ind], org.x, org.y, vec.x, vec.y); break; case RECTANGLE : points[0].x = org.x; points[0].y = org.y; points[1].x = vec.x; points[1].y = org.y; points[2].x = vec.x; points[2].y = vec.y; points[3].x = org.x; points[3].y = vec.y; points[4].x = org.x; points[4].y = org.y; XDrawLines(display, window[ind], gc[ind], points, 5, CoordModeOrigin); /*XDrawRectangle(display, window[ind], gc[ind], org.x, org.y, (unsigned)(vec.x-org.x), (unsigned)(vec.y-org.y) );*/ break; case CIRCLE : radius = (int) sqrt(pow((double)(vec.x-org.x), 2.0)+pow((double)(vec.y-org.y), 2.0)); segments[0].x1 = org.x-radius; segments[0].y1 = org.y; segments[0].x2 = org.x+radius; segments[0].y2 = org.y; segments[1].x1 = org.x; segments[1].y1 = org.y+radius; segments[1].x2 = org.x; segments[1].y2 = org.y-radius; XDrawArc(display, window[ind], gc[ind], org.x-radius, org.y-radius, 2*radius, 2*radius, 0, 23040); XDrawSegments(display, window[ind], gc[ind], segments, 2); break; } return; } int XDriverImp::Gin (GRAPHIC *graph, int geo, void* x1koordAdr, void* y1koordAdr, void* x2koordAdr, void* y2koordAdr) { Cursor cursor; XEvent event; float Org_x, Org_y; double x1koord, y1koord, x2koord, y2koord; int no = graph->wdNo; coor org, vec; XFlush(display); cursor = XCreateFontCursor(display, XC_tcross); XDefineCursor(display, window[no], cursor); XSetLineAttributes(display, gc[no], 0, 0, 0, 0); XSetFunction(display, gc[no], GXxor); XSetForeground(display, gc[no], pixels[0]); XSelectInput(display, window[no], ButtonPressMask | Button1MotionMask | ButtonReleaseMask | KeyPressMask ); while (XCheckWindowEvent(display, window[no], ButtonPressMask | Button1MotionMask | ButtonReleaseMask, &event)); XWindowEvent(display, window[no], ButtonPressMask | Button1MotionMask, &event); Org_x = event.xbutton.x; org.x = vec.x = (int) Org_x; Org_y = event.xbutton.y; org.y = vec.y = (int) Org_y; geometric(graph, geo, org, vec); do { XWindowEvent(display, window[no], Button1MotionMask |ButtonReleaseMask, &event); if ((vec.x != event.xmotion.x) || (vec.y != event.xmotion.y)) { geometric(graph, geo, org, vec); vec.x = event.xmotion.x; vec.y = event.xmotion.y; geometric(graph, geo, org, vec); } } while (event.type != ButtonRelease); geometric(graph, geo, org, vec); XUndefineCursor(display, window[no]); XSetLineAttributes(display, gc[no], lineWidth[graph->drPenSz], graph->linestyle == SOLID ? LineSolid : LineOnOffDash, CapButt, 0); XSetFunction(display, gc[no], GXcopy); XSelectInput(display, window[no], ButtonPressMask | KeyPressMask); x1koord = (Org_x - graph->xTrans) / graph->xScal; y1koord = (graph->wdHght - Org_y - graph->yTrans) / graph->yScal; x2koord = (event.xmotion.x - graph->xTrans) / graph->xScal; y2koord = (graph->wdHght - event.xmotion.y - graph->yTrans) / graph->yScal; if (graph->prec == SINGLE) { *((float*)x1koordAdr) = x1koord; *((float*)y1koordAdr) = y1koord; *((float*)x2koordAdr) = x2koord; *((float*)y2koordAdr) = y2koord; } else { *((double*)x1koordAdr) = x1koord; *((double*)y1koordAdr) = y1koord; *((double*)x2koordAdr) = x2koord; *((double*)y2koordAdr) = y2koord; } return True; } int XDriverImp::Event(GRAPHIC *graph, int* typAdr, int* buttonAdr, void* xkoordAdr, void* ykoordAdr, int* chAdr) { char ch; int no = graph->wdNo; XEvent event, last_event; XKeyEvent keyEvent, keyLast_event; double xkoord = 0, ykoord = 0; *typAdr = *buttonAdr = *chAdr = 0; last_event.type = -1; while (XCheckWindowEvent(display, window[no], ButtonPressMask | KeyPressMask, &event)) { if (event.type == KeyPress) if (XLookupString(&keyEvent, &ch, 1, 0, 0)) if (ch > 31) input_queue[no][queue_pointer[no]++] = ch; last_event = event; } if (last_event.type != -1) { switch (last_event.type) { case KeyPress : *typAdr |= 4; if (XLookupString(&keyLast_event, &ch, 1, 0, 0)) *chAdr = ch; else { switch (XLookupKeysym(&keyLast_event, 0)) { case XK_Shift_L : case XK_Shift_R : *typAdr |= 1; break; case XK_Control_L : case XK_Control_R : *typAdr |= 2; break; default : ; } } break; case ButtonPress : switch (last_event.xbutton.button) { case 1 : *buttonAdr |= 4; break; case 2 : *buttonAdr |= 2; break; case 3 : *buttonAdr |= 1; break; default : *buttonAdr |= 4; } *typAdr |= 8; break; default : ; } if (last_event.xkey.state & ShiftMask) *typAdr |= 1; if (last_event.xkey.state & ControlMask) *typAdr |= 2; xkoord = (last_event.xbutton.x - graph->xTrans) / graph->xScal; ykoord = (graph->wdHght - last_event.xbutton.y - graph->yTrans) / graph->yScal; } if (graph->prec == SINGLE) { *((float*)xkoordAdr) = xkoord; *((float*)ykoordAdr) = ykoord; } else { *((double*)xkoordAdr) = xkoord; *((double*)ykoordAdr) = ykoord; } if (last_event.type == -1) return False; return True; } int XDriverImp::Wait (GRAPHIC* graph, int* typAdr, int* buttonAdr, void* xkoordAdr, void* ykoordAdr, int* chAdr) { int no = graph->wdNo; XEvent event; XKeyEvent keyEvent; double xkoord, ykoord; char ch = 0; *typAdr = *buttonAdr = *chAdr = 0; XSetInputFocus(display, window[no], RevertToPointerRoot, 0); XFlush(display); while (XCheckWindowEvent(display, window[no], ButtonPressMask | KeyPressMask, &event)) if (event.type == KeyPress) if (XLookupString(&keyEvent, &ch, 1, 0, 0)) if (ch > 31) input_queue[no][queue_pointer[no]++] = ch; event.type = -1; XWindowEvent(display, window[no], ButtonPressMask | KeyPressMask, &event); switch (event.type) { case KeyPress : *typAdr |= 4; if (XLookupString(&keyEvent, &ch, 1, 0, 0)) { *chAdr = ch; if (ch > 31) input_queue[no][queue_pointer[no]++] = ch; } else { switch (XLookupKeysym(&keyEvent, 0)) { case XK_Shift_L : case XK_Shift_R : *typAdr |= 1; break; case XK_Control_L : case XK_Control_R : *typAdr |= 2; break; default : ; } } break; case ButtonPress : switch (event.xbutton.button) { case 1 : *buttonAdr |= 4; break; case 2 : *buttonAdr |= 2; break; case 3 : *buttonAdr |= 1; break; default : *buttonAdr |= 4; } *typAdr |= 8; break; default : ; } if (event.xkey.state & ShiftMask) *typAdr |= 1; if (event.xkey.state & ControlMask) *typAdr |= 2; xkoord = (event.xbutton.x - graph->xTrans) / graph->xScal; ykoord = (graph->wdHght - event.xbutton.y - graph->yTrans) / graph->yScal; if (graph->prec == SINGLE) { *((float*)xkoordAdr) = xkoord; *((float*)ykoordAdr) = ykoord; } else { *((double*)xkoordAdr) = xkoord; *((double*)ykoordAdr) = ykoord; } /*XPutBackEvent(display, &event);*/ return True; } int XDriverImp::String (GRAPHIC *graph, char* string, int* length) { int no = graph->wdNo, i; XEvent event; XKeyEvent keyEvent; char ch; while (XCheckWindowEvent(display, window[no], KeyPressMask, &event)) if (event.type == KeyPress) if (XLookupString(&keyEvent, &ch, 1, 0, 0)) if (ch > 31) input_queue[no][queue_pointer[no]++] = ch; for(i = 0; i < queue_pointer[no]; i++) *string++ = input_queue[no][i]; for(i = queue_pointer[no]; i < MAX_STRING; i++) *string++ = '\0'; *length = queue_pointer[no]; queue_pointer[no] = 0; return True; } /*int stop_event(display, event, args) Display display; XEvent event; char *args; { if (XLookupKeysym(&event, 0) == XK_Pause) return True; return False; } void stop() { XEvent event; if (XCheckIfEvent(display, &event, stop_event, 0)) { printf("MiniGraphik : Stop execution !\n"); printf("Press any key or button to continue.\n"); } return; } */ /*-------------------------------------------------------------------------*/ XDriverImp::XDriverImp() { int k, i, size, low = BLACK, high = WHITE; int count; xreal dRed, dGreen, dBlue, dk; XColor col; for (i=0; ibottom = DisplayHeight(display, screen); graph->left = 0.0; graph->top = 0.0; graph->right = DisplayWidth(display, screen); graph->wdWdth = graph->wdHght = int((graph->bottom - graph->top)*size - 31.0); switch (free % 4) { case 0 : graph->wdOrgX = int(graph->right - graph->wdWdth - 10); graph->wdOrgY = int((graph->bottom - graph->top) * 0.5); break; case 1 : graph->wdOrgX = int(graph->right - 2*graph->wdWdth - 20); graph->wdOrgY = int((graph->bottom - graph->top) * 0.5); break; case 2 : graph->wdOrgX = int(graph->right - 2*graph->wdWdth - 20); graph->wdOrgY = int(graph->bottom); break; case 3 : graph->wdOrgX = int(graph->right - graph->wdWdth - 10); graph->wdOrgY = int(graph->bottom); break; } graph->drRes = 1.0; graph->drPenSz = SMALL; graph->linestyle = SOLID; graph->drFntSz = MEDIUM; graph->FntProp = TRANSPARENT; graph->drXcm = (double)DisplayWidthMM(display, screen) / (double)(10*DisplayWidth(display, screen)); graph->drYcm = (double)DisplayHeightMM(display, screen) / (double)(10*DisplayHeight(display,screen)); graph->penCol = graph->fllCol = graph->fntCol = graph->mrkCol = BLACK; graph->backgrCol = WHITE; graph->maxCol = COLORS; graph->maxGry = GRAYS; graph->mark = STAR; graph->id = X11; graph->wdNo = free; graph->fontName = fontName[fonttyp][MEDIUM]; graph->fileName = 0; graph->caption = new char[strlen(captionName)+1]; strcpy (graph->caption, captionName); graph->file = 0; graph->buffer = ON; return True; } int XDriverImp::SelFont(GRAPHIC *graph) { int no = graph->wdNo; if (font[no] != 0) XUnloadFont(display, font[no]); graph->fontName = fontName[fonttyp][graph->drFntSz]; font[no] = XLoadFont(display, graph->fontName); if (graph->ready) XSetFont(display, gc[no], font[no]); return True; } /*-------------------------------------------------------------------------*/ void XDriverImp:: FlushDisplay() { XFlush(display); } /*-------------------------------------------------------------------------*/