/* ---------------------------------------------------------------- * * cxt_listb.c * * Xlib - wrappers and convenience functions * * v4.00 2002-03-27 auto-managed windows / MainWindow [CCB] * * ---------------------------------------------------------------- */ #define IS_CXTLIB_C /* DEFINEs -------------------------------------------------------- */ #ifndef DEBUG #define DEBUG 1 /* debug level */ #endif #ifdef FONTSIZE #define PXh FONTSIZE #else #define PXh 14 /* default fontsize */ #endif #define PXw (10+(PXh-14)/2) #define XXh (PXh+4) #define PREFUN __func__ /* INCLUDEs ------------------------------------------------------- */ #define _REENTRANT #include #if (DEBUG > 0) #include #endif #include "cxt.h" /* TYPEDEFs ------------------------------------------------------- */ /* EXTERNs -------------------------------------------------------- */ extern Application *cbx_app; /* function prototype(s) */ extern void cbx_msleep (int); extern int cbx_min (int,int); extern int cbx_max (int,int); /* ---------------------------------------------------------------- */ /* Listbox routines */ /* ---------------------------------------------------------------- */ #define DW (PXw+6) Window CBX_CreateListbox(MainWindow* mw,Listbox* lb,int x,int y,int w,int h, int n,char** list,int nlist) { Display *disp = mw->disp; GfC gfs = mw->gfs; Window win; int i; (void)CBX_Lock(0); win = XCreateSimpleWindow(disp,mw->win,x,y,w,n*h+2,0,cbx_app->black, cbx_app->grey); XMapRaised(disp,win); lb->mwin = mw; lb->disp = disp; lb->bg = cbx_app->beige; for (i=0; iwin[i] = XCreateSimpleWindow(disp,win,0,i*h,w-2*PXw,h-1, 1,cbx_app->black,lb->bg); XMapRaised(disp,lb->win[i]); XSelectInput(disp,lb->win[i],ButtonPressMask); } CBX_Unlock(); (void)CBX_CreateSButton_Ext(mw,&lb->upbut,win,gfs,w-DW,0, DW,PXh, CBX_UP_TRI); (void)CBX_CreateSButton_Ext(mw,&lb->dnbut,win,gfs,w-DW,n*h-PXh,DW,PXh, CBX_DN_TRI); lb->sch = n*h-32; /* scroll window */ lb->scwin = CBX_CreateSimpleWindow_Ext(disp,win,w-DW,DW,PXh,lb->sch, cbx_app->grey); CBX_SelectInput_Ext(disp,lb->scwin,ButtonPressMask | ButtonReleaseMask | Button1MotionMask); if (nlist > 0) lb->scbut.h = cbx_min(lb->sch,cbx_max(7,(lb->sch*n)/nlist)); else lb->scbut.h = lb->sch; /* scroll button */ lb->sby = 0; (void)CBX_CreateButton_Ext(mw,&lb->scbut,lb->scwin,gfs,0,lb->sby, PXw+2,lb->scbut.h,NULL); lb->listbox = win; lb->gfs = gfs; lb->n = n; lb->h = h; lb->list = list; lb->nlist = nlist; lb->sel = -1; lb->pos = 0; return(win); } /* ---------------------------------------------------------------- */ void CBX_RedrawListbox(Listbox* lb,Bool all) { Display *disp=lb->disp; GC gc=lb->gfs.gc; int i,j; char *text; #if (DEBUG > 1) fprintf(stderr,"%s(%p): all=%d, pos=%d\n",PREFUN,lb,all,lb->pos); #endif if (all) { CBX_UpdateButton(&lb->upbut); CBX_UpdateButton(&lb->dnbut); } (void)CBX_Lock(0); if (all) XClearWindow(disp,lb->scwin); for (i=0,j=lb->pos; i < lb->n; i++,j++) { if (j == lb->sel) { XSetForeground(disp,gc,cbx_app->white); XSetWindowBackground(disp,lb->win[i],cbx_app->lgrey); } else { XSetForeground(disp,gc,cbx_app->black); XSetWindowBackground(disp,lb->win[i],lb->bg); } XClearWindow(disp,lb->win[i]); if (j < lb->nlist) { text = lb->list[j]; XDrawString(disp,lb->win[i],gc,3,lb->h-5,text,strlen(text)); } if (j == lb->sel) XSetForeground(disp,gc,cbx_app->black); } if (lb->nlist > lb->n) lb->sby = cbx_max(0,cbx_min(lb->sch-lb->scbut.h, (lb->pos*(lb->sch-lb->scbut.h))/(lb->nlist-lb->n))); else lb->sby = 0; XMoveWindow(disp,lb->scbut.win,0,lb->sby); CBX_Unlock(); CBX_UpdateButton(&lb->scbut); CBX_Flush_Ext(disp); } /* ---------------------------------------------------------------- */ Bool CBX_HandleListbox(XEvent* event,Listbox* lb,void (*call_on_dclick)()) { Display *disp=lb->disp; int i,slt; Bool handled=False; if (event->type != ButtonPress) return(False); if (event->xbutton.button != 1) return(False); #if (DEBUG > 1) fprintf(stderr,"%s(%p): call=%p\n",PREFUN,lb,call_on_dclick); #endif if (event->xbutton.window == lb->upbut.win) { /* scroll button up */ lb->upbut.flag=CBX_PRESSED; CBX_UpdateButton(&lb->upbut); CBX_Flush_Ext(disp); if (lb->pos > 0) { lb->pos--; CBX_RedrawListbox(lb,False); } cbx_msleep(200); slt=100; /* auto-repeat delay */ while (!CBX_CheckEvent_Ext(disp,ButtonReleaseMask,event)) { if (lb->pos > 0) { lb->pos--; CBX_RedrawListbox(lb,False); } slt-=5; cbx_msleep(cbx_max(slt,40)); } lb->upbut.flag=CBX_NORMAL; CBX_UpdateButton(&lb->upbut); handled = True; } else if (event->xbutton.window == lb->dnbut.win) { /* scroll button down */ lb->dnbut.flag=CBX_PRESSED; CBX_UpdateButton(&lb->dnbut); CBX_Flush_Ext(disp); if (lb->pos < lb->nlist-lb->n) { lb->pos++; CBX_RedrawListbox(lb,False); } cbx_msleep(200); slt=100; /* auto-repeat delay */ while (!CBX_CheckEvent_Ext(disp,ButtonReleaseMask,event)) { if (lb->pos < lb->nlist-lb->n) { lb->pos++; CBX_RedrawListbox(lb,False); } slt-=5; cbx_msleep(cbx_max(slt,40)); } lb->dnbut.flag=CBX_NORMAL; CBX_UpdateButton(&lb->dnbut); handled = True; } else if (event->xbutton.window == lb->scbut.win) { /* scrollbar button */ CBX_PressButton(&lb->scbut); (void)CBX_Lock(0); (void)XGrabPointer(disp,lb->scwin,False, /* grab pointer events */ Button1MotionMask | ButtonReleaseMask, GrabModeAsync,GrabModeAsync,lb->scwin,None,0); CBX_Unlock(); do { CBX_WaitEvent_Ext(disp,event,50); /* sleeptime ? */ if (event->type == MotionNotify) { /* move scroll-button */ lb->sby = event->xbutton.y-lb->scbut.h/2; /* new position */ lb->sby = cbx_max(0,cbx_min(lb->sch-lb->scbut.h,lb->sby)); if ((lb->sch-lb->scbut.h > 0) && (lb->nlist > lb->n)) { i = cbx_max(0,cbx_min(lb->nlist-lb->n, (lb->sby*(lb->nlist-lb->n))/(lb->sch-lb->scbut.h))); } else { i = 0; } if (i != lb->pos) { lb->pos = i; CBX_RedrawListbox(lb,False); } } } while (event->type != ButtonRelease); /* until 'ButtonRelease' */ (void)CBX_Lock(0); XUngrabPointer(disp,CurrentTime); /* release pointer-grab */ CBX_Unlock(); CBX_ReleaseButton(&lb->scbut); handled = True; } else if (event->xbutton.window == lb->scwin) { /* scrollbar window */ if (event->xbutton.y < lb->sby) i = cbx_max(0,lb->pos-lb->n); else if (event->xbutton.y > lb->sby+lb->scbut.h) i = cbx_min(lb->nlist-lb->n,lb->pos+lb->n); else i = lb->pos; if (i != lb->pos) { lb->pos = i; CBX_RedrawListbox(lb,False); } do { /* wait for release */ CBX_WaitEvent_Ext(disp,event,50); } while (event->type != ButtonRelease); handled = True; } else { /* check listbox entries */ if (call_on_dclick == NULL) return(False); for (i=0; in; i++) { if (event->xbutton.window != lb->win[i]) continue; /* not this window */ handled = True; if (i+lb->pos >= lb->nlist) break; /* non-empty window */ lb->sel = i+lb->pos; CBX_RedrawListbox(lb,False); cbx_msleep(200); /* double-click delay */ (void)CBX_Lock(0); if (XCheckTypedWindowEvent(disp,lb->win[i],ButtonPress,event)) { CBX_Unlock(); call_on_dclick(); } else CBX_Unlock(); break; } /* endfor(lb->n) */ } /* endif(event->xbutton.window) */ return(handled); } /* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */