/* grOS2_1.c - * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* * * This file contains primitive functions to manipulate an X window system * Included here are initialization and closing * functions, and several utility routines used by the other X * modules. */ #define HIRES /* #define HIRESDB */ #include #include #include #include #define INCL_DOSPROCESS #define INCL_DOSSEMAPHORES #define INCL_DOSDATETIME #define INCL_DOSNMPIPES #define INCL_DOSQUEUES #include #include #include #include #include #include #define SIGKILL SIGTERM #ifdef SYSV #include #else #include #endif #include #include #include #include #include "misc/magic.h" #include "misc/magsgtty.h" #include "utils/geometry.h" #include "graphics/glyphs.h" #include "graphics/graphics.h" #include "windows/windows.h" #include "graphics/graphicsInt.h" #include "textio/textio.h" #include "textio/txcommands.h" #include "signals/signals.h" #include "utils/utils.h" #include "utils/hash.h" #include "grX11Int.h" #include "misc/paths.h" Display *grXdpy; int grXscrn; GR_CURRENT grCurrent= {0,0,0,0,0,0}; GC grGCFill, grGCText, grGCDraw, grGCCopy, grGCGlyph, grGCStipple; #ifdef HIRES extern Visual *grVisual; extern unsigned int grClass; #endif /* HIRES */ Void grXWStdin(int , ClientData ); int grXuserPC = 0; char grXdepth[8]; static Atom wm_delete_window; /* lbl close window patch */ Pixmap grX11Stipples[GR_NUM_STIPPLES]; HashTable grX11WindowTable; /* locals */ int pipeRead, pipeWrite; typedef struct { char dashlist[8]; int dlen; } LineStyle; static LineStyle LineStyleTab[256]; int Xhelper; HEV hevXhandle; ULONG pPostcnt; #define grMagicToXs(n) (DisplayHeight(grXdpy,grXscrn)-(n)) #define grXsToMagic(n) (DisplayHeight(grXdpy,grXscrn)-(n)) /* This is kind of a long story, and very kludgy, but the following * things need to be defined as externals because of the way lint * libraries are made by taking this module and changing all procedures * names "Xxxx" to "Grxxx". The change is only done at the declaration * of the procedure, so we need these declarations to handle uses * of those names, which don't get modified. Check out the Makefile * for details on this. */ extern Void GrX11Close(), GrX11Flush(); extern Void GrX11Init(),GrX11Create(MagWindow *); extern Void GrX11Delete(MagWindow *),GrX11Configure(MagWindow *); extern Void GrX11Raise(MagWindow *),GrX11Lower(MagWindow *); extern Void GrX11Lock(MagWindow *, bool),GrX11Unlock(MagWindow *); extern Void GrX11IconUpdate(MagWindow *, char *); /*--------------------------------------------------------- * grxSetWMandC: * This is a local routine that resets the value of the current * write mask and color, if necessary. * * Results: None. * * Side Effects: None. * * Errors: None. *--------------------------------------------------------- */ Void grx11SetWMandC (mask, c) int mask; /* New value for write mask */ int c; /* New value for current color */ { static int oldC = -1; static int oldM = -1; c = grPixels[c]; #ifdef HIRES if(grCurrent.depth <= 8) { mask = grPlanes[mask]; if (mask == -65) mask = AllPlanes; } else { mask = AllPlanes; } #else mask = grPlanes[mask]; if (mask == -65) mask = AllPlanes; #endif /* HIRES */ if (oldC == c && oldM == mask) return; GR_X_FLUSH_BATCH(); XSetPlaneMask(grXdpy,grGCFill,mask); XSetPlaneMask(grXdpy,grGCDraw,mask); XSetPlaneMask(grXdpy,grGCText,mask); XSetForeground(grXdpy,grGCFill,c); XSetForeground(grXdpy,grGCDraw,c); XSetForeground(grXdpy,grGCText,c); oldC = c; oldM = mask; } /*--------------------------------------------------------- * grxSetLineStyle: * This local routine sets the current line style. * * Results: None. * * Side Effects: * A new line style is output to the display. * *--------------------------------------------------------- */ Void grx11SetLineStyle (style) int style; /* New stipple pattern for lines. */ { static int oldStyle = -1; LineStyle *linestyle; int xstyle; style &= 0xFF; if (style == oldStyle) return; oldStyle = style; GR_X_FLUSH_BATCH(); switch (style) { case 0xFF: case 0x00: xstyle = LineSolid; break; default: xstyle = LineOnOffDash; linestyle = &LineStyleTab[style]; if (linestyle->dlen == 0) { /* translate style to an X11 dashlist */ char *e; int cnt,offset,cur,new,curnew,i,match; e = linestyle->dashlist; cnt = 0; offset = 1; cur = 0; for (i = 7; i >= 0; i--) { new = (style >> i) & 1; curnew = (cur << 1) | new; switch (curnew) { case 0: case 3: cnt++; break; case 1: if (cnt > 0) *e++ = cnt; else offset = 0; cnt = 1; break; case 2: *e++ = cnt; cnt = 1; break; } cur = new; } *e++ = cnt; cnt = e - linestyle->dashlist; if (offset) { cur = e[0]; for (i = 0; i < cnt-1; i++) e[i] = e[i+1]; e[cnt-1] = cur; } match = 1; do { if (cnt % 2) break; for (i = 0; i < cnt/2; i++) { if (e[i] != e[cnt/2 + i]) match = 0; } if (match == 0) break; cnt = cnt/2; } while (match); linestyle->dlen = cnt; } XSetDashes(grXdpy, grGCDraw, 0, linestyle->dashlist, linestyle->dlen); } #ifdef OLD_XFREE /* Bypass bug in XFree-2.x server */ XSetLineAttributes(grXdpy, grGCDraw, 1, xstyle, CapNotLast, JoinMiter); #else XSetLineAttributes(grXdpy, grGCDraw, 0, xstyle, CapNotLast, JoinMiter); #endif } /*--------------------------------------------------------- * grxSetSPattern: * xSetSPattern associates a stipple pattern with a given * stipple number. This is a local routine called from * grStyle.c . * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ Void grx11SetSPattern (stipple, pattern) int stipple; /* The stipple number, 1-15. */ int pattern[8]; /* 8 8-bit patterns integers */ { Pixmap p; int x,y,pat; p = XCreatePixmap(grXdpy, XDefaultRootWindow(grXdpy), 8, 8, 1); if (grGCStipple == 0) { grGCStipple = XCreateGC(grXdpy, p, 0, 0); } for (y = 0; y < 8; y++) { pat = pattern[y]; for (x = 0; x < 8; x++) { XSetForeground(grXdpy, grGCStipple, pat & 1); XDrawPoint(grXdpy, p, grGCStipple, x, y); pat >>= 1; } } grX11Stipples[stipple] = p; } /*--------------------------------------------------------- * grxSetStipple: * This routine sets the Xs current stipple number. * * Results: None. * * Side Effects: * The current clipmask in the X is set to stipple, * if it wasn't that already. *--------------------------------------------------------- */ Void grx11SetStipple (stipple) int stipple; /* The stipple number to be used. */ { static int oldStip = -1; if (stipple == oldStip) return; oldStip = stipple; GR_X_FLUSH_BATCH(); if (stipple == 0 || stipple > GR_NUM_STIPPLES) { XSetFillStyle(grXdpy, grGCFill, FillSolid); } else { if (grX11Stipples[stipple] == 0) { TxPrintf("Stipple index %d not supported. Correct the dstyle file.\n", stipple); return; } XSetStipple(grXdpy, grGCFill, grX11Stipples[stipple]); XSetFillStyle(grXdpy, grGCFill, FillStippled); } } bool /*--------------------------------------------------------- * GrXInit: * GrXInit initializes the graphics display and clears its screen. * Files must have been previously opened with GrSetDisplay(); * * Results: TRUE if successful. *--------------------------------------------------------- */ GrX11Init () { grXdpy = XOpenDisplay(NULL); if (grXdpy == NULL) { TxError("Couldn't open display %s; check DISPLAY variable\n", getenv("DISPLAY")); return false; } grXscrn = XDefaultScreen(grXdpy); grCurrent.depth = XDefaultDepth(grXdpy, grXscrn); grCurrent.window = XDefaultRootWindow(grXdpy); if (grXuserPC > 0) { if (grXuserPC > grCurrent.depth) { TxError("You cannot specify more planes (%d) than the display has (%d).\n",grXuserPC,grCurrent.depth); return false; } grCurrent.depth = (grXuserPC == 1)?0:grXuserPC; } else /* default to nearest depth that we "should" have dstyles and colormap for. */ { if (grCurrent.depth < 4) grCurrent.depth = 0; else if (grCurrent.depth < 6) grCurrent.depth = 4; else if (grCurrent.depth < 7) grCurrent.depth = 6; else grCurrent.depth = 7; } /* lbl close-window patch */ /* Prevents termination when Magic window is deleted via the window-manager. Same global atom (wm_delete_window) used by all windows */ wm_delete_window = XInternAtom(grXdpy, "WM_DELETE_WINDOW", False); grDStyleType = grXdepth; if (grCurrent.depth) { sprintf(grXdepth,"%dbit",grCurrent.depth); grCMapType = grXdepth; } else { sprintf(grXdepth,"bw"); grCMapType = NULL; /* have to call GrX11SetCmap directly here; with colormap set to NULL, it doesn't get called otherwise. */ GrX11SetCMap((char *)NULL); } HashInit(&grX11WindowTable,8,HT_WORDKEYS); return grx11LoadFont(); } /*--------------------------------------------------------- * GrXClose: * * Results: None. * * Side Effects: *--------------------------------------------------------- */ Void GrX11Close () { int rc; if (grXdpy == NULL) return; TxDelete1InputDevice(pipeRead); rc = DosClose( pipeRead); rc = DosClose( pipeWrite); rc = kill( Xhelper, 1); /* XXX: delete from list! */ grGCStipple = 0; XCloseDisplay(grXdpy); } /*--------------------------------------------------------- * GrXFlush: * Flush output to display. * * Flushing is done automatically the next time input is read, * so this procedure should not be used very often. * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ Void GrX11Flush () { XFlush(grXdpy); } /* * --------------------------------------------------------------------------- * * grXStdin -- * * Handle the stdin device for the X driver. * * Results: * None. * * Side Effects: * Adds events to the data queue. * * --------------------------------------------------------------------------- */ Void grX11Stdin () { TxInputEvent *event; XEvent xevent; HashEntry *entry; int rc; ULONG BytesRead; struct _AVAILDATA BytesAvail; ULONG PipeState; rc = DosPeekNPipe(pipeRead, &xevent, sizeof(XEvent), &BytesRead, &BytesAvail, &PipeState); if(BytesAvail.cbpipe < sizeof(XEvent)) { return; } /* printf(" BytesAvail %d\n", BytesAvail.cbpipe); */ rc = _read(pipeRead, &xevent, sizeof(XEvent)); if(rc < sizeof(XEvent)){printf("Pipe read length error: %d\n", rc); return;} switch (xevent.type) { case ButtonPress: case ButtonRelease: { XButtonEvent *ButtonEvent = (XButtonEvent *) &xevent; event = TxNewEvent(); switch (ButtonEvent->button) { case Button1: event->txe_button = TX_LEFT_BUTTON; break; case Button2: event->txe_button = TX_MIDDLE_BUTTON; break; case Button3: event->txe_button = TX_RIGHT_BUTTON; break; } switch(xevent.type) { case ButtonRelease: event->txe_buttonAction = TX_BUTTON_UP; break; case ButtonPress: event->txe_buttonAction = TX_BUTTON_DOWN; break; } grCurrent.window = ButtonEvent->window; entry = HashLookOnly(&grX11WindowTable,grCurrent.window); grCurrent.mw= (entry)?(MagWindow *)HashGetValue(entry):0; event->txe_p.p_x = ButtonEvent->x; event->txe_p.p_y = grXToMagic(ButtonEvent->y); event->txe_wid = grCurrent.mw->w_wid; TxAddEvent(event); } break; case KeyPress: { XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) &xevent; int c; event = TxNewEvent(); grCurrent.window = KeyPressedEvent->window; entry = HashLookOnly(&grX11WindowTable,grCurrent.window); grCurrent.mw= (entry)?(MagWindow *)HashGetValue(entry):0; _read(pipeRead, &c, sizeof(int)); if (c == (int)'\r') c = (int)'\n'; event->txe_button = TX_CHARACTER; event->txe_ch = c; event->txe_buttonAction = TX_KEY_DOWN; event->txe_p.p_x = KeyPressedEvent->x; event->txe_p.p_y = grXToMagic(KeyPressedEvent->y); event->txe_wid = grCurrent.mw->w_wid; TxAddEvent(event); } break; case Expose: { XExposeEvent *ExposeEvent = (XExposeEvent*) &xevent; Rect screenRect; MagWindow *w; grCurrent.window = ExposeEvent->window; entry = HashLookOnly(&grX11WindowTable,grCurrent.window); w = (entry)?(MagWindow *)HashGetValue(entry):0; /* The line above is defintely NOT a good idea. w == 0 causes address exception. Why X11 is generating an expose event for a non-existent window is another question... ***mdg*** */ if(w == 0) {printf("Expose: w = %d.\n", w); break;} grCurrent.mw=w; screenRect.r_xbot = ExposeEvent->x; screenRect.r_xtop = ExposeEvent->x+ExposeEvent->width; screenRect.r_ytop = w->w_allArea.r_ytop-ExposeEvent->y; screenRect.r_ybot = w->w_allArea.r_ytop - (ExposeEvent->y + ExposeEvent->height); SigDisableInterrupts(); WindAreaChanged( w, &screenRect); WindUpdate(); SigEnableInterrupts(); } break; case ConfigureNotify: { XConfigureEvent *ConfigureEvent = (XConfigureEvent*) &xevent; Rect screenRect; MagWindow *w; grCurrent.window = ConfigureEvent->window; entry = HashLookOnly(&grX11WindowTable,grCurrent.window); w = (entry)?(MagWindow *)HashGetValue(entry):0; /* The line above is defintely NOT a good idea. w == 0 causes address exception. Why X11 is generating an event for a non-existent window is another question... ***mdg*** */ if(w == 0) {printf("ConfigureNotify: w = %d.\n", w); break;} grCurrent.mw=w; screenRect.r_xbot = ConfigureEvent->x; screenRect.r_xtop = ConfigureEvent->x+ ConfigureEvent->width; screenRect.r_ytop = grXsToMagic(ConfigureEvent->y); screenRect.r_ybot = grXsToMagic(ConfigureEvent->y+ ConfigureEvent->height); /* Configure events do not seem to require complete window repaint. */ SigDisableInterrupts(); WindReframe(w,&screenRect,FALSE,FALSE); WindUpdate(w); SigEnableInterrupts(); } default: break; } } /*--------------------------------------------------------- * x11suSetDisplay: * This routine sets the appropriate parameters so that * Magic will work with the X display. * * Under Xlib, all input events (mouse and keyboard) are * sent to one queue which has to be polled to discover * whether there is any input or not. To fit the Magic * interrupt-driven input model, a helper process is * spawned which reads and blocks on the event queue, * sending SIGIO's to Magic when it detects input. The * input read in the helper process is then sent to Magic * via a communication pipe. * * Results: success / fail * * Side Effects: Sets up the pipe. *--------------------------------------------------------- */ bool x11suSetDisplay (dispType, outFileName, mouseFileName) char *dispType; /* arguments not used by X */ char *outFileName; char *mouseFileName; { int fildes[2],fildes2[2]; char readPipeN[60], writePipeN[60], SemName[60], x11commandl[200]; char *tmp; int rc, parentID; ULONG BytesRead; struct _AVAILDATA BytesAvail; ULONG PipeState; char *planecount; char *fullname; FILE* f; bool execFailed = false; WindPackageType = WIND_X_WINDOWS; grCursorType = "bw"; if ((int)strlen(dispType) > 5) /* 5 == strlen("XWIND") */ { planecount = dispType+5; grXuserPC = atoi(planecount); } WindScrollBarWidth = 14; /* OS/2 setup of x11helper requires: Setup OS/2 style pipes. Start x11helper by: system() call. Provide arguments to x11helper so that it can open pipes at client end. Required arguments are: server process ID and pipe names. */ strcpy(SemName, "\\SEM32\\MagicS"); tmp = strrchr(tmpnam(NULL), '\\'); tmp++; strcat(SemName, tmp); rc = pipe(fildes, readPipeN, writePipeN); if (rc != 0) { printf("Pipe create failed: %d\n", rc); exit(-1); } parentID = getpid(); /* For production use insert /C and maybe /MIN after start below */ sprintf(x11commandl, "start /C /MIN \"Magic X11helper\" x11helper.exe \"%d %d %d\" %s %s %s", fildes[0], fildes[1], parentID, readPipeN, writePipeN, SemName); rc = system(x11commandl); if ( rc != 0) {printf("system call to start x11helper failed: %d\n", rc); exit(-1);} DosCreateEventSem(SemName, &hevXhandle, 0, FALSE); rc = DosConnectNPipe( fildes[0]); /* Waits for DosOpen from client! */ rc = DosConnectNPipe( fildes[1]); pipeRead = fildes[0]; pipeWrite = fildes[1]; rc = DosPeekNPipe(pipeRead, &Xhelper, sizeof(Xhelper), &BytesRead, &BytesAvail, &PipeState); while(BytesAvail.cbpipe < sizeof(Xhelper)) {DosSleep(1L); rc = DosPeekNPipe(pipeRead, &Xhelper, sizeof(Xhelper), &BytesRead, &BytesAvail, &PipeState); } rc = _read(pipeRead, (char *)&Xhelper, sizeof(Xhelper)); printf("X11helper PID received: %d\n", Xhelper); TxAdd1InputDevice(pipeRead, grX11Stdin, (ClientData) NULL); /* Set up the procedure values in the indirection table. */ GrLockPtr = GrX11Lock; GrUnlockPtr = GrX11Unlock; GrInitPtr = GrX11Init; GrClosePtr = GrX11Close; GrSetCMapPtr = GrX11SetCMap; GrEnableTabletPtr = GrX11EnableTablet; GrDisableTabletPtr = GrX11DisableTablet; GrSetCursorPtr = GrX11SetCursor; GrTextSizePtr = GrX11TextSize; GrDrawGlyphPtr = GrX11DrawGlyph; GrReadPixelPtr = GrX11ReadPixel; GrFlushPtr = GrX11Flush; GrCreateWindowPtr = GrX11Create; GrDeleteWindowPtr = GrX11Delete; GrConfigureWindowPtr = GrX11Configure; GrOverWindowPtr = GrX11Raise; GrUnderWindowPtr = GrX11Lower; GrUpdateIconPtr = GrX11IconUpdate; /* local indirections */ grSetSPatternPtr = grx11SetSPattern; grPutTextPtr = grx11PutText; grDefineCursorPtr = grx11DefineCursor; GrBitBltPtr = GrX11BitBlt; grDrawGridPtr = grx11DrawGrid; grDrawLinePtr = grx11DrawLine; grSetWMandCPtr = grx11SetWMandC; grFillRectPtr = grx11FillRect; grSetStipplePtr = grx11SetStipple; grSetLineStylePtr = grx11SetLineStyle; grSetCharSizePtr = grx11SetCharSize; grMaxStipples = 32; #ifdef NONMANHATTAN grFillPolygonPtr = grx11FillPolygon; #endif if (execFailed) { TxError("Execution failed!\n"); return false; } TxAdd1InputDevice(fileno(stdin), grXWStdin, (ClientData) NULL); if(!GrX11Init()){ return false; }; GrScreenRect.r_xtop = DisplayWidth(grXdpy,grXscrn); GrScreenRect.r_ytop = DisplayHeight(grXdpy,grXscrn); return true; } /* * ---------------------------------------------------------------------------- * * grXWStdin -- * Handle the stdin device for X window interface. * * Results: * None. * * Side Effects: * Adds events to the event queue. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ Void grXWStdin(fd, cdata) int fd; ClientData cdata; { int ch; TxInputEvent *event; if(_kbhit()) { ch = _getch(); event = TxNewEvent(); if (ch == 0xd){ ch = 0xa; printf("\n"); fflush(stdout); } } else { return;} if (ch == EOF) event->txe_button = TX_EOF; else event->txe_button = TX_CHARACTER; event->txe_ch = ch; event->txe_buttonAction = 0; event->txe_wid = WIND_NO_WINDOW; event->txe_p.p_x = GR_CURSOR_X; event->txe_p.p_y = GR_CURSOR_Y; TxAddEvent(event); } /* This separate thread scans for input -- non-blocking */ void _Optlink Input_monitor(void *arg) { XEvent xevent; int rc, pass = 0; ULONG BytesRead; struct _AVAILDATA BytesAvail; ULONG PipeState; while (true) { DosSleep(8L); /* time in ms */ if (_kbhit() ) { sigOnInterrupt(); } if(grXdpy != NULL) { rc = DosPeekNPipe(pipeRead, &xevent, sizeof(XEvent), &BytesRead, &BytesAvail, &PipeState); if(BytesAvail.cbpipe >= sizeof(XEvent)) { /* printf("bytes %d size %d\n", BytesAvail.cbpipe, sizeof(XEvent)); */ /* The reason for the test below for queued input is to better handle the double button sequence when the button is on the borders (indicating scrolling or zoom). It is not good to set sigInterruptPending on the button release. */ if((pass >= 1) && (BytesAvail.cbpipe > sizeof(XEvent))) { sigOnInterrupt(); pass = 0; } else pass++;} else pass = 0; } } } /* * ---------------------------------------------------------------------------- * * GrX11Create -- * Create a new window under the X window system. * Bind X window to Magic Window w. * * Results: * Window created, window ID send to Xhelper. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ static int firstWindow = 1; GrX11Create(w) MagWindow *w; { Window wind; Window w_focus; int revert_to; XSizeHints *xsh; HashEntry *entry; char *windowplace; char *option = (firstWindow == 1)?"window":"newwindow"; int k; XGCValues grvalues; int x = w->w_frameArea.r_xbot; int y = grMagicToXs(w->w_frameArea.r_ytop); unsigned int width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; unsigned int height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; unsigned long event_mask = SubstructureNotifyMask; Bool propagate = 0; XEvent opn_event; int sentr; unsigned long attribmask = CWBackPixel | CWBorderPixel | CWColormap; XSetWindowAttributes grAttributes; int grDepth; WindSeparateRedisplay(w); xsh = XAllocSizeHints(); /* ASSERT(xsh!=0, "failed XAllocSizeHints"); */ if (windowplace=XGetDefault(grXdpy,"magic",option)) { XParseGeometry(windowplace,&x,&y, (unsigned int *)&width,(unsigned int *)&height); w->w_frameArea.r_xbot = x; w->w_frameArea.r_xtop = x+width; w->w_frameArea.r_ytop = grXsToMagic(y); w->w_frameArea.r_ybot = grXsToMagic(y+height); WindReframe(w,&(w->w_frameArea),FALSE,FALSE); xsh->flags = USPosition | USSize; } else { xsh->flags = PPosition|PSize; } #ifdef HIRES grAttributes.background_pixel = WhitePixel(grXdpy,grXscrn); grAttributes.border_pixel = BlackPixel(grXdpy,grXscrn); grAttributes.colormap = grXcmap; grDepth = grCurrent.depth; if(grClass == 3) grDepth = 8; /* Needed since grCurrent.depth is reset to 7 if Pseudocolor */ #ifdef HIRESDB TxPrintf("x %d y %d width %d height %d depth %d class %d mask %d\n", x,y,width,height, grDepth, grClass, attribmask); #endif /* HIRESDB */ if ( wind = XCreateWindow(grXdpy, XDefaultRootWindow(grXdpy), x, y, width, height, 0, grDepth, InputOutput, grVisual, attribmask, &grAttributes)) #else if ( wind = XCreateSimpleWindow(grXdpy, XDefaultRootWindow(grXdpy), x,y,width,height,0, BlackPixel(grXdpy,grXscrn), WhitePixel(grXdpy,grXscrn))) #endif /* HIRES */ { #ifdef sun /* Hint's for Sun's implementation of X11 (News/X11) */ { XWMHints wmhints; wmhints.flags = InputHint; wmhints.input = True; XSetWMHints(grXdpy, wind, &wmhints); } #endif sun /* * Signal xhelper to poll window. */ grCurrent.window = wind; /* * Define window cursor and complete initialization. */ xsh->x = w->w_frameArea.r_xbot; xsh->y = grMagicToXs(w->w_frameArea.r_ytop); xsh->width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; xsh->height= w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; XSetStandardProperties(grXdpy, wind, "magic", "magic", None, 0, 0, xsh); #ifndef HIRES XSetWindowColormap(grXdpy,grCurrent.window,grXcmap); #endif /* HIRES */ XMapWindow(grXdpy, grCurrent.window); XSync(grXdpy,0); XFree(xsh); /* Prevents termination when a window is deleted via the window-manager */ (void) XSetWMProtocols(grXdpy, grCurrent.window, &wm_delete_window, 1); if (firstWindow == 1) { grGCFill = XCreateGC(grXdpy, grCurrent.window, 0, 0); grGCDraw = XCreateGC(grXdpy, grCurrent.window, 0, 0); grGCText = XCreateGC(grXdpy, grCurrent.window, 0, 0); grGCCopy = XCreateGC(grXdpy, grCurrent.window, 0, 0); grGCGlyph = XCreateGC(grXdpy, grCurrent.window, 0, 0); } XSetPlaneMask(grXdpy,grGCGlyph,AllPlanes); grCurrent.window = wind; grCurrent.mw = w; w->w_grdata = (ClientData) wind; entry = HashFind(&grX11WindowTable,grCurrent.window); HashSetValue(entry,w); XDefineCursor(grXdpy, grCurrent.window,grCurrent.cursor); GrX11IconUpdate(w,w->w_caption); XSync(grXdpy,0); _write( pipeWrite, (char *) &wind, sizeof(Window)); DosPostEventSem(hevXhandle); event_mask = ExposureMask|SubstructureNotifyMask|StructureNotifyMask; opn_event.type = CreateNotify; if (firstWindow != 1){ /* This may look like a kludge, but it was the only way I could find to get XSendEvent to send an event that x11helper would see before the window that is currently being created had been processed in x11helper. */ XLowerWindow(grXdpy, wind); XGetInputFocus(grXdpy, &w_focus, &revert_to); sentr = XSendEvent(grXdpy, w_focus, propagate, event_mask, &opn_event); } firstWindow++; DosQueryEventSem(hevXhandle, &pPostcnt); while (pPostcnt) { DosQueryEventSem(hevXhandle, &pPostcnt); DosSleep(10L); } XRaiseWindow(grXdpy, wind); /* XSync(grXdpy, 0); */ /* printf("Create call completed.\n"); */ return 1; } else TxError("Could not open new X window\n"); return 0; } /* * ---------------------------------------------------------------------------- * * GrXDelete -- * Destroy an X window. * * Results: * Window destroyed. * * * ---------------------------------------------------------------------------- */ GrX11Delete(w) MagWindow *w; { Window xw; HashEntry *entry; if(firstWindow == 2) return; xw = (Window) w->w_grdata; entry = HashLookOnly(&grX11WindowTable,xw); HashSetValue(entry,NULL); XDestroyWindow(grXdpy,xw); firstWindow--; } /* * ---------------------------------------------------------------------------- * * GrXConfigure -- * Resize/ Move an existing X window. * * Results: * Window reconfigured to w->w_frameArea. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ GrX11Configure(w) MagWindow *w; { XMoveResizeWindow(grXdpy,(Window) w->w_grdata, w->w_frameArea.r_xbot, grMagicToXs(w->w_frameArea.r_ytop), w->w_frameArea.r_xtop - w->w_frameArea.r_xbot, w->w_frameArea.r_ytop - w->w_frameArea.r_ybot); } /* * ---------------------------------------------------------------------------- * * GrXRaise -- * Raise a window to the top of the screen such that nothing * obscures it. * * Results: * Window raised. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ GrX11Raise(w) MagWindow *w; { XRaiseWindow(grXdpy, (Window) w->w_grdata ); } /* * ---------------------------------------------------------------------------- * * GrXLower -- * Lower a window below all other X windows. * obscures it. * * Results: * Window lowered. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ GrX11Lower(w) MagWindow *w; { XLowerWindow(grXdpy, (Window) w->w_grdata ); } /* * ---------------------------------------------------------------------------- * * GrX11Lock -- * Lock a window and set global variables "grCurrent.window" * and "grCurrent.mw" to reference the locked window. * * Results: * Window locked. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ GrX11Lock(w, flag) MagWindow *w; bool flag; { grSimpleLock(w, flag); if ( w != (MagWindow *) GR_LOCK_SCREEN ) { grCurrent.mw = w; grCurrent.window = (Window) w->w_grdata; } } /* * ---------------------------------------------------------------------------- * * GrX11Unlock -- * Unlock a window, flushing stuff out to the display. * * Results: * Window unlocked. * * Side Effects: * Display update. * * ---------------------------------------------------------------------------- */ GrX11Unlock(w) MagWindow *w; { GR_X_FLUSH_BATCH(); grSimpleUnlock(w); } /* *------------------------------------------------------------------------- * * GrX11IconUpdate -- updates the icon text with the window script * * Results: none * * Side Effects: changes the icon text * *------------------------------------------------------------------------- */ Void GrX11IconUpdate(w,text) MagWindow *w; char *text; { Window wind = (Window)(w->w_grdata); XClassHint class; char *brack; if (w->w_grdata == NULL) return; class.res_name = "magic"; class.res_class = "magic"; XSetClassHint( grXdpy, wind, &class); if (brack = index(text,'[')) { brack--; *brack = 0; XSetIconName(grXdpy,wind,text); XStoreName(grXdpy,wind,text); *brack = ' '; return; } if (brack = rindex(text,' ')) text = brack+1; XSetIconName(grXdpy,wind,text); XStoreName(grXdpy,wind,text); }