home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / evbl0627.zip / everblue_20010627.zip / x11 / Xlib_private.c < prev    next >
C/C++ Source or Header  |  2001-03-09  |  29KB  |  971 lines

  1.  
  2. #include "Xlib_private.h"
  3.  
  4. #ifndef RGB_DB
  5. #define RGB_DB            "/XFree86/lib/X11/rgb"
  6. #endif
  7.  
  8. int _Xdebug = 0;
  9.  
  10. int xinitialized = 0;
  11. int wndcount = 0;
  12. int auto_repeat = 1;
  13. PID mypid = 0;
  14.  
  15. XErrorHandler _XErrorFunction = NULL;
  16. XIOErrorHandler _XIOErrorFunction = NULL;
  17. void * _qfree = NULL;
  18. Display * _XHeadOfDisplayList = NULL;
  19.  
  20. Display * maindisplay = NULL;
  21.  
  22. char *rgbPath = RGB_DB;
  23. volatile int Xlib_DebugOffset = 0;
  24.  
  25. USHORT GXtoMixMode[16]    = {
  26.     FM_ZERO,    /* GXclear */
  27.     FM_AND,        /* GXand */
  28.     FM_MASKSRCNOT,    /* GXandReverse */
  29.     FM_OVERPAINT,    /* GXcopy */
  30.     FM_SUBTRACT,    /* GXandInverted */
  31.     FM_LEAVEALONE,    /* GXnoop */
  32.     FM_XOR,        /* GXxor */
  33.     FM_OR,        /* GXor */
  34.     FM_NOTMERGESRC,    /* GXnor */
  35.     FM_NOTXORSRC,    /* GXequiv */
  36.     FM_INVERT,    /* GXinvert */
  37.     FM_MERGESRCNOT,    /* GXorReverse */
  38.     FM_NOTCOPYSRC,    /* GXcopyInverted */
  39.     FM_MERGENOTSRC,    /* GXorInverted */
  40.     FM_NOTMASKSRC,    /* GXnand */
  41.     FM_ONE,        /* GXset */
  42. };
  43.  
  44. USHORT GXtoROPMode[16]    = {
  45.     ROP_ZERO,    /* GXclear */
  46.     ROP_SRCAND,    /* GXand */
  47.     ROP_SRCERASE,    /* GXandReverse */
  48.     ROP_SRCCOPY,    /* GXcopy */
  49.     0x0022,        /* GXandInverted */
  50.     0x00aa,        /* GXnoop */
  51.     0x0066,        /* GXxor */
  52.     ROP_SRCPAINT,    /* GXor */
  53.     ROP_NOTSRCERASE,/* GXnor */
  54.     0x0099,        /* GXequiv */
  55.     ROP_DSTINVERT,    /* GXinvert */
  56.     0x00dd,        /* GXorReverse */
  57.     ROP_NOTSRCCOPY,    /* GXcopyInverted */
  58.     ROP_MERGEPAINT,    /* GXorInverted */
  59.     0x0077,        /* GXnand */
  60.     ROP_ONE,    /* GXset */
  61. };
  62.  
  63. USHORT LineStyletoLineType[3] = {
  64.     LINETYPE_SOLID,        /* LineSolid */
  65.     LINETYPE_SHORTDASH,    /* LineOnOffDash */
  66.     LINETYPE_LONGDASH,    /* LineDoubleDash */
  67. };
  68.  
  69. USHORT CapStyletoLineEnd[4] = {
  70.     LINEEND_FLAT,        /* CapNotLast */
  71.     LINEEND_FLAT,        /* CapButt */
  72.     LINEEND_ROUND,        /* CapRound */
  73.     LINEEND_SQUARE,        /* CapProjecting */
  74. };
  75.  
  76. USHORT JoinStyletoLineJoin[3] = {
  77.     LINEJOIN_MITRE,        /* JoinMiter */
  78.     LINEJOIN_ROUND,        /* JoinRound */
  79.     LINEJOIN_BEVEL,        /* JoinBevel */
  80. };
  81.  
  82.  
  83. #if defined(__DATE__) && defined(__TIME__)
  84. static const char Xlib_built[] = __DATE__ " " __TIME__;
  85. #else
  86. static const char Xlib_built[] = "unknown";
  87. #endif
  88.  
  89. #ifdef DEBUG
  90. int Xlib_DebugEnter(char* name,int lnum,char* proc, char* info)
  91. {
  92.     int DebugLevel = ++Xlib_DebugOffset;
  93.     Xlib_DebugInfo[DebugLevel].filename = name;
  94.     Xlib_DebugInfo[DebugLevel].linenumb = lnum;
  95.     Xlib_DebugInfo[DebugLevel].procname = proc;
  96.     Xlib_DebugInfo[DebugLevel].procinfo = info;
  97.     return DebugLevel;
  98. }
  99. #endif
  100.  
  101. /* We are getting lots of crashes while in this function,
  102.  * however the crashes are occuring in thread 2 (PM).
  103.  * Brian */
  104. XWindowAttributes *GetWinAttrib(Drawable w, HPS *hps)
  105. {
  106.     DBUG_ENTER("GetWinAttrib")
  107.     WinAttribData *winattrib = NULL;
  108.     if (hps) *hps = NULLHANDLE;
  109.     if (!w) DBUG_RETURN(NULL);
  110.         DBUG_POINT("WinIsWindow()");
  111.     if (WinIsWindow(mainhab,(HWND)w)) {
  112.         char winclass[32];
  113.                 PID pid;
  114.                 if (!WinQueryWindowProcess((HWND)w,&pid,NULL) || pid != mypid)
  115.                     DBUG_RETURN(NULL);
  116.         winclass[WinQueryClassName((HWND)w, sizeof(winclass), winclass)] = 0;
  117.         if (strcmp(winclass,"XPMChild") == 0)
  118.             winattrib = WinQueryWindowPtr((HWND)w,QWP_WINATTRIB);
  119.         if (winattrib) {
  120.                     if (hps) *hps = winattrib->hps;
  121.                         DBUG_RETURN(&winattrib->winattrib);
  122.         }
  123.         }
  124.     /* it is a Pixmap, so no WinAttrib data! */
  125.     DBUG_RETURN(NULL);
  126. }
  127.  
  128. int Xlib_SetFont(Pixmap, Font);
  129. int Xlib_SetStipple(Pixmap, Pixmap);
  130.  
  131. int RestoreGCValues(HPS hps, XGCValues *oldvalues, XGCValues *newvalues)
  132. {
  133.     if (!hps || !newvalues) return FALSE;
  134.     if (!oldvalues || oldvalues->function != newvalues->function) {
  135.         GpiSetMix(hps, GXtoMixMode[newvalues->function]);
  136.         GpiSetBackMix(hps, GXtoMixMode[newvalues->function]);
  137.     }
  138.     if (!oldvalues || oldvalues->foreground != newvalues->foreground) 
  139.         GpiSetColor(hps,newvalues->foreground);
  140.     if (!oldvalues || oldvalues->background != newvalues->background) 
  141.         GpiSetBackColor(hps,newvalues->background);
  142.     if (!oldvalues || oldvalues->line_style != newvalues->line_style) 
  143.         GpiSetLineType(hps,LineStyletoLineType[newvalues->line_style]);
  144.     if (!oldvalues || oldvalues->cap_style != newvalues->cap_style) 
  145.         GpiSetLineEnd(hps,CapStyletoLineEnd[newvalues->cap_style]);
  146.     if (!oldvalues || oldvalues->join_style != newvalues->join_style) 
  147.         GpiSetLineJoin(hps,JoinStyletoLineJoin[newvalues->join_style]);
  148.     if (!oldvalues || oldvalues->line_width != newvalues->line_width) 
  149.         GpiSetLineWidthGeom(hps,newvalues->line_width);
  150.     return TRUE;
  151. }
  152.  
  153. int GetDrawableHeight(Drawable d, GC gc, HPS *hps, int pathtype)
  154. {
  155.     long height, width;
  156.     DBUG_ENTER("GetDrawableHeight");
  157.     Xlib_GetDrawableInfo(d, gc, hps, pathtype, &width, &height);
  158.     DBUG_RETURN(height);
  159. }
  160.  
  161. void Xlib_GetDrawableInfo(Drawable d, GC gc, HPS *hps, int pathtype, long *width, long *height)
  162. {
  163.         DBUG_ENTER("Xlib_GetDrawableInfo")
  164.         *height = *width = 0L;
  165.     /*printf("[");*/
  166.     if (d == (Drawable)0L) {
  167.         Xlib_GC *newgc = (Xlib_GC *)gc;
  168.         HDC hdc;
  169.         /*printf("z");*/
  170.                 if (!gc) DBUG_VOID_RETURN;
  171.         if ((hdc = GpiQueryDevice(*hps = (HPS)newgc->gid))) {
  172.             /*printf("d");*/
  173.             DevQueryCaps(hdc, CAPS_HEIGHT, 1L, height);
  174.             DevQueryCaps(hdc, CAPS_WIDTH, 1L, width);
  175.             RestoreGCValues((HPS)newgc->gid, NULL, &newgc->values);
  176.             if (newgc->values.font) {
  177.                 Xlib_Font *font = (Xlib_Font *)newgc->values.font;
  178.                 GpiCreateLogFont((HPS)newgc->gid,NULL,1,&font->fattrs);
  179.                 GpiSetCharSet((HPS)newgc->gid,1);
  180.                 if (font->psmode)
  181.                 GpiSetCharBox((HPS)newgc->gid, &font->sizef);
  182.             }
  183.                         if (*height < 0) *height = 0;
  184.                         if (*width < 0) *width = 0;
  185.         }
  186.         DBUG_VOID_RETURN;
  187.     } else
  188.     if (WinIsWindow(mainhab, (HWND)d)) {
  189.         char winclass[32];
  190.         RECTL rectl;
  191.         HDC hdc;
  192.         PID pid;
  193.         winclass[WinQueryClassName((HWND)d, sizeof(winclass), winclass)] = 0;
  194.         if (WinQueryWindowProcess((HWND)d,&pid,NULL) && pid == mypid &&
  195.             strcmp(winclass,"XPMChild") == 0) {
  196.             WinAttribData *winattrib = WinQueryWindowPtr((HWND)d, QWP_WINATTRIB);
  197.             Xlib_GC *newgc = (Xlib_GC *)(gc?gc:winattrib->currentGC);
  198.             /*printf("x");*/
  199.             /*if (!winattrib) printf("?");*/
  200.             *hps = winattrib->hps;
  201.             if (winattrib->currentGC != gc) {
  202.                 Xlib_GC *oldgc = (Xlib_GC *)(winattrib->currentGC);
  203.                 int prevpath = GC_NOPATH;
  204.                 if (pathtype == GC_NOPATH && oldgc) pathtype = oldgc->path;
  205.                 if (oldgc && pathtype != (prevpath = oldgc->path))
  206.                     XFlushGC(maindisplay,(GC)oldgc);
  207.                 if (newgc && newgc->path != GC_NOPATH)
  208.                     XFlushGC(maindisplay,(GC)newgc);
  209.                 if (oldgc) {
  210.                     GpiQueryCurrentPosition((HPS)oldgc->gid, &oldgc->cp);
  211.                     oldgc->path = GC_NOPATH;
  212.                 }
  213.                 RestoreGCValues(*hps, (oldgc)?&oldgc->values:NULL, 
  214.                               (newgc)?&newgc->values:NULL );
  215.                 if (newgc) {
  216.                     SIZEL sizl;
  217.                     /*printf("(");*/
  218.                     if ((GpiQueryPS((HPS)newgc->gid, &sizl) & GPIT_MICRO) == 0)
  219.                         GpiDestroyPS((HPS)newgc->gid);
  220.                     if (newgc->winattrib && newgc->winattrib->currentGC == gc)
  221.                         newgc->winattrib->currentGC = (GC)0L;
  222.                     if (newgc->pixmap && newgc->pixmap->currentGC == gc)
  223.                         newgc->pixmap->currentGC = (GC)0L;
  224.                     newgc->gid = *hps;
  225.                     newgc->path = pathtype;
  226.                     newgc->winattrib = winattrib; winattrib->currentGC = gc;
  227.                     newgc->pixmap = NULL;
  228.                     Xlib_SetFont((Pixmap)winattrib, newgc->values.font);
  229.                     Xlib_SetStipple((Pixmap)winattrib, newgc->values.stipple);
  230.                     GpiMove(*hps, &newgc->cp);
  231.                     if (pathtype != GC_NOPATH && prevpath != pathtype) 
  232.                         GpiBeginPath(*hps, 1L);
  233.                     /*printf(")");*/
  234.                 }
  235.             } else 
  236.             if (newgc) {
  237.                 if (newgc->path != GC_NOPATH && newgc->path != pathtype)
  238.                     XFlushGC(maindisplay, gc);
  239.                 Xlib_SetFont((Pixmap)winattrib, newgc->values.font);
  240.                 Xlib_SetStipple((Pixmap)winattrib, newgc->values.stipple);
  241.                 switch (pathtype) {
  242.                 case GC_AREAFILL:
  243.                     GpiBeginArea(*hps, BA_BOUNDARY | 
  244.                         (newgc->values.fill_rule == WindingRule ?
  245.                          BA_WINDING : BA_ALTERNATE ));
  246.                     newgc->path = GC_AREAFILL;
  247.                     break;
  248.                 case GC_STROKEPATH:
  249.                 case GC_FILLPATH:
  250.                     GpiBeginPath(*hps, 1L);
  251.                     newgc->path = pathtype;
  252.                 }
  253.             }
  254.             /*printf("]");*/
  255.             /*if (!gc) return 0;*/
  256.                         *height = winattrib->winattrib.height;
  257.                         *width = winattrib->winattrib.width;
  258.                         DBUG_VOID_RETURN;
  259.         }
  260.         if (WinQueryWindowRect((HWND)d, &rectl)) {
  261.             HDC newhdc = gc?WinQueryWindowDC((HWND)d):NULLHANDLE;
  262.             Xlib_GC *newgc = (Xlib_GC *)gc;
  263.             hdc = gc?GpiQueryDevice((HPS)newgc->gid):NULLHANDLE;
  264.             /*printf("w");*/
  265.             if (!hdc || !newhdc) {
  266.                             /*printf("!]");*/
  267.                             *height = *width = 0;
  268.                             DBUG_VOID_RETURN;
  269.             }
  270.             if (newhdc != hdc) {
  271.                 XFlushGC(maindisplay,gc);
  272.                 if (hdc)
  273.                 if (!GpiAssociate((HPS)newgc->gid, NULLHANDLE)) {
  274.                     SIZEL sizl = {0,0};
  275.                     (HPS)newgc->gid = GpiCreatePS( mainhab, NULLHANDLE, &sizl,
  276.                         PU_PELS | GPIT_NORMAL );
  277.                     GpiCreateLogColorTable((HPS)newgc->gid, 0, LCOLF_RGB, 0, 0, NULL );
  278.                 }
  279.                                 if (!GpiAssociate((HPS)newgc->gid, newhdc))
  280.                                 {
  281.                                     *height = *width = 0;
  282.                                     DBUG_VOID_RETURN;
  283.                                 }
  284.                 RestoreGCValues((HPS)newgc->gid, NULL, &newgc->values);
  285.                 GpiSetCurrentPosition(*hps, &newgc->cp);
  286.             }
  287.             *hps = (HPS)newgc->gid;
  288.             if (newgc->winattrib && newgc->winattrib->currentGC == gc)
  289.                 newgc->winattrib->currentGC = (GC)0L;
  290.             if (newgc->pixmap && newgc->pixmap->currentGC == gc)
  291.                 newgc->pixmap->currentGC = (GC)0L;
  292.             newgc->gid = *hps;
  293.             newgc->path = pathtype;
  294.             newgc->winattrib = NULL; newgc->pixmap = NULL;
  295.             if (newgc->values.font) {
  296.                 Xlib_Font *font = (Xlib_Font *)newgc->values.font;
  297.                 GpiCreateLogFont((HPS)newgc->gid,NULL,1,&font->fattrs);
  298.                 GpiSetCharSet((HPS)newgc->gid,1);
  299.                 if (font->psmode)
  300.                 GpiSetCharBox((HPS)newgc->gid, &font->sizef);
  301.             }
  302.             if (pathtype != GC_NOPATH) GpiBeginPath(*hps, 1L);
  303.             /*printf("]");*/
  304.                         *height = rectl.yTop - rectl.yBottom;
  305.                         *width = rectl.xRight - rectl.xLeft;
  306.                         DBUG_VOID_RETURN;
  307.         }
  308.         /* rely on current GC data... */
  309.         if ((hdc = GpiQueryDevice(*hps = (HPS)((Xlib_GC *)gc)->gid))) {
  310.             Xlib_GC *newgc = (Xlib_GC *)gc;
  311.             /*printf("d");*/
  312.             DevQueryCaps(hdc, CAPS_HEIGHT, 1L, height);
  313.             DevQueryCaps(hdc, CAPS_WIDTH, 1L, width);
  314.             RestoreGCValues((HPS)newgc->gid, NULL, &newgc->values);
  315.                         if (*height < 0) *height = 0;
  316.                         if (*width < 0) *width = 0;
  317.                         DBUG_VOID_RETURN;
  318.         }
  319.                 /*printf("n]");*/
  320.                 *height = *width = 0;
  321.         DBUG_VOID_RETURN;
  322.     }
  323.     /*printf("p");*/
  324.     /* assume it is a Pixmap, cross fingers! */
  325.     {
  326.         Xlib_Pixmap *pixmap = (Xlib_Pixmap *)d;
  327.         Xlib_GC *newgc = (Xlib_GC *)(gc?gc:pixmap->currentGC);
  328.         Xlib_GC *oldgc = (Xlib_GC *)pixmap->currentGC;
  329.                 *hps = pixmap->hps;
  330.         if (oldgc != newgc) {
  331.             int prevpath = GC_NOPATH;
  332.             if (pathtype == GC_NOPATH && oldgc) pathtype = oldgc->path;
  333.             if (oldgc && pathtype != (prevpath = oldgc->path))
  334.                 XFlushGC(maindisplay,(GC)oldgc);
  335.             if (newgc && newgc->path != GC_NOPATH)
  336.                 XFlushGC(maindisplay,(GC)newgc);
  337.             if (oldgc) {
  338.                 GpiQueryCurrentPosition((HPS)oldgc->gid, &oldgc->cp);
  339.                 oldgc->path = GC_NOPATH;
  340.             }
  341.             RestoreGCValues(*hps, (oldgc)?&oldgc->values:NULL, 
  342.                           (newgc)?&newgc->values:NULL );
  343.             if (newgc) {
  344.                 SIZEL sizl;
  345.                 if ((GpiQueryPS((HPS)newgc->gid, &sizl) & GPIT_MICRO) == 0)
  346.                     GpiDestroyPS((HPS)newgc->gid);
  347.                 if (newgc->winattrib && newgc->winattrib->currentGC == gc)
  348.                     newgc->winattrib->currentGC = (GC)0L;
  349.                 if (newgc->pixmap && newgc->pixmap->currentGC == gc)
  350.                     newgc->pixmap->currentGC = (GC)0L;
  351.                 newgc->gid = *hps;
  352.                 newgc->path = pathtype;
  353.                 newgc->winattrib = NULL; 
  354.                 newgc->pixmap = pixmap; pixmap->currentGC = gc;
  355.                 Xlib_SetFont((Pixmap)pixmap, newgc->values.font);
  356.                 Xlib_SetStipple((Pixmap)pixmap, newgc->values.stipple);
  357.                 GpiMove(*hps, &newgc->cp);
  358.                 if (pathtype != GC_NOPATH && prevpath != pathtype) 
  359.                     GpiBeginPath(*hps, 1L);
  360.             }
  361.         } else 
  362.         if (newgc) {
  363.             if (newgc->path != GC_NOPATH && newgc->path != pathtype)
  364.                 XFlushGC(maindisplay, gc);
  365.             Xlib_SetFont((Pixmap)pixmap, newgc->values.font);
  366.             Xlib_SetStipple((Pixmap)pixmap, newgc->values.stipple);
  367.             switch (pathtype) {
  368.             case GC_AREAFILL:
  369.                 GpiBeginArea(*hps, BA_BOUNDARY | 
  370.                     (newgc->values.fill_rule == WindingRule ?
  371.                      BA_WINDING : BA_ALTERNATE ));
  372.                 newgc->path = GC_AREAFILL;
  373.                 break;
  374.             case GC_STROKEPATH:
  375.             case GC_FILLPATH:
  376.                 GpiBeginPath(*hps, 1L);
  377.                 newgc->path = pathtype;
  378.             }
  379.         }
  380.         /*printf("]");*/
  381.                 /*if (!gc) return 0;*/
  382.                 *height = pixmap->height;
  383.                 *width = pixmap->width;
  384.         DBUG_VOID_RETURN;
  385.     }
  386. }
  387.  
  388. void Xlib_buildmark(char *mark, int len)
  389. {
  390.     strncpy(mark, Xlib_built, len);
  391. }
  392.  
  393. XEvent *Xlib_NewEvent(void)
  394. {
  395.     Xlib_EventQueue *newq;
  396.  
  397.     /* Add event to the bottom of the list */
  398.     pthread_mutex_lock(&evmutex);
  399.     newq = malloc(sizeof(Xlib_EventQueue));
  400.     newq->next = NULL;
  401.     if(EventQueue == NULL)
  402.         EventQueue = newq;
  403.     else
  404.     {
  405.         Xlib_EventQueue *tmp;
  406.  
  407.         tmp = EventQueue;
  408.         while(tmp->next != NULL)
  409.             tmp = tmp->next;
  410.         tmp->next = newq;
  411.     }
  412.     pthread_mutex_unlock(&evmutex);
  413.     return &(newq->event);
  414. }
  415.  
  416. void Xlib_RemoveEvent(XEvent *ev)
  417. {
  418.     Xlib_EventQueue *prev = NULL, *tmp = EventQueue;
  419.  
  420.     pthread_mutex_lock(&evmutex);
  421.     while(tmp != NULL)
  422.     {
  423.         if(&(tmp->event) == ev)
  424.         {
  425.             if(prev) 
  426.                 prev->next = tmp->next;
  427.             else
  428.                 EventQueue = tmp->next;
  429.             free(tmp);
  430.             pthread_mutex_unlock(&evmutex);
  431.             return;
  432.         }
  433.         prev = tmp;
  434.         tmp=tmp->next;
  435.     }
  436.     pthread_mutex_unlock(&evmutex);
  437.     return;
  438. }
  439.  
  440. /* This is here because functions often times generate an event, 
  441.  * so I figured it would be nice to be able to have a function to
  442.  * send an Event and beable to specify if it was "send_event" or
  443.  * not for convenience. Brian Smith.
  444.  */
  445. Status Xlib_SendEvent(Display *display, Window w, Bool propagate, 
  446.                   long event_mask, XEvent *event_send, Bool send_event)
  447. {
  448.     DBUG_ENTER("Xlib_SendEvent")
  449.     XEvent *new;
  450.  
  451.     /* Need to look into how the event mask should be
  452.        handled here. */
  453.  
  454.         pthread_mutex_lock(&evmutex);
  455.         new = Xlib_NewEvent();
  456.     memcpy(new, event_send, sizeof(XEvent));
  457.     /* Does serial get incremented in sent events? */
  458.     new->xany.serial = 0;
  459.     new->xany.send_event = send_event;
  460.     new->xany.display = display;
  461.     new->xany.window = w;
  462.     display->qlen++;
  463.     write(pmout[1], (char *) &new, sizeof(void *));
  464.     pthread_mutex_unlock(&evmutex);
  465.     DBUG_RETURN(True);
  466. }
  467.  
  468. #define POLLFD_CACHE_SIZE 5
  469.  
  470. /* initialize the struct array passed to poll() below */
  471. Bool _XPollfdCacheInit(dpy)
  472.     Display *dpy;
  473. {
  474. #ifdef USE_POLL
  475.     struct pollfd *pfp;
  476.  
  477.     pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
  478.     if (!pfp)
  479.     return False;
  480.     pfp[0].fd = dpy->fd;
  481.     pfp[0].events = POLLIN;
  482.  
  483.     dpy->filedes = (XPointer)pfp;
  484. #endif
  485.     return True;
  486. }
  487.  
  488. void _XPollfdCacheAdd(dpy, fd)
  489.     Display *dpy;
  490.     int fd;
  491. {
  492. #ifdef USE_POLL
  493.     struct pollfd *pfp = (struct pollfd *)dpy->filedes;
  494.  
  495.     if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
  496.     pfp[dpy->im_fd_length].fd = fd;
  497.     pfp[dpy->im_fd_length].events = POLLIN;
  498.     }
  499. #endif
  500. }
  501.  
  502. /* ARGSUSED */
  503. void _XPollfdCacheDel(dpy, fd)
  504.     Display *dpy;
  505.     int fd;            /* not used */
  506. {
  507. #ifdef USE_POLL
  508.     struct pollfd *pfp = (struct pollfd *)dpy->filedes;
  509.     struct _XConnectionInfo *conni;
  510.  
  511.     /* just recalculate whole list */
  512.     if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
  513.     int loc = 1;
  514.     for (conni = dpy->im_fd_info; conni; conni=conni->next) {
  515.         pfp[loc].fd = conni->fd;
  516.         pfp[loc].events = POLLIN;
  517.         loc++;
  518.     }
  519.     }
  520. #endif
  521. }
  522.  
  523.  
  524. /*
  525.  * This routine can be used to (cheaply) get some memory within a single
  526.  * Xlib routine for scratch space.  A single buffer is reused each time
  527.  * if possible.  To be MT safe, you can only call this between a call to
  528.  * GetReq* and a call to Data* or _XSend*, or in a context when the thread
  529.  * is guaranteed to not unlock the display.
  530.  */
  531. char *_XAllocScratch (dpy, nbytes)
  532.     register Display *dpy;
  533.     unsigned long nbytes;
  534. {
  535.     DBUG_ENTER("_XAllocScratch")
  536.     if (nbytes > dpy->scratch_length) {
  537.         if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
  538.         if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
  539.         dpy->scratch_length = nbytes;
  540.         else dpy->scratch_length = 0;
  541.     }
  542.     DBUG_RETURN(dpy->scratch_buffer);
  543. }
  544. /*
  545.  * Scratch space allocator you can call any time, multiple times, and be
  546.  * MT safe, but you must hand the buffer back with _XFreeTemp.
  547.  */
  548. char *_XAllocTemp (dpy, nbytes)
  549.     register Display *dpy;
  550.     unsigned long nbytes;
  551. {
  552.     DBUG_ENTER("_XAllocTemp")
  553.     char *buf;
  554.     buf = _XAllocScratch(dpy, nbytes);
  555.     dpy->scratch_buffer = NULL;
  556.     dpy->scratch_length = 0;
  557.     DBUG_RETURN(buf);
  558. }
  559. void _XFreeTemp (dpy, buf, nbytes)
  560.     register Display *dpy;
  561.     char *buf;
  562.     unsigned long nbytes;
  563. {
  564.     DBUG_ENTER("_XFreeTemp")
  565.     if (dpy->scratch_buffer)
  566.     Xfree(dpy->scratch_buffer);
  567.     dpy->scratch_buffer = buf;
  568.     dpy->scratch_length = nbytes;
  569.     DBUG_VOID_RETURN;
  570. }
  571.  
  572. /* _XRegisterInternalConnection
  573.  * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
  574.  * include in its select/poll mask must call this function to register the
  575.  * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
  576.  * will also be called.
  577.  *
  578.  * Whenever Xlib detects input available on fd, it will call callback
  579.  * with call_data to process it.  If non-Xlib code calls select/poll
  580.  * and detects input available, it must call XProcessInternalConnection,
  581.  * which will call the associated callback.
  582.  *
  583.  * Non-Xlib code can learn about these additional fds by calling
  584.  * XInternalConnectionNumbers or, more typically, by registering
  585.  * a XConnectionWatchProc with XAddConnectionWatch
  586.  * to be called when fds are registered or unregistered.
  587.  *
  588.  * Returns True if registration succeeded, False if not, typically
  589.  * because could not allocate memory.
  590.  * Assumes Display locked when called.
  591.  */
  592. #if NeedFunctionPrototypes
  593. Status _XRegisterInternalConnection(
  594.     Display* dpy,
  595.     int fd,
  596.     _XInternalConnectionProc callback,
  597.     XPointer call_data
  598. )
  599. #else
  600. Status
  601. _XRegisterInternalConnection(dpy, fd, callback, call_data)
  602.     Display *dpy;
  603.     int fd;
  604.     _XInternalConnectionProc callback;
  605.     XPointer call_data;
  606. #endif
  607. {
  608.     DBUG_ENTER("_XRegisterInternalConnection")
  609.     struct _XConnectionInfo *new_conni, **iptr;
  610.     struct _XConnWatchInfo *watchers;
  611.     XPointer *wd;
  612.  
  613.     new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
  614.     if (!new_conni)
  615.     DBUG_RETURN(0);
  616.     new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
  617.     if (!new_conni->watch_data) {
  618.     Xfree(new_conni);
  619.     DBUG_RETURN(0);
  620.     }
  621.     new_conni->fd = fd;
  622.     new_conni->read_callback = callback;
  623.     new_conni->call_data = call_data;
  624.     new_conni->next = NULL;
  625.     /* link new structure onto end of list */
  626.     for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
  627.     ;
  628.     *iptr = new_conni;
  629.     dpy->im_fd_length++;
  630.     _XPollfdCacheAdd(dpy, fd);
  631.  
  632.     for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
  633.      watchers;
  634.      watchers=watchers->next, wd++) {
  635.     *wd = NULL;        /* for cleanliness */
  636.     (*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
  637.     }
  638.  
  639.     DBUG_RETURN(1);
  640. }
  641.  
  642. /* _XUnregisterInternalConnection
  643.  * Each IM (or Xlib extension) that closes a file descriptor previously
  644.  * registered with _XRegisterInternalConnection must call this function.
  645.  * Any XConnectionWatchProc registered by XAddConnectionWatch
  646.  * will also be called.
  647.  *
  648.  * Assumes Display locked when called.
  649.  */
  650. #if NeedFunctionPrototypes
  651. void _XUnregisterInternalConnection(
  652.     Display* dpy,
  653.     int fd
  654. )
  655. #else
  656. void
  657. _XUnregisterInternalConnection(dpy, fd)
  658.     Display *dpy;
  659.     int fd;
  660. #endif
  661. {
  662.     DBUG_ENTER("_XUnregisterInternalConnection")
  663.     struct _XConnectionInfo *info_list, **prev;
  664.     struct _XConnWatchInfo *watch;
  665.     XPointer *wd;
  666.  
  667.     for (prev = &dpy->im_fd_info; (info_list = *prev); prev = &info_list->next) {
  668.     if (info_list->fd == fd) {
  669.         *prev = info_list->next;
  670.         dpy->im_fd_length--;
  671.         for (watch=dpy->conn_watchers, wd=info_list->watch_data;
  672.          watch;
  673.          watch=watch->next, wd++) {
  674.         (*watch->fn) (dpy, watch->client_data, fd, False, wd);
  675.         }
  676.         if (info_list->watch_data)
  677.         Xfree (info_list->watch_data);
  678.         Xfree (info_list);
  679.         break;
  680.     }
  681.     }
  682.     _XPollfdCacheDel(dpy, fd);
  683.     DBUG_VOID_RETURN;
  684. }
  685.  
  686. /* XInternalConnectionNumbers
  687.  * Returns an array of fds and an array of corresponding call data.
  688.  * Typically a XConnectionWatchProc registered with XAddConnectionWatch
  689.  * will be used instead of this function to discover
  690.  * additional fds to include in the select/poll mask.
  691.  *
  692.  * The list is allocated with Xmalloc and should be freed by the caller
  693.  * with Xfree;
  694.  */
  695. #if NeedFunctionPrototypes
  696. Status XInternalConnectionNumbers(
  697.     Display *dpy,
  698.     int **fd_return,
  699.     int *count_return
  700. )
  701. #else
  702. Status
  703. XInternalConnectionNumbers(dpy, fd_return, count_return)
  704.     Display *dpy;
  705.     int **fd_return;
  706.     int *count_return;
  707. #endif
  708. {
  709.     DBUG_ENTER("XInternalConnectionNumbers")
  710.     int count;
  711.     struct _XConnectionInfo *info_list;
  712.     int *fd_list;
  713.  
  714.     LockDisplay(dpy);
  715.     count = 0;
  716.     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
  717.     count++;
  718.     fd_list = (int*) Xmalloc (count * sizeof(int));
  719.     if (!fd_list) {
  720.     UnlockDisplay(dpy);
  721.     DBUG_RETURN(0);
  722.     }
  723.     count = 0;
  724.     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
  725.     fd_list[count] = info_list->fd;
  726.     count++;
  727.     }
  728.     UnlockDisplay(dpy);
  729.  
  730.     *fd_return = fd_list;
  731.     *count_return = count;
  732.     DBUG_RETURN(1);
  733. }
  734.  
  735. static void _XProcessInternalConnection(dpy, conn_info)
  736.     Display *dpy;
  737.     struct _XConnectionInfo *conn_info;
  738. {
  739.     DBUG_ENTER("_XProcessInternalConnection")
  740.     /*dpy->flags |= XlibDisplayProcConni;*/
  741. #ifdef XTHREADS
  742.     if (dpy->lock) {
  743.     /* check cache to avoid call to thread_self */
  744.     if (xthread_have_id(dpy->lock->reading_thread))
  745.         dpy->lock->conni_thread = dpy->lock->reading_thread;
  746.     else
  747.         dpy->lock->conni_thread = XThread_Self();
  748.     }
  749. #endif /* XTHREADS */
  750.     UnlockDisplay(dpy);
  751.     (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
  752.     LockDisplay(dpy);
  753. #ifdef XTHREADS
  754.     if (dpy->lock)
  755.     xthread_clear_id(dpy->lock->conni_thread);
  756. #endif /* XTHREADS */
  757.     /*dpy->flags &= ~XlibDisplayProcConni;*/
  758.     DBUG_VOID_RETURN;
  759. }
  760.  
  761. /* XProcessInternalConnection
  762.  * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
  763.  * for this fd.
  764.  * The Display is NOT locked during the call.
  765.  */
  766. #if NeedFunctionPrototypes
  767. void XProcessInternalConnection(
  768.     Display* dpy,
  769.     int fd
  770. )
  771. #else
  772. void
  773. XProcessInternalConnection(dpy, fd)
  774.     Display *dpy;
  775.     int fd;
  776. #endif
  777. {
  778.     DBUG_ENTER("XProcessInternalConnection")
  779.     struct _XConnectionInfo *info_list;
  780.  
  781.     LockDisplay(dpy);
  782.     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
  783.     if (info_list->fd == fd) {
  784.         _XProcessInternalConnection(dpy, info_list);
  785.         break;
  786.     }
  787.     }
  788.     UnlockDisplay(dpy);
  789.     DBUG_VOID_RETURN;
  790. }
  791.  
  792. /* XAddConnectionWatch
  793.  * Register a callback to be called whenever _XRegisterInternalConnection
  794.  * or _XUnregisterInternalConnection is called.
  795.  * Callbacks are called with the Display locked.
  796.  * If any connections are already registered, the callback is immediately
  797.  * called for each of them.
  798.  */
  799. #if NeedFunctionPrototypes
  800. Status XAddConnectionWatch(
  801.     Display* dpy,
  802.     XConnectionWatchProc callback,
  803.     XPointer client_data
  804. )
  805. #else
  806. Status
  807. XAddConnectionWatch(dpy, callback, client_data)
  808.     Display *dpy;
  809.     XConnectionWatchProc callback;
  810.     XPointer client_data;
  811. #endif
  812. {
  813.     DBUG_ENTER("XAddConnectionWatch")
  814.     struct _XConnWatchInfo *new_watcher, **wptr;
  815.     struct _XConnectionInfo *info_list;
  816.     XPointer *wd_array;
  817.  
  818.     LockDisplay(dpy);
  819.  
  820.     /* allocate new watch data */
  821.     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
  822.     wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
  823.                     (dpy->watcher_count + 1) *
  824.                     sizeof(XPointer));
  825.     if (!wd_array) {
  826.         UnlockDisplay(dpy);
  827.         DBUG_RETURN(0);
  828.     }
  829.     wd_array[dpy->watcher_count] = NULL;    /* for cleanliness */
  830.     }
  831.  
  832.     new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
  833.     if (!new_watcher) {
  834.     UnlockDisplay(dpy);
  835.     DBUG_RETURN(0);
  836.     }
  837.     new_watcher->fn = callback;
  838.     new_watcher->client_data = client_data;
  839.     new_watcher->next = NULL;
  840.  
  841.     /* link new structure onto end of list */
  842.     for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
  843.     ;
  844.     *wptr = new_watcher;
  845.     dpy->watcher_count++;
  846.  
  847.     /* call new watcher on all currently registered fds */
  848.     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
  849.     (*callback) (dpy, client_data, info_list->fd, True,
  850.              info_list->watch_data + dpy->watcher_count - 1);
  851.     }
  852.  
  853.     UnlockDisplay(dpy);
  854.     DBUG_RETURN(1);
  855. }
  856.  
  857. /* XRemoveConnectionWatch
  858.  * Unregister a callback registered by XAddConnectionWatch.
  859.  * Both callback and client_data must match what was passed to
  860.  * XAddConnectionWatch.
  861.  */ 
  862. #if NeedFunctionPrototypes
  863. void XRemoveConnectionWatch(
  864.     Display* dpy,
  865.     XConnectionWatchProc callback,
  866.     XPointer client_data
  867. )
  868. #else
  869. void
  870. XRemoveConnectionWatch(dpy, callback, client_data)
  871.     Display *dpy;
  872.     XConnectionWatchProc callback;
  873.     XPointer client_data;
  874. #endif
  875. {
  876.     DBUG_ENTER("XRemoveConnectionWatch")
  877.     struct _XConnWatchInfo *watch;
  878.     struct _XConnWatchInfo *previous = NULL;
  879.     struct _XConnectionInfo *conni;
  880.     int counter = 0;
  881.  
  882.     LockDisplay(dpy);
  883.     for (watch=dpy->conn_watchers; watch; watch=watch->next) {
  884.     if (watch->fn == callback  &&  watch->client_data == client_data) {
  885.         if (previous)
  886.         previous->next = watch->next;
  887.         else
  888.         dpy->conn_watchers = watch->next;
  889.         Xfree (watch);
  890.         dpy->watcher_count--;
  891.         /* remove our watch_data for each connection */
  892.         for (conni=dpy->im_fd_info; conni; conni=conni->next) {
  893.         /* don't bother realloc'ing; these arrays are small anyway */
  894.         /* overlapping */
  895.         memmove(conni->watch_data+counter,
  896.             conni->watch_data+counter+1,
  897.             dpy->watcher_count - counter);
  898.         }
  899.         break;
  900.     }
  901.     previous = watch;
  902.     counter++;
  903.     }
  904.     UnlockDisplay(dpy);
  905.     DBUG_VOID_RETURN;
  906. }
  907.  
  908. /* end of internal connections support */
  909.  
  910. int XSync (dpy, discard)
  911.     register Display *dpy;
  912.     Bool discard;
  913. {
  914.     DBUG_ENTER("XSync")
  915.     QMSG qmsg;
  916.  
  917.     pthread_mutex_lock(&evmutex);
  918.     while (WinPeekMsg(mainhab, &qmsg, 0, 0, 0, PM_REMOVE))
  919.         WinDispatchMsg(mainhab, &qmsg);
  920.     pthread_mutex_unlock(&evmutex);
  921.     DBUG_RETURN(1);
  922. }
  923.  
  924. void Xlib_crash(int signal)
  925. {
  926.    extern HMODULE hk_module;
  927.    extern HAB pmctls_hab;
  928.  
  929.    x11_console_notice("SIGSEGV caught! Removing input queue hook.\n");
  930.    if(WinReleaseHook(pmctls_hab, NULLHANDLE, HK_INPUT, Xlib_InputQueueHook, hk_module)==FALSE)
  931.       x11_console_notice("Error removing the input hook!\n");
  932.    else
  933.    {
  934.        x11_console_notice("Xlib/PM successfully shutdown. (Xlib_crash)\n");
  935.        DosFreeModule(hk_module);
  936.    }
  937. }
  938.  
  939. void Xlib_SetGC(HPS hps, Xlib_GC *xgc)
  940. {
  941.     LONG alTable[18];
  942.  
  943.     GpiQueryLogColorTable(hps, 0L, 0L, 18L, alTable);
  944.  
  945.     alTable[16] = xgc->values.foreground;
  946.     alTable[17] = xgc->values.background;
  947.  
  948.     GpiCreateLogColorTable(hps,
  949.                            0L,
  950.                            LCOLF_CONSECRGB,
  951.                            0L,
  952.                            18,
  953.                            alTable);
  954.     GpiSetColor(hps, 16);
  955.     GpiSetBackColor(hps, 17);
  956.  
  957.     GpiSetMix(hps, GXtoMixMode[xgc->values.function]);
  958.     GpiSetBackMix(hps, GXtoMixMode[xgc->values.function]);
  959.  
  960.     GpiSetLineWidthGeom(hps, xgc->values.line_width);
  961.  
  962.     GpiSetLineType(hps, LineStyletoLineType[xgc->values.line_style]);
  963.  
  964.     GpiSetLineEnd(hps, CapStyletoLineEnd[xgc->values.cap_style]);
  965.  
  966.     GpiSetLineJoin(hps, JoinStyletoLineJoin[xgc->values.join_style]);
  967. }
  968.  
  969.  
  970.  
  971.