/* ---------------------------------------------------------------- * * cxt_main.c * * Project: C Xlib Toolkit * * Xlib - wrappers and convenience functions * * v0.01 1995-07-19 Christoph C. Birk, birk@mpia-hd.mpg.de * v1.00 1995 Sep. [CCB] * ..... * v1.31 1998 July getnanf(),getnand() [CCB] * * v2.00 1999 May general overhaul [CCB] * ..... * v2.20 2000-10-10 FreeMenu,TWindow [CCB] * * v3.00 2000-10-18 fully multi-threaded [CCB] * v3.01 2001-05-09 private colormap [CCB] * v3.02 2001-06-20 Listbox [CCB] * v3.03 2001-07-27 N_KEEP_COLORS [CCB] * v3.04 2001-12-06 AlignWithParent() [CCB] * v3.05 2002-02-08 CBX_CloseXlib(Bool) [CCB] * v3.06 2002-03-26 EditWindow.cpos [CCB] * * v4.00 2002-03-27 auto-managed windows / MainWindow [CCB] * modularization (cxt_.c) * 4.04 2003-01-23 auto version check * 4.05 -05-07 KillNotify,AutoLed * 4.06 2004-06-17 CBX_ClearAutoQueue(): fix 'Expose' events [CCB] * 4.064 CBX_ENFORCE * 4.065 CBX_Top_WindowExt() * 4.070 2015-02-02 handle WM close event [CCB] * 4.080 2016-12-08 CBX_CreateAutoOutput_Ext(),CBX_CreateAutoEdit_Ext() [CCB] * * http://tronche.com/gui/x/xlib/events/processing-overview.html * * ---------------------------------------------------------------- */ #define IS_CXTLIB_C /* DEFINEs -------------------------------------------------------- */ #ifndef DEBUG #define DEBUG 1 /* debug level */ #endif #define XDEBUG 0 #define CBX_DCLICK 200 #define CBX_BTIME 600 #ifdef LINUX #define N_KEEP_COLORS 32 #else #define N_KEEP_COLORS 16 #endif #define BSP ((char)8) #define DEL ((char)127) #define CR ((char)13) #define ESC ((char)27) #ifdef FONTSIZE #define PXh FONTSIZE #else #define PXh 14 /* default fontsize */ #endif #define PXw (10+(PXh-14)/2) #define XXh (PXh+4) #ifdef SOLARIS #ifndef SVR4 #define SVR4 #endif #endif #define PREFUN __func__ /* INCLUDEs ------------------------------------------------------- */ #define _REENTRANT #include #include /* fprintf(),stderr */ #include /* strlen(),memcpy() */ #include /* sqrt(),floor() */ #include /* getcwd() */ #include /* struct hostent */ #include #include #include #include "cxt.h" /* EXTERNs -------------------------------------------------------- */ #ifdef SOLARIS extern int gethostname(char*,int); #endif /* STATICs -------------------------------------------------------- */ static u_long black,white,grey,lgrey,red,green,blue,yellow; /* function prototype(s) */ static Status cbx_AllocStdColors (Application*); static int cbx_fatal_error_handler (Display*); static int cbx_error_handler (Display*,XErrorEvent*); static void cbx_GetXY (long,int*,int*,int,int,int); static Window cbx_create_pop (Menu*,int,int,int,int,u_long); static void cbx_draw_pop (Window,Menu*,char**,u_long); static int cbx_handle_pop (Window,Menu*,int,char**,u_long); static void cbx_remove_pop (Window,Menu*,char**); static char* cbx_extend(char*,char,int); /* GLOBALs -------------------------------------------------------- */ Application *cbx_app; /* global application */ /* function prototype(s) */ void cbx_msleep (int); int cbx_max (int,int); int cbx_min (int,int); void cbx_FillTextProperty (XTextProperty*,const char*); /* ---------------------------------------------------------------- */ int cbx_max(int x,int y) { if (x > y) return(x); return(y); } int cbx_min(int x,int y) { if (x < y) return(x); return(y); } /* ---------------------------------------------------------------- */ /* Xlib general */ /* ---------------------------------------------------------------- */ Application* CXT_OpenLib(char* name,u_int version) { Application *app; Display *disp; XColor c[N_KEEP_COLORS]; Colormap cmap; char *font; int i,screen; assert((version>>4)==(CXTLIB_VERSION>>4)); #if (DEBUG > 1) fprintf(stderr,"%s/v%x.%03x\n",__FILE__, CXTLIB_VERSION >> 12,CXTLIB_VERSION & 0x0fff); fprintf(stderr,"sizeof(u_long)=%lu\n",sizeof(u_long)); fprintf(stderr,"sizeof(XID)=%lu\n",sizeof(XID)); #endif cbx_app = app = (Application*)malloc(sizeof(Application)); if (app == NULL) return(NULL); #if (DEBUG > 1) fprintf(stderr,"%s(%s): app=%p\n",PREFUN,name,(void*)app); #endif (void)strcpy(app->xserver,name); /* store 'xserver' */ app->disp = disp = XOpenDisplay(name); /* connect to X-server */ #if (DEBUG > 1) fprintf(stderr,"%s(%s): disp=%p\n",PREFUN,name,(void*)disp); #endif if (disp == NULL) return(NULL); #if (XDEBUG > 0) XSynchronize(disp,True); #endif pthread_mutex_init(&(app->lock),NULL); /* initialize 'xlib' mutex */ app->rwin = DefaultRootWindow(disp); app->screen = screen = DefaultScreen(disp); app->cmap = cmap = DefaultColormap(disp,screen); app->vdepth = DefaultDepth(disp,screen); app->sw = DisplayWidth(disp,screen); app->sh = DisplayHeight(disp,screen); #if (DEBUG > 1) fprintf(stderr,"%s(%s): vdepth=%d, dw=%d, dh=%d\n",PREFUN,name, app->vdepth,app->sw,app->sh); #endif if (!cbx_AllocStdColors(app)) { /* allocate colors */ app->local_colormap = True; /* failed -> local colormap */ #if (DEBUG > 0) fprintf(stderr,"%s(): create local colormap\n",PREFUN); #endif app->cmap = cmap = XCopyColormapAndFree(disp,cmap); if (cmap == 0) { /* failed */ fprintf(stderr,"%s(): create local colormap failed\n",PREFUN); XCloseDisplay(disp); return(NULL); } for (i=0; ilocal_colormap = False; font = getenv("CBXFONT"); if (!font) font = "courier"; /* default font */ app->gfs = CBX_CreateGfC_Ext(disp,font,"bold",PXh); app->busy_cursor = XCreateFontCursor(disp,XC_watch); /* create cursors */ app->input_cursor = XCreateFontCursor(disp,XC_pencil); app->mw_list = (MainWindow**)malloc(sizeof(MainWindow*)); /* main window */ #if (DEBUG > 1) fprintf(stderr,"app->mw_list=%p\n",(void*)app->mw_list); #endif *(app->mw_list) = NULL; cxt_wmDeleteMessage = XInternAtom(disp,"WM_DELETE_WINDOW",False); (void)XSetErrorHandler(cbx_error_handler); /* default error handler(s) */ (void)XSetIOErrorHandler(cbx_fatal_error_handler); return(app); } /* ---------------------------------------------------------------- */ static Status cbx_AllocStdColors(Application* app) { Display *disp=app->disp; Colormap cmap=app->cmap; Status s; /* LINUX: /usr/X11R6/lib/X11/rgb.txt */ XColor xcol,ycol; /* SOLARIS: /usr/openwin/lib/rgb.txt */ #if (DEBUG > 1) fprintf(stderr,"%s(%p): disp=%p\n",PREFUN,app,disp); #endif /* required colors */ s = XAllocNamedColor(disp,cmap,"white",&xcol,&ycol); if (!s) return(s); app->white = white = xcol.pixel; s = XAllocNamedColor(disp,cmap,"black",&xcol,&ycol); if (!s) return(s); app->black = black = xcol.pixel; s = XAllocNamedColor(disp,cmap,"grey",&xcol,&ycol); if (!s) return(s); app->grey = grey = xcol.pixel; s = XAllocNamedColor(disp,cmap,"lightgrey",&xcol,&ycol); if (!s) return(s); app->lgrey = lgrey = xcol.pixel; s = XAllocNamedColor(disp,cmap,"red",&xcol,&ycol); if (!s) return(s); app->red = red = xcol.pixel; s = XAllocNamedColor(disp,cmap,"green",&xcol,&ycol); if (!s) return(s); app->green = green = xcol.pixel; s = XAllocNamedColor(disp,cmap,"blue",&xcol,&ycol); if (!s) return(s); app->blue = blue = xcol.pixel; s = XAllocNamedColor(disp,cmap,"yellow",&xcol,&ycol); if (!s) return(s); app->yellow = yellow = xcol.pixel; /* optional colors */ s = XAllocNamedColor(disp,cmap,"AntiqueWhite",&xcol,&ycol); if (app->vdepth > 8) { float f=0.95; /* darker */ xcol.red=(int)(xcol.red*f); xcol.green=(int)(xcol.green*f); xcol.blue=(int)(xcol.blue*f); s = XAllocColor(disp,cmap,&xcol); } if (!s) app->antique = app->white; else app->antique = xcol.pixel; s = XAllocNamedColor(disp,cmap,"beige",&xcol,&ycol); if (app->vdepth > 8) { float f=0.95; /* darker */ xcol.red=(int)(xcol.red*f); xcol.green=(int)(xcol.green*f); xcol.blue=(int)(xcol.blue*f); s = XAllocColor(disp,cmap,&xcol); } if (!s) app->beige = app->white; else app->beige = xcol.pixel; s = XAllocNamedColor(disp,cmap,"brown",&xcol,&ycol); if (!s) app->brown = app->grey; else app->brown = xcol.pixel; s = XAllocNamedColor(disp,cmap,"orange",&xcol,&ycol); if (!s) app->orange = app->brown; else app->orange = xcol.pixel; return((Status)1); } /* ---------------------------------------------------------------- */ void CXT_CloseLib(Bool free_colors) { Application *app=cbx_app; u_long pixels[32]; int npixels=0; if (free_colors) { pixels[npixels++] = app->grey; pixels[npixels++] = app->lgrey; pixels[npixels++] = app->red; pixels[npixels++] = app->green; pixels[npixels++] = app->blue; pixels[npixels++] = app->yellow; pixels[npixels++] = app->brown; pixels[npixels++] = app->orange; pixels[npixels++] = app->antique; pixels[npixels++] = app->beige; XFreeColors(app->disp,app->cmap,pixels,npixels,0); } if (app->local_colormap) XFreeColormap(app->disp,app->cmap); XCloseDisplay(app->disp); pthread_mutex_destroy(&(app->lock)); free((void*)app); } /* ----------------------------------------------------------------- */ static int cbx_fatal_error_handler(Display* disp) { fprintf(stderr,"cxtlib-v%x.%03x: fatal error-condition on X-Display=%p\n", CXTLIB_VERSION >> 12,CXTLIB_VERSION & 0x0fff,(void*)disp); exit(0); return(0); } /* ---------------------------------------------------------------- */ static int cbx_error_handler(Display* disp,XErrorEvent* ee) { char buffer[1024]; fprintf(stderr,"cbx_error_handler (v%x.%03x) on display=%p\n", CXTLIB_VERSION >> 12,CXTLIB_VERSION & 0x0fff,(void*)disp); fprintf(stderr,"\ttype=%d\n",ee->type); fprintf(stderr,"\tserial=%ld\n",ee->serial); fprintf(stderr,"\terror_code=%d\n",ee->error_code); fprintf(stderr,"\trequest_code=%d\n",ee->request_code); fprintf(stderr,"\tminor_code=%d\n",ee->minor_code); XGetErrorText(disp,ee->error_code,buffer,sizeof(buffer)); fprintf(stderr,"\terror_text=%s\n",buffer); return(0); } /* ---------------------------------------------------------------- */ void* CBX_SetFatalErrorHandler(XIOErrorHandler err_handler) { void* old_handler; (void)CBX_Lock(0); old_handler = (void*)XSetIOErrorHandler(err_handler); CBX_Unlock(); return(old_handler); } /* ---------------------------------------------------------------- */ Bool CBX_Lock(int timeout) { int st; if (timeout == 0) { /* no timeout -> blocking */ pthread_mutex_lock(&(cbx_app->lock)); return(True); } st = cbx_max(20,(int)sqrt((double)timeout)); while (pthread_mutex_trylock(&(cbx_app->lock))) { /* use timeout */ if (timeout > 0) cbx_msleep(st); timeout -= st; if (timeout < 0) return(False); } return(True); } /* ---------------------------------------------------------------- */ void CBX_Unlock(void) { pthread_mutex_unlock(&(cbx_app->lock)); } /* ---------------------------------------------------------------- */ /* MainWindow functions */ /* ---------------------------------------------------------------- */ Window CXT_OpenMainWindow(MainWindow* mw, /* v4.070 */ long pos,int w,int h,XSizeHints* hint, const char* title,const char* icon,Bool fixed) { Window win; win = CBX_OpenMainWindow(mw,pos,w,h,hint,title,icon,fixed); if (win) { /* request (close) event */ CXT_InterceptWMclose(mw->disp,win); } return win; } /* ---------------------------------------------------------------- */ Window CXT_OpenMainWindow_Ext(Display* disp,MainWindow* mw, /* v4.070 */ long pos,int w,int h,XSizeHints* hint, const char* title,const char* icon,Bool fixed) { Window win; win = CBX_OpenMainWindow_Ext(disp,mw,pos,w,h,hint,title,icon,fixed); if (win) { /* request (close) event */ CXT_InterceptWMclose(mw->disp,win); } return win; } /* ---------------------------------------------------------------- */ void CXT_InterceptWMclose(Display* disp,Window win) /* v4.070 */ { (void)CBX_Lock(0); XSetWMProtocols(disp,win,&cxt_wmDeleteMessage,1); CBX_Unlock(); } /* ---------------------------------------------------------------- */ Window CBX_OpenMainWindow(MainWindow* mw,long pos,int w,int h, XSizeHints* hint,const char* title,const char* icon, Bool fixed) { Display *disp; (void)CBX_Lock(0); disp = XOpenDisplay(cbx_app->xserver); /* connect to X-server */ CBX_Unlock(); if (disp == NULL) return(0); /* failed */ #if (XDEBUG > 0) XSynchronize(disp,True); #endif return CBX_OpenMainWindow_Ext(disp,mw,pos,w,h,hint,title,icon,fixed); } /* ---------------------------------------------------------------- */ Window CBX_OpenMainWindow_Ext(Display* disp,MainWindow* mw,long pos, int w,int h,XSizeHints* hint, const char* title,const char* icon,Bool fixed) { int x,y; mw->disp = disp; /* display */ mw->screen = cbx_app->screen; /* global screen */ mw->cmap = cbx_app->cmap; /* global colormap */ mw->gfs = cbx_app->gfs; /* gr. context and font */ mw->elist.olist = NULL; /* clear callback list(s) */ mw->elist.nlist = mw->elist.mlist = 0; pthread_mutex_init(&(mw->elist.lock),NULL); mw->blist.olist = NULL; /* clear callback list(s) */ mw->blist.nlist = mw->blist.mlist = 0; pthread_mutex_init(&(mw->blist.lock),NULL); mw->mlist.olist = NULL; /* clear callback list(s) */ mw->mlist.nlist = mw->mlist.mlist = 0; pthread_mutex_init(&(mw->mlist.lock),NULL); mw->llist.olist = NULL; /* clear callback list(s) */ mw->llist.nlist = mw->llist.mlist = 0; pthread_mutex_init(&(mw->llist.lock),NULL); mw->bg = cbx_app->grey; /* default background */ cbx_GetXY(pos,&x,&y,w,h,0); /* get (x,y) from 'pos */ #if (DEBUG > 1) fprintf(stderr,"%s(): rwin=%ld, x=%d, y=%d\n",PREFUN,cbx_app->rwin,x,y); #endif (void)CBX_Lock(0); mw->win = XCreateSimpleWindow(disp,cbx_app->rwin, x,y,w,h,2,black,mw->bg); if (cbx_app->local_colormap) XSetWindowColormap(disp,mw->win,cbx_app->cmap); CBX_Unlock(); hint->x = x; hint->y = y; /* setup window hints */ hint->width = w; hint->height = h; if (fixed) { hint->min_width = hint->max_width = w; hint->min_height = hint->max_height = h; hint->flags = PPosition | PSize | PMinSize | PMaxSize; } else { hint->flags = PPosition | PSize; } mw->w = w; mw->h = h; CBX_SetWMProperties_Ext(disp,mw->win,title,icon,hint); (void)CBX_Lock(0); if (fixed) XSelectInput(disp,mw->win,ExposureMask); /* default event mask */ else XSelectInput(disp,mw->win,ExposureMask | StructureNotifyMask); XMapRaised(disp,mw->win); { MainWindow **temp; int n=0; /* add 'mw' to list */ temp = cbx_app->mw_list; while (*temp != NULL) { n++; temp++; } temp = (MainWindow**)malloc((n+2)*sizeof(MainWindow*)); memcpy((void*)temp,(void*)cbx_app->mw_list,n*sizeof(MainWindow*)); *(temp+n) = mw; /* add new main window to list */ *(temp+n+1) = NULL; /* new terminator */ free((void*)cbx_app->mw_list); /* free old list */ cbx_app->mw_list = temp; /* set pointer to new list */ } #if (DEBUG > 1) { MainWindow **temp; int n=0; temp = cbx_app->mw_list; while (*temp != NULL) { fprintf(stderr,"mw_list[%d]=%p\n",n,(void*)*temp); temp++; n++; } } #endif CBX_Unlock(); return(mw->win); } /* ---------------------------------------------------------------- */ void CBX_CloseMainWindow(MainWindow* mw) { if (mw->disp == NULL) return; #if (DEBUG > 1) fprintf(stderr,"%s(%p): disp=%p\n",PREFUN,mw,(void*)mw->disp); #endif (void)CBX_Lock(0); XDestroyWindow(mw->disp,mw->win); if (mw->disp != cbx_app->disp) XCloseDisplay(mw->disp); mw->disp = NULL; CBX_Unlock(); CXT_RemoveMainWindow(mw); } /* ---------------------------------------------------------------- */ void CXT_RemoveMainWindow(MainWindow* mw) /* v4.070 */ { #if (DEBUG > 1) fprintf(stderr,"%s(%p): disp=%p\n",PREFUN,mw,(void*)mw->disp); #endif pthread_mutex_destroy(&(mw->elist.lock)); /* remove AutoEdit */ if (mw->elist.olist) free((void*)mw->elist.olist); pthread_mutex_destroy(&(mw->blist.lock)); /* remove AutoButton */ if (mw->blist.olist) free((void*)mw->blist.olist); pthread_mutex_destroy(&(mw->mlist.lock)); /* remove AutoMenu */ if (mw->mlist.olist) free((void*)mw->mlist.olist); pthread_mutex_destroy(&(mw->llist.lock)); /* remove AutoLed */ if (mw->llist.olist) free((void*)mw->llist.olist); (void)CBX_Lock(0); { MainWindow **temp; /* remove 'mw' from list */ temp = cbx_app->mw_list; while (*temp != mw) { temp++; } /* find pointer to 'mw' */ while (*temp != NULL) { /* copy list */ memcpy((void*)temp,(void*)(temp+1),sizeof(MainWindow*)); temp++; } } #if (DEBUG > 1) { MainWindow **temp; int n=0; temp = cbx_app->mw_list; while (*temp != NULL) { fprintf(stderr,"mw_list[%d]=%p\n",n,(void*)*temp); temp++; n++; } } #endif CBX_Unlock(); } /* --------------------------------------------------------------- */ void CBX_IconifyMainWindow(MainWindow* mw) { (void)CBX_Lock(0); XIconifyWindow(mw->disp,mw->win,mw->screen); XFlush(mw->disp); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_SetMainWindowBackground(MainWindow* mw,u_char r,u_char g,u_char b) { XColor col; col.red = 256*r; col.green = 256*g; col.blue = 256*b; (void)CBX_Lock(0); XAllocColor(cbx_app->disp,cbx_app->cmap,&col); mw->bg = col.pixel; XSetWindowBackground(mw->disp,mw->win,mw->bg); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_SelectInput(MainWindow* mw,long mask) { CBX_SelectInput_Ext(mw->disp,mw->win,mask); } /* ---------------------------------------------------------------- */ void CBX_SelectInput_Ext(Display* disp,Window win,long mask) { (void)CBX_Lock(0); XSelectInput(disp,win,mask); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_SetMainWindowHints(MainWindow* mw,XSizeHints *hint, int wmin,int wmax,int hmin,int hmax) { hint->min_width = wmin; hint->max_width = wmax; hint->min_height = hmin; hint->max_height = hmax; hint->flags = PPosition | PSize | PMinSize | PMaxSize; (void)CBX_Lock(0); XSetWMNormalHints(mw->disp,mw->win,hint); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_SetMainWindowProperties(MainWindow* mw,const char* name, const char* icon,XSizeHints* hints) { CBX_SetWMProperties_Ext(mw->disp,mw->win,name,icon,hints); } /* ---------------------------------------------------------------- */ void cbx_FillTextProperty(XTextProperty* p,const char* text) { char *list[2]; list[0] = (char*)text; list[1] = NULL; (void)CBX_Lock(0); XStringListToTextProperty(list,1,p); /* convert string */ CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_SetWMProperties_Ext(Display* disp,Window win, const char* name,const char* icon, XSizeHints* hints) { XTextProperty tp; cbx_FillTextProperty(&tp,name); (void)CBX_Lock(0); XSetWMName(disp,win,&tp); XFree((void*)tp.value); CBX_Unlock(); cbx_FillTextProperty(&tp,icon); (void)CBX_Lock(0); XSetWMIconName(disp,win,&tp); XFree((void*)tp.value); XSetWMNormalHints(disp,win,hints); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_SetMainWindowName(MainWindow* mw ,const char* name) { XTextProperty tp; cbx_FillTextProperty(&tp,name); (void)CBX_Lock(0); XSetWMName(mw->disp,mw->win,&tp); XFree((void*)tp.value); CBX_Unlock(); } /* ---------------------------------------------------------------- */ #ifdef LINUX #define XOFF 6 #define YOFF 35 #define HOFF 35 #else #define XOFF 5 #define YOFF 25 #define HOFF 30 #endif static void cbx_GetXY(long position,int* x,int* y,int w,int h,int ds) { int sh,sw,x0,y0; if (3*cbx_app->sw > 4*cbx_app->sh) { /* wider that 4/3 */ sh = cbx_app->sh; sw = cbx_app->sw/2; x0 = ds*sw; y0 = 0; } else { /* regular screen */ sh = cbx_app->sh; sw = cbx_app->sw; x0 = 0; y0 = 0; } switch(position) { /* calculate window position */ case CBX_TOPLEFT: *x = x0; *y = y0; break; case CBX_TOPMID: *x = x0+(sw-w-2*XOFF)/2; *y = y0; break; case CBX_TOPRIGHT: *x = x0+sw-w-2*XOFF; *y = y0; break; case CBX_MIDLEFT: *x = x0; *y = y0+(sh-h-YOFF)/2; break; case CBX_CENTER: *x = x0+(sw-w-2*XOFF)/2; *y = y0+(sh-h-YOFF)/2; break; case CBX_MIDRIGHT: *x = x0+sw-w-2*XOFF; *y = y0+(sh-h-YOFF)/2; break; case CBX_BOTTOMLEFT: *x = x0; *y = y0+sh-h-HOFF; break; case CBX_BOTTOMMID: *x = x0+(sw-w-2*XOFF)/2; *y = y0+sh-h-HOFF; break; case CBX_BOTTOMRIGHT: *x = x0+sw-w-2*XOFF; *y = y0+sh-h-HOFF; break; default: *x = position % 32000; *y = position / 32000; break; } #if (DEBUG > 2) fprintf(stderr,"%s: cbx_GetXY(): x=%d, y=%d\n",__FILE__,*x,*y); #endif } #undef HOFF #undef YOFF #undef XOFF /* ---------------------------------------------------------------- */ long CBX_AlignWithParent(MainWindow* mw,int where,int w0,int h0) { int x0,y0; u_int n; Window r,parent,*c; XWindowAttributes xwa,xpa; (void)CBX_Lock(0); /* get screen geometry */ XGetWindowAttributes(mw->disp,mw->win,&xwa); /* get window and */ XQueryTree(mw->disp,mw->win,&r,&parent,&c,&n); XGetWindowAttributes(mw->disp,parent,&xpa); /* parent geometry */ XFree((void*)c); /* free list of children */ #ifdef LINUX XQueryTree(mw->disp,parent,&r,&parent,&c,&n); XGetWindowAttributes(mw->disp,parent,&xpa); /* parent geometry */ XFree((void*)c); /* free list of children */ #endif CBX_Unlock(); switch(where) { case CBX_ALIGNLEFT: x0 = xpa.x - 2*xwa.x - w0; y0 = xpa.y; /* default: top edge */ if (y0 + h0 > cbx_app->sh-(xpa.height-xwa.height)) { y0 = xpa.y+xpa.height-h0-(xpa.height-xwa.height); } break; case CBX_ALIGNRIGHT: #if (DEBUG > 1) fprintf(stderr,"xpa.x=%d, xpa.witdh=%d\n",xpa.x,xpa.width); #endif x0 = xpa.x + xpa.width; y0 = xpa.y; break; case CBX_ALIGNBOTTOM: x0 = xpa.x; /* default: left edge */ if (x0 + w0 > cbx_app->sw-(xpa.width-xwa.width)) { x0 = xpa.x+xpa.width-2*xwa.x-w0; } y0 = xpa.y + xpa.height; break; case CBX_ALIGNTOP: x0 = xpa.x; /* default: left edge */ if (x0 + w0 > cbx_app->sw-(xpa.width-xwa.width)) { x0 = xpa.x+xpa.width-2*xwa.x-w0; } y0 = xpa.y - (xpa.height-xwa.height) - h0; break; default: /* don't know what to do */ fprintf(stderr,"%s(): unknown alignment '%d'\n",PREFUN,where); return(CBX_TOPLEFT); /* upper left corner (0,0) */ } #if (DEBUG > 1) fprintf(stderr,"x0=%d, y=%d\n",x0,y0); #endif return(CBX_CalcPosition(x0,y0)); } /* ---------------------------------------------------------------- */ long CBX_AlignWithWindow(Window w,int where,int w0,int h0) { int x0,y0; u_int n; Window r,parent=w,*c; XWindowAttributes xwa,xpa; (void)CBX_Lock(0); /* get screen geometry */ XGetWindowAttributes(cbx_app->disp,w,&xwa); /* get window and */ do { w = parent; XQueryTree(cbx_app->disp,w,&r,&parent,&c,&n); XFree((void*)c); /* free list of children */ } while (parent != r); XGetWindowAttributes(cbx_app->disp,w,&xpa); /* parent geometry */ CBX_Unlock(); switch(where) { case CBX_ALIGNLEFT: x0 = xpa.x - 2*xwa.x - w0; y0 = xpa.y; /* default: top edge */ if (y0 + h0 > cbx_app->sh-(xpa.height-xwa.height)) { y0 = xpa.y+xpa.height-h0-(xpa.height-xwa.height); } break; case CBX_ALIGNRIGHT: x0 = xpa.x + xpa.width; y0 = xpa.y; break; case CBX_ALIGNBOTTOM: x0 = xpa.x; /* default: left edge */ if (x0 + w0 > cbx_app->sw-(xpa.width-xwa.width)) { x0 = xpa.x+xpa.width-2*xwa.x-w0; } y0 = xpa.y + xpa.height; break; case CBX_ALIGNTOP: x0 = xpa.x; /* default: left edge */ if (x0 + w0 > cbx_app->sw-(xpa.width-xwa.width)) { x0 = xpa.x+xpa.width-2*xwa.x-w0; } y0 = xpa.y - (xpa.height-xwa.height) - h0; break; default: /* don't know what to do */ fprintf(stderr,"%s(): unknown alignment '%d'\n",PREFUN,where); return(CBX_TOPLEFT); /* upper left corner (0,0) */ } #if (DEBUG > 1) fprintf(stderr,"x0=%d, y=%d\n",x0,y0); #endif return(CBX_CalcPosition(x0,y0)); } /* ---------------------------------------------------------------- */ long CBX_CalcPosition(int x,int y) { return((long)x+(long)32000*y); } /* ---------------------------------------------------------------- */ GfC CBX_CreateGfC(MainWindow* mw,const char* f_f,const char* f_w,int f_ps) { mw->gfs = CBX_CreateGfC_Ext(mw->disp,f_f,f_w,f_ps); return(mw->gfs); } /* ---------------------------------------------------------------- */ GfC CBX_CreateGfC_Ext(Display* disp,const char* f_f,const char* f_w,int f_ps) { GfC gfs; Font font; char fontname[128]; (void)CBX_Lock(0); gfs.gc = XCreateGC(disp,cbx_app->rwin,0,0); XSetForeground(disp,gfs.gc,BlackPixel(disp,DefaultScreen(disp))); XSetBackground(disp,gfs.gc,WhitePixel(disp,DefaultScreen(disp))); sprintf(fontname,"-*-%s-%s-r-*-*-%d-*-*-*-*-*-*-*",f_f,f_w,f_ps); font = XLoadFont(disp,fontname); XSetFont(disp,gfs.gc,font); gfs.f_struct = XQueryFont(disp,font); CBX_Unlock(); return(gfs); } /* ---------------------------------------------------------------- */ int CBX_TextWidth(MainWindow* mw,const char* text) { return(CBX_TextWidth_Ext(mw->gfs,text)); } /* ---------------------------------------------------------------- */ int CBX_TextWidth_Ext(GfC gfs,const char* text) { int w,len; len = strlen(text); if (len == 0) return(0); (void)CBX_Lock(0); w = XTextWidth(gfs.f_struct,(char*)text,len); CBX_Unlock(); return(w); } /* ---------------------------------------------------------------- */ int CBX_TextHeight(MainWindow* mw,const char* text) { return(CBX_TextHeight_Ext(mw->gfs,text)); } /* ---------------------------------------------------------------- */ int CBX_TextHeight_Ext(GfC gfs,const char* text) { int dr,far,fdr; XCharStruct ovr; (void)CBX_Lock(0); XTextExtents(gfs.f_struct,(char*)text,(int)strlen(text),&dr,&far,&fdr,&ovr); CBX_Unlock(); return(ovr.ascent+ovr.descent); } /* ---------------------------------------------------------------- */ void CBX_DrawString(MainWindow* mw,int x,int y,const char* text) { (void)CBX_Lock(0); XDrawString(mw->disp,mw->win,mw->gfs.gc,x,y,(char*)text,strlen(text)); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_DrawLine(MainWindow* mw,int x1,int y1,int x2,int y2) { (void)CBX_Lock(0); XDrawLine(mw->disp,mw->win,mw->gfs.gc,x1,y1,x2,y2); CBX_Unlock(); } /* ---------------------------------------------------------------- */ /* Button routines */ /* ---------------------------------------------------------------- */ int CBX_HandleButton(Button* b) { XEvent event; int flag; if (b->flag & CBX_DISABLED) return(CBX_DISABLED); if (b->flag & CBX_ACTIVE) return(CBX_ACTIVE); flag = b->flag; /* save flag */ CBX_PressButton(b); /* press button */ do { /* event loop */ (void)CBX_WaitWindowEvent_Ext(b->disp,b->win,CBX_ALL_EVENTS,50,&event); #if (DEBUG > 2) fprintf(stderr,"CBX_HandleButton(%p), event.type=%d, xbutton=%d\n", (void*)b,(int)event.type,(int)event.xbutton.button); #endif switch (event.type) { /* evaluate event.type */ case LeaveNotify: CBX_ReleaseButton(b); break; case EnterNotify: CBX_PressButton(b); break; } } while ((event.type != ButtonRelease) || (event.xbutton.button != 1)); if (!(b->flag & CBX_PRESSED)) b->flag = flag; /* restore flag */ return(b->flag); } /* ---------------------------------------------------------------- */ int CBX_HandleButton3(Button* b,int button) { XEvent event; if (b->flag & CBX_DISABLED) return(CBX_DISABLED); if (b->flag & CBX_ACTIVE) return(CBX_ACTIVE); CBX_PressButton(b); /* press button */ do { /* event loop */ (void)CBX_WaitWindowEvent_Ext(b->disp,b->win,CBX_ALL_EVENTS,50,&event); switch (event.type) { /* evaluate event.type */ case LeaveNotify: CBX_ReleaseButton(b); break; case EnterNotify: CBX_PressButton(b); break; } } while ((event.type != ButtonRelease) || (event.xbutton.button != button)); return(b->flag); } /* ---------------------------------------------------------------- */ void CBX_PressButton(Button* b) { b->flag |= CBX_PRESSED; CBX_UpdateButton(b); } /* ---------------------------------------------------------------- */ void CBX_ReleaseButton(Button* b) { b->flag &= ~CBX_PRESSED; CBX_UpdateButton(b); } /* ---------------------------------------------------------------- */ void CBX_BlinkButton(Button *b,int dt) { if ((b->flag & CBX_BLINKING) || (b->flag & CBX_STRONG_BLINK)) { if ((b->blink-=dt) <= 0) { b->flag ^= CBX_INVERTED; CBX_UpdateButton(b); b->blink = CBX_BTIME; } } } /* ---------------------------------------------------------------- */ void CBX_DisableButton(Button* b,int flag) { if (b->disp == NULL) return; CBX_ClearWindowQueue_Ext(b->disp,b->win); CBX_SelectInput_Ext(b->disp,b->win,None); b->flag = flag; CBX_UpdateButton(b); } /* ---------------------------------------------------------------- */ void CBX_EnableButton(Button* b) { if (b->disp == NULL) return; CBX_SelectInput_Ext(b->disp,b->win,ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask); b->flag = CBX_NORMAL; CBX_UpdateButton(b); } /* ---------------------------------------------------------------- */ void CBX_UpdateButton(Button* b) { Display *disp = b->disp; Window button = b->win; GC gc = b->gfs.gc; int w = b->w; int h = b->h; int flag = b->flag; char* text = b->text; int x,y=h-h/5-1,d=(h-2)/2; #if (DEBUG > 1) fprintf(stderr,"%s: CBX_UpdateButton(%p)\n",__FILE__,(void*)b); #endif if (b->mode & CBX_CENTERED) x = (w-CBX_TextWidth_Ext(b->gfs,text))/2-1; else x = 5; (void)CBX_Lock(0); /* lock Xlib */ if (flag & CBX_BLINKING) { /* blinking button */ if (flag & CBX_INVERTED) XSetForeground(disp,gc,red); else XSetForeground(disp,gc,b->fg); XSetWindowBackground(disp,button,b->bg); XClearWindow(disp,button); XDrawString(disp,button,gc,x,y,text,strlen(text)); if (flag & CBX_INVERTED) XSetForeground(disp,gc,b->fg); } else if (flag & CBX_STRONG_BLINK) { /* strong blinking */ if (flag & CBX_INVERTED) { XSetForeground(disp,gc,b->bg); XSetWindowBackground(disp,button,grey); } else { XSetForeground(disp,gc,b->fg); XSetWindowBackground(disp,button,b->bg); } XClearWindow(disp,button); XDrawString(disp,button,gc,x,y,text,strlen(text)); } else { switch (flag) { /* button status */ case CBX_PRESSED: /* pressed */ XSetForeground(disp,gc,b->bg); XSetWindowBackground(disp,button,lgrey); XClearWindow(disp,button); XDrawString(disp,button,gc,x,y,text,strlen(text)); break; case CBX_ACTIVE: /* active */ XSetForeground(disp,gc,b->fg); XSetWindowBackground(disp,button,yellow); XClearWindow(disp,button); XDrawString(disp,button,gc,x,y,text,strlen(text)); break; case CBX_DISABLED: /* disabled */ XSetForeground(disp,gc,b->fg); XSetWindowBackground(disp,button,lgrey); XClearWindow(disp,button); XDrawString(disp,button,gc,x,y,text,strlen(text)); break; case CBX_NORMAL: /* normal */ XSetForeground(disp,gc,b->fg); XSetWindowBackground(disp,button,b->bg); XClearWindow(disp,button); XDrawString(disp,button,gc,x,y,text,strlen(text)); break; default: fprintf(stderr,"WARNING: unknown flag in Button=%d\n",(int)button); break; } } XSetForeground(disp,gc,black); if (flag & CBX_PRESSED) { /* 3d effect */ XDrawLine(disp,button,gc,0,0,w-2,0); XDrawLine(disp,button,gc,0,0,0,h-2); XDrawLine(disp,button,gc,1,1,w-3,1); XDrawLine(disp,button,gc,1,1,1,h-3); } else { XDrawLine(disp,button,gc,1,h-1,w-1,h-1); XDrawLine(disp,button,gc,w-1,1,w-1,h); XDrawLine(disp,button,gc,2,h-2,w-2,h-2); XDrawLine(disp,button,gc,w-2,2,w-2,h); } switch (b->symbol) { case CBX_UP_TRI: /* up-ward triangle */ XDrawLine(disp,button,gc,w/2-1,3,3,h-5); XDrawLine(disp,button,gc,3,h-5,w-5,h-5); XDrawLine(disp,button,gc,w-5,h-5,w/2-1,3); break; case CBX_DN_TRI: /* down-ward triangle */ XDrawLine(disp,button,gc,w/2-1,h-5,3,3); XDrawLine(disp,button,gc,3,3,w-5,3); XDrawLine(disp,button,gc,w-5,3,w/2-1,h-5); break; case CBX_LT_TRI: /* left-ward triangle */ XDrawLine(disp,button,gc,3,h/2-1,w-5,3); XDrawLine(disp,button,gc,w-5,3,w-5,h-5); XDrawLine(disp,button,gc,w-5,h-5,3,h/2-1); break; case CBX_RT_TRI: /* right-ward triangle */ XDrawLine(disp,button,gc,w-5,h/2-1,3,h-5); XDrawLine(disp,button,gc,3,h-5,3,3); XDrawLine(disp,button,gc,3,3,w-5,h/2-1); break; case CBX_DOT: XDrawRectangle(disp,button,gc,w-2*d,(h-d)/2,d,d); /* redraw 'dot' */ if (b->status) { XSetForeground(disp,gc,b->color); /* fill color */ XFillRectangle(disp,button,gc,w-2*d+1,(h-d)/2+1,d-1,d-1); XSetForeground(disp,gc,black); XDrawLine(disp,button,gc,w-2*d,(h-d)/2,w-2*d+d-1,(h-d)/2+d-1); XDrawLine(disp,button,gc,w-2*d+d,(h-d)/2,w-2*d,(h-d)/2+d); } break; } CBX_Unlock(); } /* ---------------------------------------------------------------- */ /* Menu routines */ /* ---------------------------------------------------------------- */ void CBX_CheckMenu(Menu* m,int e,Bool check) { if (check) m->entry[e].flag |= CBX_CHECKED; else m->entry[e].flag &= ~CBX_CHECKED; } /* ---------------------------------------------------------------- */ static int cbx_handlepmenu(Menu*); /* pop-up menu */ static int cbx_handlefmenu(Menu*); /* free pop-up menu */ static int cbx_handledmenu(Menu*); /* drop-down menu */ int CBX_HandleMenu(Menu* menu) { int i; switch (menu->type) { case MENU_DROP: i = cbx_handledmenu(menu); break; case MENU_POPUP: i = cbx_handlepmenu(menu); break; case MENU_FREE: i = cbx_handlefmenu(menu); break; default: i = -1; break; } return(i); } /* ---------------------------------------------------------------- */ static int cbx_handlepmenu(Menu* menu) { MainWindow *mw=menu->mwin; Window pop; int maxlen=0; int i,pw,ph,px,py,x,y; char *text[64],buf[128]; text[0] = (char*)malloc(128*64*sizeof(char)); /* allocate text buffers */ pw = menu->w; /* get width of 'pop' */ for (i=0; in; i++) { /* find widest entry */ maxlen = cbx_max(maxlen,(int)strlen(menu->entry[i].text)); } for (i=0; in; i++) { strcpy(buf,menu->entry[i].text); if (menu->entry[i].flag & CBX_CHECKED) { cbx_extend(buf,' ',maxlen); strcat(buf," *"); } strcpy(text[i],buf); text[i+1] = text[i] + strlen(text[i])+1; pw = cbx_max(pw,(PXw/2)+CBX_TextWidth(mw,text[i])); } ph = menu->n*menu->h+2; CBX_GetRootPos(menu->win,&x,&y); /* get position */ px = x; py = y-cbx_max(menu->sel,-1)*menu->h; pop = cbx_create_pop(menu,px,py,pw,ph,menu->bg); /* create popup window */ cbx_draw_pop(pop,menu,text,menu->bg); /* fill-in menu text */ i = cbx_handle_pop(pop,menu,pw,text,menu->bg); cbx_remove_pop(pop,menu,text); /* free resources */ return(i); } /* ---------------------------------------------------------------- */ static int cbx_handlefmenu(Menu* menu) { Window pop,r,w; int i,pw,ph,px,py,x,y,rx,ry,wx,wy; int maxlen=0; u_int m; char *text[64],buf[128]; (void)CBX_Lock(0); XQueryPointer(menu->disp,menu->win,&r,&w,&rx,&ry,&wx,&wy,&m); CBX_Unlock(); text[0] = (char*)malloc(128*64*sizeof(char)); /* allocate text buffers */ pw = menu->w; /* get width of 'pop' */ for (i=0; in; i++) { /* find widest entry */ maxlen = cbx_max(maxlen,(int)strlen(menu->entry[i].text)); } for (i=0; in; i++) { strcpy(buf,menu->entry[i].text); if (menu->entry[i].flag & CBX_CHECKED) { cbx_extend(buf,' ',maxlen); strcat(buf," *"); } strcpy(text[i],buf); text[i+1] = text[i] + strlen(text[i])+1; pw = cbx_max(pw,(PXw/2)+CBX_TextWidth_Ext(menu->gfs,text[i])); } ph = menu->n*menu->h+2; CBX_GetRootPos(menu->win,&x,&y); px = rx-pw/2; py = (ry-cbx_max(menu->sel,-1)*menu->h)-menu->h/2; pop = cbx_create_pop(menu,px,py,pw,ph,cbx_app->beige); /* create window */ cbx_draw_pop(pop,menu,text,cbx_app->beige); /* menu text */ i = cbx_handle_pop(pop,menu,pw,text,cbx_app->beige); cbx_remove_pop(pop,menu,text); /* free resources */ return(i); } /* ---------------------------------------------------------------- */ static int cbx_handledmenu(Menu* menu) { Window pop; int i,wi=PXw,x,y,px,py,pw,ph,maxlen=0; char *text[64]; CBX_GetRootPos(menu->win,&x,&y); text[0] = (char*)malloc(128*64*sizeof(char)); /* allocate text buffers */ for (i=0; in; i++) { /* find widest entry */ maxlen = cbx_max(maxlen,(int)strlen(menu->entry[i].text)); } for (i=0; in; i++) { /* find widest entry */ (void)strcpy(text[i],menu->entry[i].text); switch(menu->entry[i].flag) { case CBX_SEPARATOR: /* separator entry */ cbx_extend(text[i],'-',maxlen); break; default: /* regular entry */ if (menu->entry[i].flag & CBX_CHECKED) { cbx_extend(text[i],' ',maxlen); strcat(text[i]," *"); } break; } text[i+1] = text[i] + strlen(text[i])+1; wi = cbx_max(wi,(PXw/2)+CBX_TextWidth_Ext(menu->gfs,text[i])); } px = x; py = y+menu->h+1; pw = wi+1; ph = menu->n*menu->h+2; pop = cbx_create_pop(menu,px,py,pw,ph,menu->bg); /* create window */ cbx_draw_pop(pop,menu,text,menu->bg); /* fill-in menu text */ i = cbx_handle_pop(pop,menu,pw,text,menu->bg); cbx_remove_pop(pop,menu,text); /* free resources */ return(i); } /* ---------------------------------------------------------------- */ static Window cbx_create_pop(Menu* menu,int px,int py,int pw,int ph,u_long bg) { int e; Window pop; XSetWindowAttributes xswa; Display *disp=menu->disp; (void)CBX_Lock(0); if (py < 0) { /* menu off screen ? */ XWarpPointer(disp,None,None,0,0,0,0,0,-py+1); py=1; } if ((e=py+ph-cbx_app->sh) > 0) { XWarpPointer(disp,None,None,0,0,0,0,0,-e-1); py-=e; } if (px < 0) { XWarpPointer(disp,None,None,0,0,0,0,-px,0); px=1; } if ((e=px+pw-cbx_app->sw) > 0) { XWarpPointer(disp,None,None,0,0,0,0,-e-1,0); px-=e; } pop = XCreateSimpleWindow(disp,cbx_app->rwin,px,py,pw,ph,1,black,bg); xswa.override_redirect=True; /* ignored by window manager */ XChangeWindowAttributes(disp,pop,CWOverrideRedirect,&xswa); XSelectInput(disp,pop,Button1MotionMask | ButtonReleaseMask); XMapRaised(disp,pop); (void)XGrabPointer(disp,pop,False,PointerMotionMask|ButtonReleaseMask, GrabModeAsync,GrabModeAsync, ((menu->type == MENU_DROP) ? None : pop), None,0); /* grab mouse-pointer */ CBX_Unlock(); return(pop); } /* ---------------------------------------------------------------- */ static void cbx_draw_pop(Window pop,Menu* menu,char** text,u_long bg) { int i,sel; Display *disp=menu->disp; GC gc=menu->gfs.gc; (void)CBX_Lock(0); sel = ((menu->type == MENU_DROP) ? menu->n : menu->sel); for (i=0; in; i++) { if (i == sel) { /* selected */ XSetForeground(disp,gc,bg); XSetBackground(disp,gc,black); } else if (menu->entry[i].flag & CBX_DISABLED) { /* disabled */ XSetForeground(disp,gc,grey); XSetBackground(disp,gc,bg); } else { /* normal */ XSetForeground(disp,gc,black); XSetBackground(disp,gc,bg); } XDrawImageString(disp,pop,gc,3,(i+1)*(menu->h)-4,text[i],strlen(text[i])); } XSetBackground(disp,gc,bg); XSync(disp,False); /* flush and wait*/ CBX_Unlock(); } /* ---------------------------------------------------------------- */ static int cbx_handle_pop(Window pop,Menu* menu,int pw,char** text,u_long bg) { int i,a,def,h=menu->h,n=menu->n; XEvent event; Display *disp=menu->disp; GC gc=menu->gfs.gc; a = def = ((menu->type == MENU_DROP) ? menu->n : menu->sel); do { (void)CBX_WaitEvent_Ext(disp,&event,50); if (event.type != MotionNotify) continue; i = (event.xmotion.y/h); if ((event.xmotion.y<0) || (event.xmotion.y>n*h)) i = def; /* default */ if ((event.xmotion.x<0) || (event.xmotion.x>pw)) i = def; if (i != a) { /* new selection */ if ((a < n) && (a > -1)) { /* restore */ (void)CBX_Lock(0); XSetBackground(disp,gc,bg); if (menu->entry[a].flag & CBX_DISABLED) XSetForeground(disp,gc,grey); else XSetForeground(disp,gc,black); XDrawImageString(disp,pop,gc,3,(a+1)*h-4,text[a],strlen(text[a])); CBX_Unlock(); } if ((i < n) && (i > -1)) { /* invert */ if (!(menu->entry[i].flag & CBX_SEPARATOR) && !(menu->entry[i].flag & CBX_DISABLED)) { (void)CBX_Lock(0); XSetBackground(disp,gc,black); XSetForeground(disp,gc,bg); XDrawImageString(disp,pop,gc,3,(i+1)*h-4,text[i],strlen(text[i])); CBX_Unlock(); } } a = i; /* new selection */ } } while ((event.type != ButtonRelease) || (event.xbutton.button != 1)); if ((a >= n) || (a < 0)) return(-1); if (menu->entry[a].flag & CBX_DISABLED) return(-1); if (menu->entry[a].flag & CBX_SEPARATOR) return(-1); return(a); } /* ---------------------------------------------------------------- */ static void cbx_remove_pop(Window pop,Menu* menu,char** text) { (void)CBX_Lock(0); XSetForeground(menu->disp,menu->gfs.gc,black); /* reset GC */ XDestroyWindow(menu->disp,pop); /* destroy windows */ XSync(menu->disp,False); CBX_Unlock(); free((void*)text[0]); /* free text buffers */ } /* ---------------------------------------------------------------- */ static char* cbx_extend(char *s, char c, int l) { int i; i = strlen(s); while (i < l) { s[i++] = c; } s[i] = '\0'; /* s[l] = '\0' Note: trim */ return(s); } /* ---------------------------------------------------------------- */ static void cbx_updatepmenu (Menu*); static void cbx_updatedmenu (Menu*); static void cbx_updatefmenu (Menu*); void CBX_UpdateMenu(Menu* menu) { #if (DEBUG > 2) fprintf(stderr,"CBX_UpdateMenu(%p)\n",(void*)menu); #endif switch (menu->type) { /* menu-type */ case MENU_DROP: /* drop-down menu */ cbx_updatedmenu(menu); break; case MENU_POPUP: /* popup menu */ cbx_updatepmenu(menu); break; case MENU_FREE: /* free menu */ cbx_updatefmenu(menu); break; } } /* ---------------------------------------------------------------- */ static void cbx_updatepmenu(Menu* menu) { Display *disp=menu->disp; Window win=menu->win; GC gc=menu->gfs.gc; u_long bg; char *text; if (menu->flag == CBX_NORMAL) bg = menu->bg; else if (menu->flag == CBX_ACTIVE) bg = yellow; else bg = lgrey; (void)CBX_Lock(0); XSetWindowBackground(disp,menu->win,bg); XClearWindow(disp,menu->win); if ((menu->sel < 0) || (menu->sel >= menu->n)) text = menu->unknown; else text = menu->entry[menu->sel].text; XSetForeground(disp,gc,black); XDrawString(disp,win,gc,3,menu->h-4,text,strlen(text)); XDrawArc(disp,win,gc,menu->w-10,menu->h/3,6,6,0,23040); CBX_Unlock(); } /* ---------------------------------------------------------------- */ static void cbx_updatedmenu(Menu* menu) { Display *disp=menu->disp; GC gc=menu->gfs.gc; Window win=menu->win; int w,h,d; u_long bg; if (menu->flag == CBX_NORMAL) bg = menu->bg; else if (menu->flag == CBX_ACTIVE) bg = yellow; else bg = lgrey; (void)CBX_Lock(0); XSetWindowBackground(disp,menu->win,bg); XClearWindow(disp,menu->win); XSetForeground(disp,gc,black); XDrawString(disp,win,gc,3,menu->h-4,menu->title, strlen(menu->title)); w = menu->w; h = menu->h; d=(int)((double)h/6.+0.5); /* draw triangle */ XDrawLine(disp,win,gc,w-(3*d)/2-2,h/2+d,w-(5*d)/2-2,h/2-d); XDrawLine(disp,win,gc,w-(5*d)/2-2,h/2-d,w-(1*d)/2-2,h/2-d); XDrawLine(disp,win,gc,w-(1*d)/2-2,h/2-d,w-(3*d)/2-2,h/2+d); CBX_Unlock(); } /* ---------------------------------------------------------------- */ static void cbx_updatefmenu(Menu* menu) { Display *disp=menu->disp; u_long bg; if (menu->flag == CBX_NORMAL) bg = menu->bg; else if (menu->flag == CBX_ACTIVE) bg = yellow; else bg = lgrey; (void)CBX_Lock(0); XSetWindowBackground(disp,menu->win,bg); XClearWindow(disp,menu->win); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_EnableMenu(Menu* menu) { if (menu->disp == NULL) return; switch (menu->type) { case MENU_DROP: case MENU_POPUP: CBX_SelectInput_Ext(menu->disp,menu->win, ButtonPressMask | ButtonReleaseMask); break; case MENU_FREE: CBX_SelectInput_Ext(menu->disp,menu->win,ExposureMask | ButtonPressMask | ButtonReleaseMask); break; } menu->flag = CBX_NORMAL; CBX_UpdateMenu(menu); if (menu->type == MENU_FREE) CBX_SendExpose_Ext(menu->disp,menu->win); } /* ---------------------------------------------------------------- */ void CBX_DisableMenu(Menu* menu,int flag) { if (menu->disp == NULL) return; CBX_ClearWindowQueue_Ext(menu->disp,menu->win); switch (menu->type) { case MENU_DROP: case MENU_POPUP: CBX_SelectInput_Ext(menu->disp,menu->win,None); break; case MENU_FREE: CBX_SelectInput_Ext(menu->disp,menu->win,ExposureMask); break; } menu->flag = flag; CBX_UpdateMenu(menu); if (menu->type == MENU_FREE) CBX_SendExpose_Ext(menu->disp,menu->win); } /* ---------------------------------------------------------------- */ /* EditWindow routines */ /* ---------------------------------------------------------------- */ void CBX_AddList(ManagedList* list,ManagedObject* object) { ManagedObject *temp; pthread_mutex_lock(&(list->lock)); /* MT-safe */ if (list->nlist >= list->mlist-1) { /* list full */ list->mlist += 8; /* increase list size */ list->olist = (ManagedObject*)realloc(list->olist, /* v4.070 */ list->mlist*sizeof(ManagedObject)); } temp = &(list->olist[list->nlist]); #if (DEBUG > 2) fprintf(stderr,"temp=%p, object=%p, callback=%p\n",(void*)temp, (void*)object->object,(void*)object->callback); #endif temp->object = object->object; /* add new object */ temp->callback = object->callback; /* and callback */ temp++; temp->object = NULL; /* terminator */ temp->callback = NULL; list->nlist += 1; #if (DEBUG > 2) fprintf(stderr,"%s(%p): nlist=%d\n",PREFUN,(void*)list,list->nlist); #endif pthread_mutex_unlock(&(list->lock)); } /* ---------------------------------------------------------------- */ void CBX_RemList(ManagedList* list,ManagedObject* object) { ManagedObject *temp; pthread_mutex_lock(&(list->lock)); /* MT-safe */ temp = list->olist; while (temp->object) { /* search for object */ if (temp->object == object->object) { /* found */ do { /* copy list 1 backwards */ memcpy((void*)temp,(void*)(temp+1),sizeof(ManagedObject)); temp++; } while (temp->object); list->nlist -= 1; /* adjust list size */ break; } temp++; } pthread_mutex_unlock(&(list->lock)); } /* ---------------------------------------------------------------- */ void CBX_UpdateEditWindow(EditWindow* ewin) { Display *disp = ewin->disp; GC lgc = ewin->gfs.gc; Window win = ewin->win; int y = ewin->h-4; int cpos = ewin->cpos; char *string; if (disp == NULL) return; #if (DEBUG > 2) fprintf(stderr,"%s(%s,%p)\n",PREFUN,ewin->text,(void*)disp); #endif if ((ewin->mode & CBX_OVERWRITE) && (ewin->flag & CBX_EDIT)) { string = ewin->buf; } else { string = ewin->text; } if (ewin->mode & CBX_VALUE) { /* value edit */ if (ewin->mode & CBX_OVERWRITE) { /* overwrite */ cpos = (int)strlen(string); /* -> cursor at end */ } } else { /* find best cursor pos. */ while (CBX_TextWidth_Ext(ewin->gfs,string) > ewin->w-ewin->h/2) { string++; cpos--; } while (cpos < 0) { string--; cpos++; } } (void)CBX_Lock(0); switch(ewin->flag) { case CBX_EDIT: /* editing CBX_OVERWRITE */ XSetForeground(disp,lgc,white); XSetWindowBackground(disp,win,red); ewin->show_cursor = True; break; case CBX_ACTIVE: /* active */ XSetForeground(disp,lgc,ewin->fg); XSetWindowBackground(disp,win,yellow); ewin->show_cursor = False; break; case CBX_DISABLED: /* disabled */ XSetForeground(disp,lgc,ewin->fg); XSetWindowBackground(disp,win,lgrey); ewin->show_cursor = False; break; case CBX_NORMAL: /* normal */ XSetForeground(disp,lgc,ewin->fg); XSetWindowBackground(disp,win,ewin->bg); break; default: fprintf(stderr,"WARNING: unknown flag in EditWindow=%d\n",(int)win); break; } XClearWindow(disp,win); XDrawString(disp,win,lgc,3,y,string,strlen(string)); XSetForeground(disp,lgc,black); CBX_Unlock(); if (ewin->show_cursor) { int x; char buf[128]; strcpy(buf,string); buf[cpos] = '\0'; if (*buf) x = 3+CBX_TextWidth_Ext(ewin->gfs,buf); else x = 2; (void)CBX_Lock(0); /* draw cursor */ XDrawLine(disp,win,lgc,x,2,x,ewin->h-2); XDrawLine(disp,win,lgc,x-1,2,x+1,2); XDrawLine(disp,win,lgc,x-1,ewin->h-2,x+1,ewin->h-2); CBX_Unlock(); } } /* ---------------------------------------------------------------- */ void CBX_ResetEditWindow(EditWindow* ewin) { if (!(ewin->flag & CBX_DISABLED)) ewin->flag = CBX_NORMAL; ewin->cpos = (int)strlen(ewin->text); CBX_UpdateEditWindow(ewin); } /* ---------------------------------------------------------------- */ void CBX_CrossEditWindow(EditWindow* ewin,int type) { if (type == EnterNotify) { /* enter window */ CBX_WindowBorder_Ext(ewin->disp,ewin->win,green); if (!(ewin->mode & CBX_OVERWRITE)) ewin->show_cursor = True; CBX_UpdateEditWindow(ewin); CBX_InputCursor(ewin->win); /* includes XFlush() */ } else if (type == LeaveNotify) { /* leave window */ CBX_WindowBorder_Ext(ewin->disp,ewin->win,black); ewin->show_cursor = False; CBX_UpdateEditWindow(ewin); CBX_NormalCursor(ewin->win); } } /* ---------------------------------------------------------------- */ Bool CBX_HandleEditWindow(EditWindow* ewin,XKeyEvent* event) { #ifndef __x86_64__ Display *disp=ewin->disp; #endif int size; Bool r=False; char buf[128],k,*keys; if (event) { (void)CBX_Lock(0); if (XLookupString(event,buf,sizeof(buf),NULL,NULL)) { /* there is a char */ k = *buf; switch (k) { case DEL: /* */ case BSP: /* */ if (ewin->mode & CBX_OVERWRITE) { /* overwrite mode */ if (ewin->flag != CBX_EDIT) { if ((ewin->mode & CBX_ENFORCE) == CBX_ENFORCE) { /* v4.064 */ if (k == BSP) { strcpy(ewin->buf,ewin->text); ewin->cpos = strlen(ewin->buf); } else { ewin->buf[0] = '\0'; ewin->cpos = 0; } } else { ewin->buf[0] = '\0'; ewin->cpos = 0; } ewin->flag = CBX_EDIT; } } if (ewin->cpos) { /* delete left always */ if (ewin->mode & CBX_OVERWRITE) keys = (char*)(ewin->buf+ewin->cpos-1); else keys = (char*)(ewin->text+ewin->cpos-1); do { *keys = *(keys+1); keys++; } while (*keys); ewin->cpos -= 1; } break; case ESC: /* */ if (ewin->mode & CBX_OVERWRITE) { /* overwrite mode */ if (ewin->flag == CBX_EDIT) { ewin->cpos = (int)strlen(ewin->text); ewin->flag = 0; } } else { /* insert mode */ ewin->text[0] = '\0'; /* clear text */ ewin->cpos = 0; } break; case CR: /* or */ if (ewin->mode & CBX_OVERWRITE) { /* overwrite mode */ if (ewin->flag & CBX_EDIT) { strcpy(ewin->text,ewin->buf); /* copy 'buf' to 'text' */ ewin->flag = 0; } } else { /* insert mode */ strcpy(ewin->buf,ewin->text); } r = True; break; default: /* insert/append character */ if (ewin->mode & CBX_VALUE) { /* numerical keys only */ if (((k < '0') || (k > '9')) && (k != '.') && (k != '-')) break; } if (ewin->mode & CBX_OVERWRITE) { /* overwrite mode */ if (ewin->flag != CBX_EDIT) { ewin->buf[0] = '\0'; /* clear buffer */ ewin->cpos = 0; ewin->flag = CBX_EDIT; } size = (int)strlen(ewin->buf); } else { /* insert mode */ size = (int)strlen(ewin->text); } if (size == sizeof(ewin->text)-1) break; /* buffer full */ if (ewin->mode & CBX_OVERWRITE) { /* overwrite mode */ if (ewin->cpos < size) { /* move text */ keys = (char*)(ewin->buf+size); do { *keys = *(keys-1); keys--; } while (keys > (char*)(ewin->buf+ewin->cpos)); } else *(ewin->buf+ewin->cpos+1) = '\0'; *(ewin->buf+ewin->cpos) = k; } else { /* insert mode */ #if (DEBUG > 1) fprintf(stderr,"ewin->cpos=%d, size=%d\n",ewin->cpos,size); #endif if (ewin->cpos < size) { /* move text */ keys = (char*)(ewin->text+size); *(keys+1) = '\0'; /* new term-char */ do { *keys = *(keys-1); keys--; } while (keys > (char*)(ewin->text+ewin->cpos)); } else *(ewin->text+ewin->cpos+1) = '\0'; *(ewin->text+ewin->cpos) = k; } ewin->cpos += 1; break; } /* endswitch(k) */ } else { /* check for special key */ if (!(ewin->mode & CBX_OVERWRITE) || (ewin->flag == CBX_EDIT)) { #ifdef __x86_64__ keys = XKeysymToString(XLookupKeysym(event,0)); #else keys = XKeysymToString(XKeycodeToKeysym(disp,event->keycode,0)); #endif if (!strcmp(keys,"Left")) { if (ewin->cpos) ewin->cpos -=1; } else if (!strcmp(keys,"Right")) { if (ewin->cpos < (int)strlen(ewin->text)) ewin->cpos += 1; } } } /* endif(XLookupString) */ CBX_Unlock(); } CBX_UpdateEditWindow(ewin); return(r); } /* ---------------------------------------------------------------- */ Window CBX_CreateSimpleWindow(MainWindow* mw,int x,int y,int w,int h,u_long c) { return(CBX_CreateSimpleWindow_Ext(mw->disp,mw->win,x,y,w,h,c)); } /* ---------------------------------------------------------------- */ Window CBX_CreateSimpleWindow_Ext(Display* disp,Window parent, int x,int y,int w,int h,u_long c) { Window win; (void)CBX_Lock(0); win = XCreateSimpleWindow(disp,parent,x,y,w,h,1,black,c); XMapRaised(disp,win); CBX_Unlock(); return(win); } /* ---------------------------------------------------------------- */ Window CBX_CreateArea(MainWindow* mw,int x,int y,int w,int h,u_long c) { Window win; (void)CBX_Lock(0); win = XCreateSimpleWindow(mw->disp,mw->win,x,y,w,h,0,c,c); XMapRaised(mw->disp,win); CBX_Unlock(); return(win); } /* ---------------------------------------------------------------- */ void CBX_DisableEditWindow(EditWindow* ewin,int flag) { if (ewin->disp == NULL) return; ewin->show_cursor = False; CBX_ClearWindowQueue_Ext(ewin->disp,ewin->win); CBX_SelectInput_Ext(ewin->disp,ewin->win,None); CBX_WindowBorder_Ext(ewin->disp,ewin->win,black); ewin->flag = flag; CBX_UpdateEditWindow(ewin); } /* ---------------------------------------------------------------- */ void CBX_EnableEditWindow(EditWindow* ewin) { long mask; if (ewin->disp == NULL) return; mask = KeyPressMask | EnterWindowMask | LeaveWindowMask; #if 0 /* cut/paste */ if (ewin->mode & CBX_AUTO) mask |= ButtonPressMask | PropertyChangeMask; #else if (ewin->mode & CBX_AUTO) mask |= ButtonPressMask; #endif CBX_SelectInput_Ext(ewin->disp,ewin->win,mask); ewin->flag = CBX_NORMAL; CBX_UpdateEditWindow(ewin); } /* ---------------------------------------------------------------- */ void CBX_BlinkLed(Led *l,int dt) { if ((l->mode & CBX_BLINKING) || (l->mode & CBX_STRONG_BLINK)) { if ((l->blink-=dt) <= 0) { l->mode ^= CBX_INVERTED; CBX_UpdateLed(l); l->blink = CBX_BTIME; } } } /* ---------------------------------------------------------------- */ void CBX_UpdateLed(Led* led) { u_long color; if (led->mode & CBX_INVERTED) color = led->c2; else color = led->c1; if (led->bg != color) { (void)CBX_Lock(0); XSetWindowBackground(led->disp,led->win,led->bg=color); XClearWindow(led->disp,led->win); CBX_Unlock(); } } /* ---------------------------------------------------------------- */ /* Miscellaneous */ /* ---------------------------------------------------------------- */ #define NBUF_WINS 32 void CBX_ClearAutoQueue(MainWindow* mw) { int slpt; /* act on 'Expose', remove all other events */ Window bwins[NBUF_WINS]; int nwins=0; XEvent event; if (mw->disp == NULL) return; (void)CBX_Lock(0); while (XEventsQueued(mw->disp,QueuedAfterFlush)) { XPeekEvent(mw->disp,&event); #if (DEBUG > 1) fprintf(stderr,"%s: CBX_ClearAutoQueue(): event.type=%d\n",__FILE__, event.type); #endif if (event.type != Expose) XNextEvent(mw->disp,&event); /* remove event */ else { /* act on event */ CBX_Unlock(); if (CBX_AutoEvent(mw,&event,&slpt)) { /* event not handled */ if (nwins < NBUF_WINS) { int i; /* add to list */ for (i=0; idisp,bwins[nwins]); } } #undef NBUF_WINS /* ---------------------------------------------------------------- */ void CBX_ClearXQueue_Ext(Display *disp) { XEvent e; (void)CBX_Lock(0); while (XEventsQueued(disp,QueuedAfterFlush)) { XNextEvent(disp,&e); /* clear input-queue */ #if (DEBUG > 2) fprintf(stderr,"CBX_ClearXQueue_Ext(): event.type=%d\n",e.type); #endif } CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_ClearWindowQueue_Ext(Display* disp,Window w) { XEvent e; (void)CBX_Lock(0); XFlush(disp); while (XCheckWindowEvent(disp,w,CBX_ALL_EVENTS,&e)) { #if (DEBUG > 1) fprintf(stderr,"CBX_ClearWindowQueue_Ext(): event.type=%d\n",e.type); #endif } CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_Sync_Ext(Display* disp) { (void)CBX_Lock(0); XSync(disp,False); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_Flush_Ext(Display* disp) { (void)CBX_Lock(0); XFlush(disp); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_Flush(MainWindow* mw) { CBX_Flush_Ext(mw->disp); } /* ---------------------------------------------------------------- */ void CBX_GetRootPos(Window win,int* x,int* y) { Window root,parent,*c; u_int n; XWindowAttributes xwa; *x = *y = 0; (void)CBX_Lock(0); do { XGetWindowAttributes(cbx_app->disp,win,&xwa); XQueryTree(cbx_app->disp,win,&root,&parent,&c,&n); XFree((void*)c); /* free list of children */ *x += xwa.x; *y += xwa.y; win = parent; } while (parent != root); /* parent was NOT root */ CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_GetRootSize(Window win,int* w,int* h) { Window root,parent,*c; u_int n; XWindowAttributes xwa; (void)CBX_Lock(0); do { XGetWindowAttributes(cbx_app->disp,win,&xwa); XQueryTree(cbx_app->disp,win,&root,&parent,&c,&n); XFree((void*)c); /* free list of children */ win = parent; } while (parent != root); /* parent was NOT root */ CBX_Unlock(); *w = xwa.width; *h = xwa.height; } /* ---------------------------------------------------------------- */ void CBX_GetGeometry(Window win,int* x,int* y,int* w,int* h) { CBX_GetRootPos(win,x,y); CBX_GetRootSize(win,w,h); } /* ---------------------------------------------------------------- */ /* other routines */ /* ---------------------------------------------------------------- */ char* CBX_HostName(char *hostdomain) { char hostname[256]; struct hostent *hostp; static char host[256]; if (hostdomain == NULL) hostdomain = host; if (gethostname(hostname,sizeof(hostname)) == -1) { (void)strcpy(hostdomain,"unknown"); return(hostdomain); } hostp = gethostbyname(hostname); if (hostp == NULL) (void)strcpy(hostdomain,"unknown"); else (void)strcpy(hostdomain,hostp->h_name); return(hostdomain); } /* ---------------------------------------------------------------- */ void CBX_SendExpose_Ext(Display* disp,Window w) { XEvent event; if (disp == NULL) return; event.type = Expose; event.xexpose.send_event = True; event.xexpose.count = 0; event.xexpose.window = w; (void)CBX_Lock(0); XSendEvent(disp,w,True,ExposureMask,&event); XFlush(disp); CBX_Unlock(); } /* ---------------------------------------------------------------- */ int CBX_Sleep(int* sleeptime,int inc,int limit) { cbx_msleep(*sleeptime); *sleeptime = cbx_min(*sleeptime += inc,limit); return(*sleeptime); } /* ---------------------------------------------------------------- */ void cbx_msleep(int msec) { #ifdef SVR4 struct timespec delay; if (msec > 0) { delay.tv_sec = msec/1000; delay.tv_nsec = (msec % 1000) * 1000000; (void)nanosleep(&delay,NULL); } #else while (msec >= 1000) { sleep(1); msec -= 1000; } if (msec > 0) usleep((u_int)msec*1000); /* avoid to call usleep(0) */ #endif } /* ---------------------------------------------------------------- */ void CBX_ResizeMainWindow(MainWindow* mw,int w,int h) { CBX_ResizeWindow_Ext(mw->disp,mw->win,w,h); } /* ---------------------------------------------------------------- */ void CBX_ResizeWindow_Ext(Display* disp,Window win,int w,int h) { (void)CBX_Lock(0); XResizeWindow(disp,win,w,h); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_MoveResizeMainWindow(MainWindow* mw,long pos,int w,int h) { int x,y; cbx_GetXY(pos,&x,&y,w,h,0); (void)CBX_Lock(0); XMoveResizeWindow(mw->disp,mw->win,x,y,w,h); CBX_Unlock(); } /* ---------------------------------------------------------------- */ static Bool cbx_iswindow; Bool CBX_IsWindow(Window win) { return(CBX_IsWindow_Ext(cbx_app->disp,win)); } /* ---------------------------------------------------------------- */ static int cbx_iswindow_errhandler(Display* disp,XErrorEvent* ee) { #if (DEBUG > 1) char buffer[1024]; fprintf(stderr,"cbx_iswindow_errhandler on display=%p\n",(void*)disp); fprintf(stderr,"\ttype=%d\n",ee->type); fprintf(stderr,"\tserial=%ld\n",ee->serial); fprintf(stderr,"\terror_code=%d\n",ee->error_code); fprintf(stderr,"\trequest_code=%d\n",ee->request_code); fprintf(stderr,"\tminor_code=%d\n",ee->minor_code); XGetErrorText(disp,ee->error_code,buffer,sizeof(buffer)); fprintf(stderr,"\terror_text=%s\n",buffer); #endif cbx_iswindow = False; return(0); } /* --- */ Bool CBX_IsWindow_Ext(Display* disp,Window win) { XWindowAttributes xwa; XErrorHandler old_eh; (void)CBX_Lock(0); cbx_iswindow = True; old_eh = XSetErrorHandler(cbx_iswindow_errhandler); (void)XGetWindowAttributes(disp,win,&xwa); (void)XSetErrorHandler(old_eh); CBX_Unlock(); return(cbx_iswindow); } /* ---------------------------------------------------------------- */ Bool CBX_IsMapped(Window win) { XWindowAttributes xwa; if (!CBX_IsWindow(win)) return(False); (void)CBX_Lock(0); XGetWindowAttributes(cbx_app->disp,win,&xwa); CBX_Unlock(); if (xwa.map_state == IsUnmapped) return(False); return(True); } /* ---------------------------------------------------------------- */ Bool CBX_TopWindow(Window win) { return(CBX_TopWindow_Ext(cbx_app->disp,win)); } /* ---------------------------------------------------------------- */ Bool CBX_TopWindow_Ext(Display* disp,Window win) /* v4.065 */ { if (CBX_IsWindow(win)) { /* window exists? */ if (CBX_IsMapped(win)) { /* is mapped? -> raise it */ (void)CBX_Lock(0); XRaiseWindow(disp,win); CBX_Unlock(); } else { /* no: map it */ (void)CBX_Lock(0); XMapWindow(disp,win); CBX_Unlock(); } return(True); } return(False); } /* ---------------------------------------------------------------- */ void CBX_WindowBorder_Ext(Display* disp,Window win,u_long color) { (void)CBX_Lock(0); XSetWindowBorder(disp,win,color); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_SetCursor_Ext(Display* disp,Window win,int cursor_id) { Cursor cursor; (void)CBX_Lock(0); cursor = XCreateFontCursor(disp,(u_int)cursor_id); XDefineCursor(disp,win,cursor); XFlush(disp); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_BusyCursor(Window win) { (void)CBX_Lock(0); XDefineCursor(cbx_app->disp,win,cbx_app->busy_cursor); XFlush(cbx_app->disp); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_InputCursor(Window win) { (void)CBX_Lock(0); XDefineCursor(cbx_app->disp,win,cbx_app->input_cursor); XFlush(cbx_app->disp); CBX_Unlock(); } /* ---------------------------------------------------------------- */ void CBX_NormalCursor(Window win) { CBX_NormalCursor_Ext(cbx_app->disp,win); } /* ---------------------------------------------------------------- */ void CBX_NormalCursor_Ext(Display* disp,Window win) { (void)CBX_Lock(0); XUndefineCursor(disp,win); /* reset to norm-curs. */ XFlush(disp); CBX_Unlock(); } /* ---------------------------------------------------------------- */ char CBX_GetKey(XEvent* ev) { int i; char buf[32]; KeySym key; (void)CBX_Lock(0); i = XLookupString((XKeyEvent*)ev,buf,sizeof(buf),&key,0); CBX_Unlock(); if (i == 1) return(*buf); return((char)0); } /* ---------------------------------------------------------------- */ long CBX_GetKeySym(XEvent* ev) { char buf[32]; KeySym key; (void)CBX_Lock(0); (void)XLookupString((XKeyEvent*)ev,buf,sizeof(buf),&key,0); CBX_Unlock(); return((long)key); } /* ---------------------------------------------------------------- */ void CXT_Bell(int n,int vol) { while (n > 0) { (void)CBX_Lock(0); XBell(cbx_app->disp,vol); XFlush(cbx_app->disp); CBX_Unlock(); n--; if (n > 0) cbx_msleep(500); } } /* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */