2004-01-25 10:00:31 +01:00
|
|
|
|
/*LINTLIBRARY*/
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Mini-Toolbox
|
|
|
|
|
|
*
|
|
|
|
|
|
* David Harrison
|
|
|
|
|
|
* University of California, Berkeley
|
|
|
|
|
|
* 1988, 1989
|
|
|
|
|
|
*
|
|
|
|
|
|
* This file contains routines which implement simple display widgets
|
|
|
|
|
|
* which can be used to construct simple dialog boxes.
|
|
|
|
|
|
* A mini-toolbox has been written here (overkill but I didn't
|
|
|
|
|
|
* want to use any of the standards yet -- they are too unstable).
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2005-09-19 22:51:55 +02:00
|
|
|
|
#include <stdio.h> /* for printf() */
|
2004-01-25 10:00:31 +01:00
|
|
|
|
#include <X11/Xos.h>
|
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
|
|
#include <X11/Xutil.h>
|
2005-09-19 22:51:55 +02:00
|
|
|
|
#include <string.h> /* for strcpy() and strlen() */
|
2004-01-25 10:00:31 +01:00
|
|
|
|
#include "xtb.h"
|
|
|
|
|
|
|
|
|
|
|
|
extern void abort();
|
|
|
|
|
|
|
|
|
|
|
|
#define MAXKEYS 10
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __STDC__
|
|
|
|
|
|
#define FNPTR(fname, rtn, args) rtn (*fname)args
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
#define VARARGS(func, rtn, args) rtn func args
|
|
|
|
|
|
#else
|
|
|
|
|
|
#define FNPTR(fname, rtn, args) rtn (*fname)()
|
|
|
|
|
|
#include <varargs.h>
|
|
|
|
|
|
#define VARARGS(func, rtn, args) /*VARARGS1*/ rtn func(va_alist) va_dcl
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
struct h_info {
|
|
|
|
|
|
FNPTR(func, xtb_hret, (XEvent * evt, xtb_data info)); /* Function to call */
|
|
|
|
|
|
xtb_data info; /* Additional info */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static Display *t_disp; /* Display */
|
|
|
|
|
|
static int t_scrn; /* Screen */
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned long norm_pix; /* Foreground color */
|
|
|
|
|
|
static unsigned long back_pix; /* Background color */
|
|
|
|
|
|
|
|
|
|
|
|
static XFontStruct *norm_font; /* Normal font */
|
|
|
|
|
|
|
|
|
|
|
|
extern char *Malloc();
|
|
|
|
|
|
|
|
|
|
|
|
#define STRDUP(str) (strcpy(Malloc((unsigned) (strlen(str)+1)), (str)))
|
|
|
|
|
|
extern void Free();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_init(disp, scrn, foreground, background, font)
|
|
|
|
|
|
Display *disp; /* Display */
|
|
|
|
|
|
int scrn; /* Screen number */
|
|
|
|
|
|
unsigned long foreground; /* Foreground color */
|
|
|
|
|
|
unsigned long background; /* Background color */
|
|
|
|
|
|
XFontStruct *font; /* Normal font */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Sets default parameters used by the mini-toolbox.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
t_disp = disp;
|
|
|
|
|
|
t_scrn = scrn;
|
|
|
|
|
|
norm_pix = foreground;
|
|
|
|
|
|
back_pix = background;
|
|
|
|
|
|
norm_font = font;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define gray_width 32
|
|
|
|
|
|
#define gray_height 32
|
|
|
|
|
|
static char gray_bits[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
|
|
|
|
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
|
|
|
|
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
|
|
|
|
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
|
|
|
|
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
|
|
|
|
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
|
|
|
|
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
|
|
|
|
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
|
|
|
|
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
|
|
|
|
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
|
|
|
|
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa};
|
|
|
|
|
|
|
|
|
|
|
|
static Pixmap
|
|
|
|
|
|
make_stipple(disp, able, bits, width, height)
|
|
|
|
|
|
Display *disp;
|
|
|
|
|
|
Drawable able;
|
|
|
|
|
|
char *bits;
|
|
|
|
|
|
unsigned int width,
|
|
|
|
|
|
height;
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned int w,
|
|
|
|
|
|
h;
|
|
|
|
|
|
Pixmap stipple;
|
|
|
|
|
|
int bitmap_pad;
|
|
|
|
|
|
GC image_gc;
|
|
|
|
|
|
XGCValues image_vals;
|
|
|
|
|
|
XImage *stip_image;
|
|
|
|
|
|
|
|
|
|
|
|
if (!XQueryBestStipple(disp, able, width, height, &w, &h)) {
|
|
|
|
|
|
/* Can't query best stipple */
|
|
|
|
|
|
return (Pixmap) 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((w > width) || (h > height)) {
|
|
|
|
|
|
/* Given pattern is too small */
|
|
|
|
|
|
return (Pixmap) 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!(stipple = XCreatePixmap(disp, able, w, h, 1))) {
|
|
|
|
|
|
/* Can't create pixmap image */
|
|
|
|
|
|
return (Pixmap) 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
bitmap_pad = 8;
|
|
|
|
|
|
stip_image = XCreateImage(disp, DefaultVisual(disp, DefaultScreen(disp)),
|
|
|
|
|
|
1, XYPixmap, 0, bits, width, height,
|
|
|
|
|
|
bitmap_pad, 0);
|
|
|
|
|
|
if (!stip_image)
|
|
|
|
|
|
return (Pixmap) 0;
|
|
|
|
|
|
image_gc = XCreateGC(disp, stipple, (unsigned long) 0, &image_vals);
|
|
|
|
|
|
XPutImage(disp, stipple, image_gc, stip_image, 0, 0, 0, 0, w, h);
|
|
|
|
|
|
return stipple;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Pixmap
|
|
|
|
|
|
gray_map(win)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Returns a gray pixmap suitable for stipple fill.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
static Pixmap map = (Pixmap) 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (!map) {
|
|
|
|
|
|
map = make_stipple(t_disp, win, gray_bits, gray_width, gray_height);
|
|
|
|
|
|
}
|
|
|
|
|
|
return map;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static GC
|
|
|
|
|
|
set_gc(win, fg, bg, font, gray_p)
|
|
|
|
|
|
Window win; /* For creating GC */
|
|
|
|
|
|
unsigned long fg; /* Foreground pixel */
|
|
|
|
|
|
unsigned long bg; /* Background pixel */
|
|
|
|
|
|
Font font; /* Font */
|
|
|
|
|
|
int gray_p; /* Gray if set */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Sets and returns the fields listed above in a global graphics context.
|
|
|
|
|
|
* If graphics context does not exist, it is created.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
static GC t_gc = (GC) 0;
|
|
|
|
|
|
XGCValues gcvals;
|
|
|
|
|
|
unsigned long gcmask;
|
|
|
|
|
|
|
|
|
|
|
|
gcvals.foreground = fg;
|
|
|
|
|
|
gcvals.background = bg;
|
|
|
|
|
|
gcvals.font = font;
|
|
|
|
|
|
gcvals.stipple = gray_map(win);
|
|
|
|
|
|
gcvals.fill_style = (gray_p ? FillStippled : FillSolid);
|
|
|
|
|
|
gcmask = GCForeground | GCBackground | GCFont | GCFillStyle | GCStipple;
|
|
|
|
|
|
if (t_gc == (GC) 0) {
|
|
|
|
|
|
t_gc = XCreateGC(t_disp, win, gcmask, &gcvals);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
XChangeGC(t_disp, t_gc, gcmask, &gcvals);
|
|
|
|
|
|
}
|
|
|
|
|
|
return t_gc;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static XContext h_context = (XContext) 0;
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_register(win, func, info)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
|
|
|
|
|
|
FNPTR(func, xtb_hret, (XEvent * evt, xtb_data info));
|
|
|
|
|
|
xtb_data info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Associates the event handling function `func' with the window
|
|
|
|
|
|
* `win'. Additional information `info' will be passed to `func'.
|
|
|
|
|
|
* The routine should return one of the return codes given above.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct h_info *new_info;
|
|
|
|
|
|
|
|
|
|
|
|
if (h_context == (XContext) 0) {
|
|
|
|
|
|
h_context = XUniqueContext();
|
|
|
|
|
|
}
|
|
|
|
|
|
new_info = (struct h_info *) Malloc(sizeof(struct h_info));
|
|
|
|
|
|
new_info->func = func;
|
|
|
|
|
|
new_info->info = info;
|
|
|
|
|
|
XSaveContext(t_disp, win, h_context, (caddr_t) new_info);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xtb_data
|
|
|
|
|
|
xtb_lookup(win)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Returns the associated data with window `win'.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
xtb_data data;
|
|
|
|
|
|
|
|
|
|
|
|
if (!XFindContext(t_disp, win, h_context, (XPointer*) &data)) {
|
|
|
|
|
|
return ((struct h_info *) data)->info;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
return (xtb_data) 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xtb_hret
|
|
|
|
|
|
xtb_dispatch(evt)
|
|
|
|
|
|
XEvent *evt;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Dispatches an event to a handler if its ours. Returns one of
|
|
|
|
|
|
* the return codes given above (XTB_NOTDEF, XTB_HANDLED, or XTB_STOP).
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct h_info *info;
|
|
|
|
|
|
|
|
|
|
|
|
if (!XFindContext(t_disp, evt->xany.window, h_context, (caddr_t *) & info)) {
|
|
|
|
|
|
if (info->func)
|
2011-04-27 20:30:15 +02:00
|
|
|
|
return info->func (evt, info->info);
|
2004-01-25 10:00:31 +01:00
|
|
|
|
else
|
|
|
|
|
|
return XTB_NOTDEF;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
return XTB_NOTDEF;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
xtb_unregister(win, info)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
xtb_data *info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Removes `win' from the dialog association table. `info' is
|
|
|
|
|
|
* returned to allow the user to delete it (if desired). Returns
|
|
|
|
|
|
* a non-zero status if the association was found and properly deleted.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct h_info *hi;
|
|
|
|
|
|
|
|
|
|
|
|
if (!XFindContext(t_disp, win, h_context, (caddr_t *) & hi)) {
|
|
|
|
|
|
(void) XDeleteContext(t_disp, win, h_context);
|
|
|
|
|
|
*info = hi->info;
|
|
|
|
|
|
Free((char *) hi);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BT_HPAD 3
|
|
|
|
|
|
#define BT_VPAD 2
|
|
|
|
|
|
#define BT_LPAD 3
|
|
|
|
|
|
#define BT_BRDR 1
|
|
|
|
|
|
|
|
|
|
|
|
struct b_info {
|
|
|
|
|
|
FNPTR(func, xtb_hret, (Window win, int state, xtb_data val));
|
|
|
|
|
|
/* Function to call */
|
|
|
|
|
|
char *text; /* Text of button */
|
|
|
|
|
|
int flag; /* State of button */
|
|
|
|
|
|
int na; /* Non-zero if not active */
|
|
|
|
|
|
int line_y,
|
|
|
|
|
|
line_w; /* Entry/Exit line */
|
|
|
|
|
|
xtb_data val; /* User defined info */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
bt_draw(win, ri)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
struct b_info *ri;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Draws a button window
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ri->flag) {
|
|
|
|
|
|
XDrawImageString(t_disp, win,
|
|
|
|
|
|
set_gc(win, back_pix, norm_pix, norm_font->fid, 0),
|
|
|
|
|
|
BT_HPAD, BT_VPAD + norm_font->ascent,
|
|
|
|
|
|
ri->text, strlen(ri->text));
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
XDrawImageString(t_disp, win,
|
|
|
|
|
|
set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
|
|
|
|
|
|
BT_HPAD, BT_VPAD + norm_font->ascent,
|
|
|
|
|
|
ri->text, strlen(ri->text));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (ri->na) {
|
|
|
|
|
|
Window root;
|
|
|
|
|
|
int x,
|
|
|
|
|
|
y;
|
|
|
|
|
|
unsigned int w,
|
|
|
|
|
|
h,
|
|
|
|
|
|
b,
|
|
|
|
|
|
d;
|
|
|
|
|
|
|
|
|
|
|
|
XGetGeometry(t_disp, win, &root, &x, &y, &w, &h, &b, &d);
|
|
|
|
|
|
XFillRectangle(t_disp, win,
|
|
|
|
|
|
set_gc(win, (ri->flag ? norm_pix : back_pix),
|
|
|
|
|
|
back_pix, norm_font->fid, 1),
|
|
|
|
|
|
0, 0, w, h);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
bt_line(win, ri, pix)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
struct b_info *ri;
|
|
|
|
|
|
unsigned long pix;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Draws a status line beneath the text to indicate the
|
|
|
|
|
|
* user has moved into the button.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XDrawLine(t_disp, win,
|
|
|
|
|
|
set_gc(win, pix, back_pix, norm_font->fid, ri->na),
|
|
|
|
|
|
BT_HPAD, ri->line_y, BT_HPAD + ri->line_w, ri->line_y);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static xtb_hret
|
|
|
|
|
|
bt_h(evt, info)
|
|
|
|
|
|
XEvent *evt;
|
|
|
|
|
|
xtb_data info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Handles button events.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
Window win = evt->xany.window;
|
|
|
|
|
|
struct b_info *ri = (struct b_info *) info;
|
|
|
|
|
|
xtb_hret rtn = 0;
|
|
|
|
|
|
|
|
|
|
|
|
switch (evt->type) {
|
|
|
|
|
|
case Expose:
|
|
|
|
|
|
bt_draw(win, ri);
|
|
|
|
|
|
rtn = XTB_HANDLED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EnterNotify:
|
|
|
|
|
|
if (!ri->na)
|
|
|
|
|
|
bt_line(win, ri, norm_pix);
|
|
|
|
|
|
rtn = XTB_HANDLED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LeaveNotify:
|
|
|
|
|
|
if (!ri->na)
|
|
|
|
|
|
bt_line(win, ri, back_pix);
|
|
|
|
|
|
rtn = XTB_HANDLED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ButtonPress:
|
|
|
|
|
|
/* Nothing - just wait for button up */
|
|
|
|
|
|
rtn = XTB_HANDLED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ButtonRelease:
|
|
|
|
|
|
if (!ri->na)
|
2011-04-27 20:30:15 +02:00
|
|
|
|
rtn = ri->func (win, ri->flag, ri->val);
|
2004-01-25 10:00:31 +01:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
rtn = XTB_NOTDEF;
|
|
|
|
|
|
}
|
|
|
|
|
|
return rtn;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_bt_new(win, text, func, val, frame)
|
|
|
|
|
|
Window win; /* Parent window */
|
|
|
|
|
|
char *text; /* Text in button */
|
|
|
|
|
|
|
|
|
|
|
|
FNPTR(func, xtb_hret, (Window, int, xtb_data)); /* Callback */
|
|
|
|
|
|
xtb_data val; /* User data */
|
|
|
|
|
|
xtb_frame *frame; /* Size (RETURN) */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Makes a new button under `win' with the text `text'. The
|
|
|
|
|
|
* window, size, and position of the button are returned in `frame'.
|
|
|
|
|
|
* The initial position is always (0, 0). When the
|
|
|
|
|
|
* button is pressed, `func' will be called with the button
|
|
|
|
|
|
* window, the current state of the button, and `val'.
|
|
|
|
|
|
* It is up to `func' to change the state of the button (if desired).
|
|
|
|
|
|
* The routine should return XTB_HANDLED normally and XTB_STOP if the
|
|
|
|
|
|
* dialog should stop. The window will be automatically mapped.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XCharStruct bb;
|
|
|
|
|
|
struct b_info *info;
|
|
|
|
|
|
int dir,
|
|
|
|
|
|
ascent,
|
|
|
|
|
|
descent;
|
|
|
|
|
|
|
|
|
|
|
|
XTextExtents(norm_font, text, strlen(text), &dir, &ascent, &descent, &bb);
|
|
|
|
|
|
frame->width = bb.width + 2 * BT_HPAD;
|
|
|
|
|
|
frame->height = norm_font->ascent + norm_font->descent + BT_VPAD + BT_LPAD;
|
|
|
|
|
|
frame->x_loc = frame->y_loc = 0;
|
|
|
|
|
|
frame->win = XCreateSimpleWindow(t_disp, win,
|
|
|
|
|
|
frame->x_loc, frame->y_loc,
|
|
|
|
|
|
frame->width, frame->height,
|
|
|
|
|
|
BT_BRDR, norm_pix, back_pix);
|
|
|
|
|
|
XSelectInput(t_disp, frame->win, ExposureMask |
|
|
|
|
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
|
|
|
|
EnterWindowMask | LeaveWindowMask);
|
|
|
|
|
|
info = (struct b_info *) Malloc(sizeof(struct b_info));
|
|
|
|
|
|
info->func = func;
|
|
|
|
|
|
info->text = STRDUP(text);
|
|
|
|
|
|
info->flag = 0;
|
|
|
|
|
|
info->na = 0;
|
|
|
|
|
|
info->val = val;
|
|
|
|
|
|
info->line_y = frame->height - 2;
|
|
|
|
|
|
info->line_w = frame->width - 2 * BT_HPAD;
|
|
|
|
|
|
xtb_register(frame->win, bt_h, (xtb_data) info);
|
|
|
|
|
|
XMapWindow(t_disp, frame->win);
|
|
|
|
|
|
frame->width += (2 * BT_BRDR);
|
|
|
|
|
|
frame->height += (2 * BT_BRDR);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
xtb_bt_get(win, stuff, na)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
xtb_data *stuff;
|
|
|
|
|
|
int *na;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Returns the state of button `win'. If provided, the button
|
|
|
|
|
|
* specific info is returned in `info' and the active state
|
|
|
|
|
|
* of the button is returned in `na'.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct b_info *info = (struct b_info *) xtb_lookup(win);
|
|
|
|
|
|
|
|
|
|
|
|
if (stuff)
|
|
|
|
|
|
*stuff = info->val;
|
|
|
|
|
|
if (na)
|
|
|
|
|
|
*na = info->na;
|
|
|
|
|
|
return info->flag;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
xtb_bt_set(win, val, stuff, na)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
int val;
|
|
|
|
|
|
xtb_data stuff;
|
|
|
|
|
|
int na;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Changes the value of a button and returns the new state.
|
|
|
|
|
|
* The button is drawn. If set, the button specific info
|
|
|
|
|
|
* will be set to `info'. This doesn't allow you to set
|
|
|
|
|
|
* the state to zero, but that may not be important. If
|
|
|
|
|
|
* `na' is non-zero, the button will be deactivated (no
|
|
|
|
|
|
* activity will be allowed). The change in button appearance
|
|
|
|
|
|
* will be immediate.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct b_info *info = (struct b_info *) xtb_lookup(win);
|
|
|
|
|
|
|
|
|
|
|
|
info->flag = (val != 0);
|
|
|
|
|
|
info->na = (na != 0);
|
|
|
|
|
|
if (stuff)
|
|
|
|
|
|
info->val = stuff;
|
|
|
|
|
|
bt_draw(win, info);
|
|
|
|
|
|
XFlush(t_disp);
|
|
|
|
|
|
return info->flag;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_bt_del(win, info)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
xtb_data *info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Deletes the button `win' and returns the user defined information
|
|
|
|
|
|
* in `info' for destruction.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct b_info *bi;
|
|
|
|
|
|
|
|
|
|
|
|
if (xtb_unregister(win, (xtb_data *) & bi)) {
|
|
|
|
|
|
*info = bi->val;
|
|
|
|
|
|
Free((char *) bi->text);
|
|
|
|
|
|
Free((char *) bi);
|
|
|
|
|
|
XDestroyWindow(t_disp, win);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BR_XPAD 2
|
|
|
|
|
|
#define BR_YPAD 2
|
|
|
|
|
|
#define BR_INTER 2
|
|
|
|
|
|
|
|
|
|
|
|
struct br_info {
|
|
|
|
|
|
Window main_win; /* Main button row */
|
|
|
|
|
|
int which_one; /* Which button is on */
|
|
|
|
|
|
int btn_cnt; /* How many buttons */
|
|
|
|
|
|
FNPTR(func, xtb_hret, (Window win, int prev, int this, xtb_data val));
|
|
|
|
|
|
xtb_data val; /* User data */
|
|
|
|
|
|
Window *btns; /* Button windows */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
|
static xtb_hret
|
|
|
|
|
|
br_h(win, val, info)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
int val;
|
|
|
|
|
|
xtb_data info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* This handles events for button rows. When a button is pressed,
|
|
|
|
|
|
* it turns off the button selected in `which_one' and turns itself
|
|
|
|
|
|
* on.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct br_info *real_info = (struct br_info *) info;
|
|
|
|
|
|
int i,
|
|
|
|
|
|
prev;
|
|
|
|
|
|
|
|
|
|
|
|
prev = real_info->which_one;
|
|
|
|
|
|
if ((prev >= 0) && (prev < real_info->btn_cnt)) {
|
|
|
|
|
|
(void) xtb_bt_set(real_info->btns[prev], 0, (xtb_data) 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < real_info->btn_cnt; i++) {
|
|
|
|
|
|
if (win == real_info->btns[i]) {
|
|
|
|
|
|
real_info->which_one = i;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
(void) xtb_bt_set(win, 1, (xtb_data) 0, 0);
|
|
|
|
|
|
/* Callback */
|
|
|
|
|
|
if (real_info->func) {
|
2011-04-27 20:30:15 +02:00
|
|
|
|
return real_info->func (real_info->main_win,
|
2004-01-25 10:00:31 +01:00
|
|
|
|
prev, real_info->which_one,
|
|
|
|
|
|
real_info->val);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
return XTB_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_br_new(win, cnt, lbls, init, func, val, frame)
|
|
|
|
|
|
Window win; /* Parent window */
|
|
|
|
|
|
int cnt; /* Count of buttons */
|
|
|
|
|
|
char *lbls[]; /* Button labels */
|
|
|
|
|
|
int init; /* Initial button */
|
|
|
|
|
|
|
|
|
|
|
|
FNPTR(func, xtb_hret, (Window, int, int, xtb_data)); /* Callback */
|
|
|
|
|
|
xtb_data val; /* User data */
|
|
|
|
|
|
xtb_frame *frame; /* Returned size */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* This routine makes a new row of buttons in the window `win'
|
|
|
|
|
|
* and returns a frame containing all of these buttons. These
|
|
|
|
|
|
* buttons are designed so that only one of them will be active
|
|
|
|
|
|
* at a time. Initially, button `init' will be activated (if
|
|
|
|
|
|
* init is less than zero, none will be initially activated).
|
|
|
|
|
|
* Whenever a button is pushed, `func' will be called with the
|
|
|
|
|
|
* button row window, the index of the previous button (-1 if
|
|
|
|
|
|
* none), the index of the current button, and the user data, `val'.
|
|
|
|
|
|
* The function is optional (if zero, no function will be called).
|
|
|
|
|
|
* The size of the row is returned in `frame'. The window
|
|
|
|
|
|
* will be automatically mapped. Initially, the window containing
|
|
|
|
|
|
* the buttons will be placed at 0,0 in the parent window.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct br_info *info;
|
|
|
|
|
|
xtb_frame sub_frame;
|
|
|
|
|
|
int i,
|
|
|
|
|
|
x,
|
|
|
|
|
|
y;
|
|
|
|
|
|
|
|
|
|
|
|
frame->width = frame->height = 0;
|
|
|
|
|
|
frame->x_loc = frame->y_loc = 0;
|
|
|
|
|
|
frame->win = XCreateSimpleWindow(t_disp, win, 0, 0, 1, 1,
|
|
|
|
|
|
0, back_pix, back_pix);
|
|
|
|
|
|
info = (struct br_info *) Malloc(sizeof(struct br_info));
|
|
|
|
|
|
info->main_win = frame->win;
|
|
|
|
|
|
info->btns = (Window *) Malloc((unsigned) (sizeof(Window) * cnt));
|
|
|
|
|
|
info->btn_cnt = cnt;
|
|
|
|
|
|
info->which_one = init;
|
|
|
|
|
|
info->func = func;
|
|
|
|
|
|
info->val = val;
|
|
|
|
|
|
/* the handler is used simply to get information out */
|
|
|
|
|
|
xtb_register(frame->win, (xtb_hret(*) ()) 0, (xtb_data) info);
|
|
|
|
|
|
x = BR_XPAD;
|
|
|
|
|
|
y = BR_YPAD;
|
|
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
|
|
|
|
xtb_bt_new(frame->win, lbls[i], br_h, (xtb_data) info, &sub_frame);
|
|
|
|
|
|
info->btns[i] = sub_frame.win;
|
|
|
|
|
|
XMoveWindow(t_disp, info->btns[i], x, y);
|
|
|
|
|
|
x += (BR_INTER + sub_frame.width);
|
|
|
|
|
|
if (sub_frame.height > frame->height)
|
|
|
|
|
|
frame->height = sub_frame.height;
|
|
|
|
|
|
if (i == init)
|
|
|
|
|
|
(void) xtb_bt_set(info->btns[i], 1, (xtb_data) 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
frame->width = x - BR_INTER + BR_XPAD;
|
|
|
|
|
|
frame->height += (2 * BR_YPAD);
|
|
|
|
|
|
XResizeWindow(t_disp, frame->win, frame->width, frame->height);
|
|
|
|
|
|
XMapWindow(t_disp, frame->win);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
xtb_br_get(win)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* This routine returns the index of the currently selected item of
|
|
|
|
|
|
* the button row given by the window `win'. Note: no checking
|
|
|
|
|
|
* is done to make sure `win' is a button row.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct br_info *info = (struct br_info *) xtb_lookup(win);
|
|
|
|
|
|
|
|
|
|
|
|
return info->which_one;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_br_del(win)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Deletes a button row. All resources are reclaimed.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct br_info *info;
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
if (xtb_unregister(win, (xtb_data *) & info)) {
|
|
|
|
|
|
for (i = 0; i < info->btn_cnt; i++) {
|
|
|
|
|
|
xtb_bt_del(info->btns[i], (xtb_data *) & info);
|
|
|
|
|
|
}
|
|
|
|
|
|
Free((char *) info->btns);
|
|
|
|
|
|
Free((char *) info);
|
|
|
|
|
|
XDestroyWindow(t_disp, win);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Text widget */
|
|
|
|
|
|
|
|
|
|
|
|
#define TO_HPAD 1
|
|
|
|
|
|
#define TO_VPAD 1
|
|
|
|
|
|
|
|
|
|
|
|
struct to_info {
|
|
|
|
|
|
char *text; /* Text to display */
|
|
|
|
|
|
XFontStruct *ft; /* Font to use */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
to_draw(win, ri)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
struct to_info *ri;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Draws the text for a widget
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XDrawImageString(t_disp, win,
|
|
|
|
|
|
set_gc(win, norm_pix, back_pix, ri->ft->fid, 0),
|
|
|
|
|
|
TO_HPAD, TO_VPAD + ri->ft->ascent,
|
|
|
|
|
|
ri->text, strlen(ri->text));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static xtb_hret
|
|
|
|
|
|
to_h(evt, info)
|
|
|
|
|
|
XEvent *evt;
|
|
|
|
|
|
xtb_data info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Handles text widget events
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
Window win = evt->xany.window;
|
|
|
|
|
|
struct to_info *ri = (struct to_info *) info;
|
|
|
|
|
|
|
|
|
|
|
|
switch (evt->type) {
|
|
|
|
|
|
case Expose:
|
|
|
|
|
|
to_draw(win, ri);
|
|
|
|
|
|
return XTB_HANDLED;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return XTB_NOTDEF;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_to_new(win, text, ft, frame)
|
|
|
|
|
|
Window win; /* Parent window */
|
|
|
|
|
|
char *text; /* Text */
|
|
|
|
|
|
XFontStruct *ft; /* Font to use */
|
|
|
|
|
|
xtb_frame *frame; /* Returned size */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Makes a new text widget under `win' with the text `text'.
|
|
|
|
|
|
* The size of the widget is returned in `w' and `h'. The
|
|
|
|
|
|
* window is created and mapped at 0,0 in `win'. The font
|
|
|
|
|
|
* used for the text is given in `ft'.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct to_info *info;
|
|
|
|
|
|
|
|
|
|
|
|
frame->width = XTextWidth(ft, text, strlen(text)) + 2 * TO_HPAD;
|
|
|
|
|
|
frame->height = ft->ascent + ft->descent + 2 * TO_VPAD;
|
|
|
|
|
|
frame->x_loc = frame->y_loc = 0;
|
|
|
|
|
|
frame->win = XCreateSimpleWindow(t_disp, win, 0, 0,
|
|
|
|
|
|
frame->width, frame->height, 0,
|
|
|
|
|
|
back_pix, back_pix);
|
|
|
|
|
|
XSelectInput(t_disp, frame->win, ExposureMask);
|
|
|
|
|
|
info = (struct to_info *) Malloc(sizeof(struct to_info));
|
|
|
|
|
|
info->text = STRDUP(text);
|
|
|
|
|
|
info->ft = ft;
|
|
|
|
|
|
xtb_register(frame->win, to_h, (xtb_data) info);
|
|
|
|
|
|
XMapWindow(t_disp, frame->win);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_to_del(win)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Deletes an output only text widget.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct to_info *info;
|
|
|
|
|
|
|
|
|
|
|
|
if (xtb_unregister(win, (xtb_data *) & info)) {
|
|
|
|
|
|
if (info->text)
|
|
|
|
|
|
Free((char *) info->text);
|
|
|
|
|
|
Free((char *) info);
|
|
|
|
|
|
XDestroyWindow(t_disp, win);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Input text widget
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#define TI_HPAD 2
|
|
|
|
|
|
#define TI_VPAD 2
|
|
|
|
|
|
#define TI_LPAD 3
|
|
|
|
|
|
#define TI_BRDR 2
|
|
|
|
|
|
#define TI_CRSP 1
|
|
|
|
|
|
|
|
|
|
|
|
struct ti_info {
|
|
|
|
|
|
FNPTR(func, xtb_hret, (Window win, int ch, char *textcopy, xtb_data * val));
|
|
|
|
|
|
/* Function to call */
|
|
|
|
|
|
int maxlen; /* Maximum characters */
|
|
|
|
|
|
int curidx; /* Current index pos */
|
|
|
|
|
|
int curxval; /* Current draw loc */
|
|
|
|
|
|
char text[MAXCHBUF]; /* Current text array */
|
|
|
|
|
|
int line_y,
|
|
|
|
|
|
line_w; /* Entry/Exit line */
|
|
|
|
|
|
int focus_flag; /* If on, we have focus */
|
|
|
|
|
|
xtb_data val; /* User info */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
|
text_width(font, str, len)
|
|
|
|
|
|
XFontStruct *font; /* What font */
|
|
|
|
|
|
char *str; /* Character array */
|
|
|
|
|
|
int len; /* Length of array */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Returns the width of a string using XTextExtents.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XCharStruct bb;
|
|
|
|
|
|
int dir,
|
|
|
|
|
|
ascent,
|
|
|
|
|
|
descent;
|
|
|
|
|
|
|
|
|
|
|
|
XTextExtents(font, str, len, &dir, &ascent, &descent, &bb);
|
|
|
|
|
|
return bb.width;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
ti_cursor_on(win, ri)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
struct ti_info *ri;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Draws the cursor for the window. Uses pixel `pix'.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XFillRectangle(t_disp, win,
|
|
|
|
|
|
set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
|
|
|
|
|
|
ri->curxval + TI_HPAD + TI_CRSP, TI_VPAD,
|
|
|
|
|
|
(ri->focus_flag ? 2 : 1),
|
|
|
|
|
|
norm_font->ascent + norm_font->descent - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
ti_cursor_off(win, ri)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
struct ti_info *ri;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Draws the cursor for the window. Uses pixel `pix'.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XFillRectangle(t_disp, win,
|
|
|
|
|
|
set_gc(win, back_pix, back_pix, norm_font->fid, 0),
|
|
|
|
|
|
ri->curxval + TI_HPAD + TI_CRSP, TI_VPAD,
|
|
|
|
|
|
(ri->focus_flag ? 2 : 1),
|
|
|
|
|
|
norm_font->ascent + norm_font->descent - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
ti_draw(win, ri, c_flag)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
struct ti_info *ri;
|
|
|
|
|
|
int c_flag;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Draws the indicated text widget. This includes drawing the
|
|
|
|
|
|
* text and cursor. If `c_flag' is set, the window will
|
|
|
|
|
|
* be cleared first.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
if (c_flag)
|
|
|
|
|
|
XClearWindow(t_disp, win);
|
|
|
|
|
|
/* Text */
|
|
|
|
|
|
XDrawImageString(t_disp, win,
|
|
|
|
|
|
set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
|
|
|
|
|
|
TI_HPAD, TI_VPAD + norm_font->ascent,
|
|
|
|
|
|
ri->text, strlen(ri->text));
|
|
|
|
|
|
/* Cursor */
|
|
|
|
|
|
ti_cursor_on(win, ri);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
ti_line(win, ri, pix)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
struct ti_info *ri;
|
|
|
|
|
|
unsigned long pix;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Draws a status line beneath the text in a text widget to indicate
|
|
|
|
|
|
* the user has moved into the text field.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XDrawLine(t_disp, win,
|
|
|
|
|
|
set_gc(win, pix, back_pix, norm_font->fid, 0),
|
|
|
|
|
|
TI_HPAD, ri->line_y, TI_HPAD + ri->line_w, ri->line_y);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* For debugging */
|
|
|
|
|
|
focus_evt(evt)
|
|
|
|
|
|
XEvent *evt;
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (evt->xfocus.mode) {
|
|
|
|
|
|
case NotifyNormal:
|
|
|
|
|
|
printf("NotifyNormal");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyGrab:
|
|
|
|
|
|
printf("NotifyGrab");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyUngrab:
|
|
|
|
|
|
printf("NotifyUngrab");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
printf(", detail = ");
|
|
|
|
|
|
switch (evt->xfocus.detail) {
|
|
|
|
|
|
case NotifyAncestor:
|
|
|
|
|
|
printf("NotifyAncestor");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyVirtual:
|
|
|
|
|
|
printf("NotifyVirtual");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyInferior:
|
|
|
|
|
|
printf("NotifyInferior");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyNonlinear:
|
|
|
|
|
|
printf("NotifyNonLinear");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyNonlinearVirtual:
|
|
|
|
|
|
printf("NotifyNonLinearVirtual");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyPointer:
|
|
|
|
|
|
printf("NotifyPointer");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyPointerRoot:
|
|
|
|
|
|
printf("NotifyPointerRoot");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NotifyDetailNone:
|
|
|
|
|
|
printf("NotifyDetailNone");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xtb_hret
|
|
|
|
|
|
ti_h(evt, info)
|
|
|
|
|
|
XEvent *evt;
|
|
|
|
|
|
xtb_data info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Handles text input events.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
Window win = evt->xany.window;
|
|
|
|
|
|
struct ti_info *ri = (struct ti_info *) info;
|
|
|
|
|
|
char keys[MAXKEYS],
|
|
|
|
|
|
textcopy[MAXCHBUF];
|
|
|
|
|
|
xtb_hret rtn = 0;
|
|
|
|
|
|
int nbytes,
|
|
|
|
|
|
i;
|
|
|
|
|
|
|
|
|
|
|
|
switch (evt->type) {
|
|
|
|
|
|
case Expose:
|
|
|
|
|
|
ti_draw(win, ri, 0);
|
|
|
|
|
|
rtn = XTB_HANDLED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case KeyPress:
|
|
|
|
|
|
nbytes = XLookupString(&evt->xkey, keys, MAXKEYS,
|
|
|
|
|
|
(KeySym *) 0, (XComposeStatus *) 0);
|
|
|
|
|
|
for (i = 0; i < nbytes; i++) {
|
|
|
|
|
|
(void) strcpy(textcopy, ri->text);
|
2011-04-27 20:30:15 +02:00
|
|
|
|
if ((rtn = ri->func (win, (int) keys[i],
|
2004-01-25 10:00:31 +01:00
|
|
|
|
textcopy, ri->val)) == XTB_STOP)
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case FocusIn:
|
|
|
|
|
|
focus_evt(evt);
|
|
|
|
|
|
if (evt->xfocus.detail != NotifyPointer) {
|
|
|
|
|
|
ti_cursor_off(win, ri);
|
|
|
|
|
|
ri->focus_flag = 1;
|
|
|
|
|
|
ti_cursor_on(win, ri);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case FocusOut:
|
|
|
|
|
|
focus_evt(evt);
|
|
|
|
|
|
if (evt->xfocus.detail != NotifyPointer) {
|
|
|
|
|
|
ti_cursor_off(win, ri);
|
|
|
|
|
|
ri->focus_flag = 0;
|
|
|
|
|
|
ti_cursor_on(win, ri);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EnterNotify:
|
|
|
|
|
|
ti_line(win, ri, norm_pix);
|
|
|
|
|
|
rtn = XTB_HANDLED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LeaveNotify:
|
|
|
|
|
|
ti_line(win, ri, back_pix);
|
|
|
|
|
|
rtn = XTB_HANDLED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ButtonPress:
|
|
|
|
|
|
/* Wait for release */
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ButtonRelease:
|
|
|
|
|
|
/* Set input focus */
|
|
|
|
|
|
XSetInputFocus(t_disp, win, RevertToParent, CurrentTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
rtn = XTB_NOTDEF;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return rtn;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_ti_new(win, text, maxchar, func, val, frame)
|
|
|
|
|
|
Window win; /* Parent window */
|
|
|
|
|
|
char *text; /* Initial text */
|
|
|
|
|
|
int maxchar; /* Maximum characters */
|
|
|
|
|
|
|
|
|
|
|
|
FNPTR(func, xtb_hret, (Window, int, char *, xtb_data *)); /* Callback */
|
|
|
|
|
|
xtb_data val; /* User data */
|
|
|
|
|
|
xtb_frame *frame; /* Returned size */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* This routine creates a new editable text widget under `win'
|
|
|
|
|
|
* with the initial text `text'. The widget contains only
|
|
|
|
|
|
* one line of text which cannot exceed `maxchar' characters.
|
|
|
|
|
|
* The size of the widget is returned in `frame'. Each
|
|
|
|
|
|
* time a key is pressed in the window, `func' will be called
|
|
|
|
|
|
* with the window, the character, a copy of the text, and `val'.
|
|
|
|
|
|
* The state of the widget can be changed by the routines below.
|
|
|
|
|
|
* May set window to zero if the maximum overall character width
|
|
|
|
|
|
* (MAXCHBUF) is exceeded.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct ti_info *info;
|
|
|
|
|
|
|
|
|
|
|
|
if (maxchar >= MAXCHBUF) {
|
|
|
|
|
|
frame->win = (Window) 0;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
frame->width = XTextWidth(norm_font, "8", 1) * maxchar + 2 * TI_HPAD;
|
|
|
|
|
|
frame->height = norm_font->ascent + norm_font->descent + TI_VPAD + TI_LPAD;
|
|
|
|
|
|
frame->x_loc = frame->y_loc = 0;
|
|
|
|
|
|
frame->win = XCreateSimpleWindow(t_disp, win, 0, 0,
|
|
|
|
|
|
frame->width, frame->height, TI_BRDR,
|
|
|
|
|
|
norm_pix, back_pix);
|
|
|
|
|
|
XSelectInput(t_disp, frame->win, ExposureMask | KeyPressMask |
|
|
|
|
|
|
EnterWindowMask | LeaveWindowMask |
|
|
|
|
|
|
FocusChangeMask | ButtonPressMask |
|
|
|
|
|
|
ButtonReleaseMask);
|
|
|
|
|
|
info = (struct ti_info *) Malloc(sizeof(struct ti_info));
|
|
|
|
|
|
info->func = func;
|
|
|
|
|
|
info->val = val;
|
|
|
|
|
|
info->maxlen = maxchar;
|
|
|
|
|
|
if (text)
|
|
|
|
|
|
(void) strcpy(info->text, text);
|
|
|
|
|
|
else
|
|
|
|
|
|
info->text[0] = '\0';
|
|
|
|
|
|
info->curidx = strlen(info->text);
|
|
|
|
|
|
info->curxval = text_width(norm_font, info->text, info->curidx);
|
|
|
|
|
|
info->line_y = frame->height - 2;
|
|
|
|
|
|
info->line_w = frame->width - 2 * TI_HPAD;
|
|
|
|
|
|
info->focus_flag = 0;
|
|
|
|
|
|
xtb_register(frame->win, ti_h, (xtb_data) info);
|
|
|
|
|
|
XMapWindow(t_disp, frame->win);
|
|
|
|
|
|
frame->width += (2 * TI_BRDR);
|
|
|
|
|
|
frame->height += (2 * TI_BRDR);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_ti_get(win, text, val)
|
|
|
|
|
|
Window win; /* Widget widnow */
|
|
|
|
|
|
char text[MAXCHBUF]; /* Filled in text */
|
|
|
|
|
|
xtb_data *val; /* User info */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* This routine returns the information associated with text
|
|
|
|
|
|
* widget `win'. The text is filled into the passed buffer
|
|
|
|
|
|
* `text' which should be MAXCHBUF characters in size. If
|
|
|
|
|
|
* `val' is non-zero, the user supplied info is returned there.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct ti_info *info = (struct ti_info *) xtb_lookup(win);
|
|
|
|
|
|
|
|
|
|
|
|
if (val)
|
|
|
|
|
|
*val = info->val;
|
|
|
|
|
|
(void) strcpy(text, info->text);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
xtb_ti_set(win, text, val)
|
|
|
|
|
|
Window win; /* Widget window */
|
|
|
|
|
|
char *text; /* Replacement text */
|
|
|
|
|
|
xtb_data val; /* User info */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* This routine sets the text of a text widget. The widget
|
|
|
|
|
|
* will be redrawn. Note: for incremental changes, ti_ins and
|
|
|
|
|
|
* ti_dch should be used. If `val' is non-zero, it will replace
|
|
|
|
|
|
* the user information for the widget. The widget is redrawn.
|
|
|
|
|
|
* Will return zero if `text' is too long.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct ti_info *info = (struct ti_info *) xtb_lookup(win);
|
|
|
|
|
|
int newlen;
|
|
|
|
|
|
|
|
|
|
|
|
if (text) {
|
|
|
|
|
|
if ((newlen = strlen(text)) >= info->maxlen)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
newlen = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
info->curidx = newlen;
|
|
|
|
|
|
if (text)
|
|
|
|
|
|
(void) strcpy(info->text, text);
|
|
|
|
|
|
else
|
|
|
|
|
|
info->text[0] = '\0';
|
|
|
|
|
|
info->curxval = text_width(norm_font, info->text, info->curidx);
|
|
|
|
|
|
if (val)
|
|
|
|
|
|
info->val = val;
|
|
|
|
|
|
ti_draw(win, info, 1);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
xtb_ti_ins(win, ch)
|
|
|
|
|
|
Window win; /* Widget window */
|
|
|
|
|
|
int ch; /* Character */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Inserts the character `ch' onto the end of the text for `win'.
|
|
|
|
|
|
* Will return zero if there isn't any more room left. Does
|
|
|
|
|
|
* all appropriate display updates.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct ti_info *info = (struct ti_info *) xtb_lookup(win);
|
|
|
|
|
|
char lstr[1];
|
|
|
|
|
|
|
|
|
|
|
|
if (info->curidx >= info->maxlen - 1)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
info->text[info->curidx] = ch;
|
|
|
|
|
|
info->text[info->curidx + 1] = '\0';
|
|
|
|
|
|
/* Turn off cursor */
|
|
|
|
|
|
ti_cursor_off(win, info);
|
|
|
|
|
|
/* Text */
|
|
|
|
|
|
lstr[0] = (char) ch;
|
|
|
|
|
|
XDrawImageString(t_disp, win,
|
|
|
|
|
|
set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
|
|
|
|
|
|
info->curxval + TI_HPAD, TI_VPAD + norm_font->ascent,
|
|
|
|
|
|
lstr, 1);
|
|
|
|
|
|
info->curidx += 1;
|
|
|
|
|
|
info->curxval += text_width(norm_font, lstr, 1);
|
|
|
|
|
|
ti_cursor_on(win, info);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
xtb_ti_dch(win)
|
|
|
|
|
|
Window win; /* Widget window */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Deletes the character at the end of the text for `win'. Will
|
|
|
|
|
|
* return zero if there aren't any characters to delete. Does
|
|
|
|
|
|
* all appropriate display updates.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct ti_info *info = (struct ti_info *) xtb_lookup(win);
|
|
|
|
|
|
int chw;
|
|
|
|
|
|
|
|
|
|
|
|
if (info->curidx == 0)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
/* Wipe out cursor */
|
|
|
|
|
|
ti_cursor_off(win, info);
|
|
|
|
|
|
info->curidx -= 1;
|
|
|
|
|
|
chw = text_width(norm_font, &(info->text[info->curidx]), 1);
|
|
|
|
|
|
info->curxval -= chw;
|
|
|
|
|
|
/* Wipe out character */
|
|
|
|
|
|
XClearArea(t_disp, win, info->curxval + TI_HPAD, TI_VPAD,
|
|
|
|
|
|
(unsigned int) chw + 1,
|
|
|
|
|
|
(unsigned int) norm_font->ascent + norm_font->descent,
|
|
|
|
|
|
False);
|
|
|
|
|
|
info->text[info->curidx] = '\0';
|
|
|
|
|
|
ti_cursor_on(win, info);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_ti_del(win, info)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
xtb_data *info;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Deletes an input text widget. User defined data is returned in `info'.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
struct ti_info *ti;
|
|
|
|
|
|
|
|
|
|
|
|
if (xtb_unregister(win, (xtb_data *) & ti)) {
|
|
|
|
|
|
*info = ti->val;
|
|
|
|
|
|
Free((char *) ti);
|
|
|
|
|
|
XDestroyWindow(t_disp, win);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Simple colored output frame - usually used for drawing lines
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_bk_new(win, width, height, frame)
|
|
|
|
|
|
Window win; /* Parent window */
|
|
|
|
|
|
unsigned width,
|
|
|
|
|
|
height; /* Size */
|
|
|
|
|
|
xtb_frame *frame; /* Returned size */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* This routine creates a new frame that displays a block
|
|
|
|
|
|
* of color whose size is given by `width' and `height'.
|
|
|
|
|
|
* It is usually used to draw lines. No user interaction
|
|
|
|
|
|
* is defined for the frame. The color used is the default
|
|
|
|
|
|
* foreground color set in xtb_init().
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
frame->x_loc = frame->y_loc = 0;
|
|
|
|
|
|
frame->width = width;
|
|
|
|
|
|
frame->height = height;
|
|
|
|
|
|
frame->win = XCreateSimpleWindow(t_disp, win,
|
|
|
|
|
|
frame->x_loc, frame->y_loc,
|
|
|
|
|
|
frame->width, frame->height,
|
|
|
|
|
|
0, norm_pix, norm_pix);
|
|
|
|
|
|
XMapWindow(t_disp, frame->win);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_bk_del(win)
|
|
|
|
|
|
Window win;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Deletes a block frame.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
XDestroyWindow(t_disp, win);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Formatting support
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#define ERROR(msg) printf("%s\n", msg); abort();
|
|
|
|
|
|
|
|
|
|
|
|
xtb_fmt *
|
|
|
|
|
|
xtb_w(w)
|
|
|
|
|
|
xtb_frame *w;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Returns formatting structure for a widget.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
xtb_fmt *ret;
|
|
|
|
|
|
|
|
|
|
|
|
ret = (xtb_fmt *) Malloc((unsigned) sizeof(xtb_fmt));
|
|
|
|
|
|
ret->wid.type = W_TYPE;
|
|
|
|
|
|
ret->wid.w = w;
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VARARGS(xtb_hort, xtb_fmt *, (xtb_just just, int padding, int interspace,...))
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Builds a horizontal structure
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
xtb_fmt *ret,
|
|
|
|
|
|
*val;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __STDC__
|
|
|
|
|
|
va_start(ap, interspace);
|
|
|
|
|
|
#else
|
|
|
|
|
|
xtb_just just;
|
|
|
|
|
|
int padding,
|
|
|
|
|
|
interspace;
|
|
|
|
|
|
|
|
|
|
|
|
va_start(ap);
|
|
|
|
|
|
just = va_arg(ap, xtb_just);
|
|
|
|
|
|
padding = va_arg(ap, int);
|
|
|
|
|
|
interspace = va_arg(ap, int);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
ret = (xtb_fmt *) Malloc((unsigned) sizeof(xtb_fmt));
|
|
|
|
|
|
ret->align.type = A_TYPE;
|
|
|
|
|
|
ret->align.dir = HORIZONTAL;
|
|
|
|
|
|
ret->align.just = just;
|
|
|
|
|
|
ret->align.padding = padding;
|
|
|
|
|
|
ret->align.interspace = interspace;
|
|
|
|
|
|
/* Build array of incoming xtb_fmt structures */
|
|
|
|
|
|
ret->align.ni = 0;
|
|
|
|
|
|
while ((val = va_arg(ap, xtb_fmt *)) != (xtb_fmt *) 0) {
|
|
|
|
|
|
if (ret->align.ni < MAX_BRANCH) {
|
|
|
|
|
|
ret->align.items[ret->align.ni] = val;
|
|
|
|
|
|
ret->align.ni++;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
ERROR("too many branches\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VARARGS(xtb_vert, xtb_fmt *, (xtb_just just, int padding, int interspace,...))
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Builds a vertical structure
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
xtb_fmt *ret,
|
|
|
|
|
|
*val;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __STDC__
|
|
|
|
|
|
va_start(ap, interspace);
|
|
|
|
|
|
#else
|
|
|
|
|
|
xtb_just just;
|
|
|
|
|
|
int padding,
|
|
|
|
|
|
interspace;
|
|
|
|
|
|
|
|
|
|
|
|
va_start(ap);
|
|
|
|
|
|
just = va_arg(ap, xtb_just);
|
|
|
|
|
|
padding = va_arg(ap, int);
|
|
|
|
|
|
interspace = va_arg(ap, int);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
ret = (xtb_fmt *) Malloc((unsigned) sizeof(xtb_fmt));
|
|
|
|
|
|
ret->align.type = A_TYPE;
|
|
|
|
|
|
ret->align.dir = VERTICAL;
|
|
|
|
|
|
ret->align.just = just;
|
|
|
|
|
|
ret->align.padding = padding;
|
|
|
|
|
|
ret->align.interspace = interspace;
|
|
|
|
|
|
/* Build array of incoming xtb_fmt structures */
|
|
|
|
|
|
ret->align.ni = 0;
|
|
|
|
|
|
while ((val = va_arg(ap, xtb_fmt *)) != (xtb_fmt *) 0) {
|
|
|
|
|
|
if (ret->align.ni < MAX_BRANCH) {
|
|
|
|
|
|
ret->align.items[ret->align.ni] = val;
|
|
|
|
|
|
ret->align.ni++;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
ERROR("too many branches\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
xtb_fmt_setpos(def, x, y)
|
|
|
|
|
|
xtb_fmt *def;
|
|
|
|
|
|
int x,
|
|
|
|
|
|
y;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Sets all position fields of widgets in `def' to x,y.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
switch (def->type) {
|
|
|
|
|
|
case W_TYPE:
|
|
|
|
|
|
def->wid.w->x_loc = x;
|
|
|
|
|
|
def->wid.w->y_loc = y;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case A_TYPE:
|
|
|
|
|
|
for (i = 0; i < def->align.ni; i++) {
|
|
|
|
|
|
xtb_fmt_setpos(def->align.items[i], x, y);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
ERROR("bad type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
xtb_fmt_addpos(def, x, y)
|
|
|
|
|
|
xtb_fmt *def;
|
|
|
|
|
|
int x,
|
|
|
|
|
|
y;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Adds the offset specified to all position fields of widgets in `def'.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
switch (def->type) {
|
|
|
|
|
|
case W_TYPE:
|
|
|
|
|
|
def->wid.w->x_loc += x;
|
|
|
|
|
|
def->wid.w->y_loc += y;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case A_TYPE:
|
|
|
|
|
|
for (i = 0; i < def->align.ni; i++) {
|
|
|
|
|
|
xtb_fmt_addpos(def->align.items[i], x, y);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
ERROR("bad type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
xtb_fmt_hort(nd, defs, widths, heights, just, pad, inter, rw, rh)
|
|
|
|
|
|
int nd; /* Number of children */
|
|
|
|
|
|
xtb_fmt *defs[]; /* Definitions themselves */
|
|
|
|
|
|
unsigned int widths[]; /* Widths of children */
|
|
|
|
|
|
unsigned int heights[]; /* Heights of children */
|
|
|
|
|
|
xtb_just just; /* Justification */
|
|
|
|
|
|
int pad,
|
|
|
|
|
|
inter; /* Padding and interspace */
|
|
|
|
|
|
unsigned int *rw,
|
|
|
|
|
|
*rh; /* Returned size */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Formats items horizontally subject to the widths and heights
|
|
|
|
|
|
* of the items passed.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
int max_height = 0;
|
|
|
|
|
|
int tot_width = 0;
|
|
|
|
|
|
int xspot;
|
|
|
|
|
|
|
|
|
|
|
|
/* Find parameters */
|
|
|
|
|
|
for (i = 0; i < nd; i++) {
|
|
|
|
|
|
if (heights[i] > max_height)
|
|
|
|
|
|
max_height = heights[i];
|
|
|
|
|
|
tot_width += widths[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Place items -- assumes center justification */
|
|
|
|
|
|
xspot = pad;
|
|
|
|
|
|
for (i = 0; i < nd; i++) {
|
|
|
|
|
|
switch (just) {
|
|
|
|
|
|
case XTB_TOP:
|
|
|
|
|
|
xtb_fmt_addpos(defs[i], xspot, pad);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XTB_BOTTOM:
|
|
|
|
|
|
xtb_fmt_addpos(defs[i], xspot, max_height - heights[i] + pad);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XTB_CENTER:
|
|
|
|
|
|
default:
|
|
|
|
|
|
/* Everyone else center */
|
|
|
|
|
|
xtb_fmt_addpos(defs[i], xspot, (max_height - heights[i]) / 2 + pad);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
xspot += (widths[i] + inter);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Figure out resulting size */
|
|
|
|
|
|
*rw = tot_width + (nd - 1) * inter + (2 * pad);
|
|
|
|
|
|
*rh = max_height + (2 * pad);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
xtb_fmt_vert(nd, defs, widths, heights, just, pad, inter, rw, rh)
|
|
|
|
|
|
int nd; /* Number of children */
|
|
|
|
|
|
xtb_fmt *defs[]; /* Definitions themselves */
|
|
|
|
|
|
unsigned int widths[]; /* Widths of children */
|
|
|
|
|
|
unsigned int heights[]; /* Heights of children */
|
|
|
|
|
|
xtb_just just; /* Justification */
|
|
|
|
|
|
int pad,
|
|
|
|
|
|
inter; /* Padding and interspace */
|
|
|
|
|
|
unsigned int *rw,
|
|
|
|
|
|
*rh; /* Returned size */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Formats items vertically subject to the widths and heights
|
|
|
|
|
|
* of the items passed.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
int max_width = 0;
|
|
|
|
|
|
int tot_height = 0;
|
|
|
|
|
|
int yspot;
|
|
|
|
|
|
|
|
|
|
|
|
/* Find parameters */
|
|
|
|
|
|
for (i = 0; i < nd; i++) {
|
|
|
|
|
|
if (widths[i] > max_width)
|
|
|
|
|
|
max_width = widths[i];
|
|
|
|
|
|
tot_height += heights[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Place items -- assumes center justification */
|
|
|
|
|
|
yspot = pad;
|
|
|
|
|
|
for (i = 0; i < nd; i++) {
|
|
|
|
|
|
switch (just) {
|
|
|
|
|
|
case XTB_LEFT:
|
|
|
|
|
|
xtb_fmt_addpos(defs[i], pad, yspot);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XTB_RIGHT:
|
|
|
|
|
|
xtb_fmt_addpos(defs[i], max_width - widths[i] + pad, yspot);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XTB_CENTER:
|
|
|
|
|
|
default:
|
|
|
|
|
|
/* Everyone else center */
|
|
|
|
|
|
xtb_fmt_addpos(defs[i], (max_width - widths[i]) / 2 + pad, yspot);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
yspot += (heights[i] + inter);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Figure out resulting size */
|
|
|
|
|
|
*rw = max_width + (2 * pad);
|
|
|
|
|
|
*rh = tot_height + (nd - 1) * inter + (2 * pad);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
xtb_fmt_top(def, w, h)
|
|
|
|
|
|
xtb_fmt *def;
|
|
|
|
|
|
unsigned *w,
|
|
|
|
|
|
*h;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Recursive portion of formatter
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned widths[MAX_BRANCH];
|
|
|
|
|
|
unsigned heights[MAX_BRANCH];
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
switch (def->type) {
|
|
|
|
|
|
case A_TYPE:
|
|
|
|
|
|
/* Formatting directive */
|
|
|
|
|
|
/* place children and determine sizes */
|
|
|
|
|
|
for (i = 0; i < def->align.ni; i++) {
|
|
|
|
|
|
xtb_fmt_top(def->align.items[i], &(widths[i]), &(heights[i]));
|
|
|
|
|
|
}
|
|
|
|
|
|
/* now format based on direction */
|
|
|
|
|
|
switch (def->align.dir) {
|
|
|
|
|
|
case HORIZONTAL:
|
|
|
|
|
|
xtb_fmt_hort(def->align.ni, def->align.items, widths, heights,
|
|
|
|
|
|
def->align.just, def->align.padding,
|
|
|
|
|
|
def->align.interspace, w, h);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VERTICAL:
|
|
|
|
|
|
xtb_fmt_vert(def->align.ni, def->align.items, widths, heights,
|
|
|
|
|
|
def->align.just, def->align.padding,
|
|
|
|
|
|
def->align.interspace, w, h);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
ERROR("bad direction");
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case W_TYPE:
|
|
|
|
|
|
/* Simple widget - return size */
|
|
|
|
|
|
*w = def->wid.w->width;
|
|
|
|
|
|
*h = def->wid.w->height;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
ERROR("bad type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
static void
|
|
|
|
|
|
xtb_fmt_debug(def)
|
|
|
|
|
|
xtb_fmt *def;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Dumps formatting structure for debugging purposes.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
switch (def->type) {
|
|
|
|
|
|
case W_TYPE:
|
|
|
|
|
|
printf("%d %d %d %d\n",
|
|
|
|
|
|
def->wid.w->x_loc, def->wid.w->y_loc,
|
|
|
|
|
|
def->wid.w->width, def->wid.w->height);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case A_TYPE:
|
|
|
|
|
|
for (i = 0; i < def->align.ni; i++) {
|
|
|
|
|
|
xtb_fmt_debug(def->align.items[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
ERROR("bad type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
xtb_fmt *
|
|
|
|
|
|
xtb_fmt_do(def, w, h)
|
|
|
|
|
|
xtb_fmt *def;
|
|
|
|
|
|
unsigned *w,
|
|
|
|
|
|
*h;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Actually does formatting
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
/* First zero out all positions */
|
|
|
|
|
|
xtb_fmt_setpos(def, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
/* Now call recursive portion */
|
|
|
|
|
|
xtb_fmt_top(def, w, h);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
xtb_fmt_debug(def);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
return def;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_fmt_free(def)
|
|
|
|
|
|
xtb_fmt *def;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Frees resources associated with formatting routines
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
if (def->type == A_TYPE) {
|
|
|
|
|
|
for (i = 0; i < def->align.ni; i++) {
|
|
|
|
|
|
xtb_fmt_free(def->align.items[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Free((char *) def);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
xtb_mv_frames(nf, frames)
|
|
|
|
|
|
int nf; /* Number of frames */
|
|
|
|
|
|
xtb_frame frames[]; /* Array of frames */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Moves frames to the location indicated in the frame
|
|
|
|
|
|
* structure for each item.
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < nf; i++) {
|
|
|
|
|
|
XMoveWindow(t_disp, frames[i].win, frames[i].x_loc, frames[i].y_loc);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|