diff --git a/libami/Makefile.in b/libami/Makefile.in index ddc82c4..c53816f 100644 --- a/libami/Makefile.in +++ b/libami/Makefile.in @@ -21,12 +21,12 @@ RM = -rm -f OBJS = drawinfo.o module.o broker.o eventdispatcher.o mdscreen.o \ mdicon.o mdwindow.o kbdsupport.o hotkey.o \ lists.o readargs.o iconlib.o iconutil.o error.o strutil.o \ - iffparse.o + iffparse.o gadget_button.o gadget_textbox.o gadget_textinput.o SRCS = drawinfo.c module.c broker.c eventdispatcher.c mdscreen.c \ mdicon.c mdwindow.c kbdsupport.c hotkey.c \ lists.c readargs.c iconlib.c iconutil.c error.c strutil.c \ - iffparse.c + iffparse.c gadget_button.c gadget_textbox.c gadget_textinput.c all : libami.a diff --git a/libami/gadget_button.c b/libami/gadget_button.c new file mode 100644 index 0000000..c336d60 --- /dev/null +++ b/libami/gadget_button.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#include +#ifdef USE_FONTSETS +#include +#include +#endif + +#include "drawinfo.h" + +#include "gadget_button.h" + +#ifdef AMIGAOS +#include +extern struct Library *XLibBase; +#endif + +/* + * This is the button code from the executecmd.c tool. + */ + +struct gadget_button * +gadget_button_init(Display *dpy, struct DrawInfo *dri, GC gc, Window mainwin, + int x, int y, int butw, int buth) +{ + struct gadget_button *b; + + b = calloc(1, sizeof(*b)); + if (b == NULL) { + return (NULL); + } + b->dpy = dpy; + b->dri = dri; + b->x = x; + b->y = y; + b->butw = butw; + b->buth = buth; + b->txt = strdup(""); + b->gc = gc; + + b->w = XCreateSimpleWindow(dpy, mainwin, + x, y, + butw, /* width */ + buth, /* height */ + 0, /* depth */ + dri->dri_Pens[SHADOWPEN], + dri->dri_Pens[BACKGROUNDPEN]); + + XSelectInput(dpy, b->w, ExposureMask | ButtonPressMask + | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask); + + return (b); +} + +void +gadget_button_set_text(struct gadget_button *b, const char *txt) +{ + if (b->txt != NULL) + free(b->txt); + b->txt = strdup(txt); +} + +void +gadget_button_refresh(struct gadget_button *b) +{ + int fh = b->dri->dri_Ascent + b->dri->dri_Descent; + int h = fh + (2 * BUT_VSPACE); + int l=strlen(b->txt); +#ifdef USE_FONTSETS + int tw = XmbTextEscapement(b->dri->dri_FontSet, b->txt, l); +#else + int tw = XTextWidth(b->dri->dri_Font, b->txt, l); +#endif + XSetForeground(b->dpy, b->gc, b->dri->dri_Pens[TEXTPEN]); +#ifdef USE_FONTSETS + XmbDrawString(b->dpy, b->w, b->dri->dri_FontSet, b->gc, + (b->butw-tw)>>1, b->dri->dri_Ascent+BUT_VSPACE, b->txt, l); +#else + XDrawString(b->dpy, b->w, b->gc, (b->butw-tw)>>1, + b->dri->dri_Ascent+BUT_VSPACE, b->txt, l); +#endif + XSetForeground(b->dpy, b->gc, + b->dri->dri_Pens[b->depressed ? SHADOWPEN:SHINEPEN]); + + XDrawLine(b->dpy, b->w, b->gc, 0, 0, b->butw-2, 0); + XDrawLine(b->dpy, b->w, b->gc, 0, 0, 0, h-2); + XSetForeground(b->dpy, b->gc, + b->dri->dri_Pens[b->depressed ? SHINEPEN:SHADOWPEN]); + + XDrawLine(b->dpy, b->w, b->gc, 1, h-1, b->butw-1, h-1); + XDrawLine(b->dpy, b->w, b->gc, b->butw-1, 1, b->butw-1, h-1); + XSetForeground(b->dpy, b->gc, b->dri->dri_Pens[BACKGROUNDPEN]); + XDrawPoint(b->dpy, b->w, b->gc, b->butw-1, 0); + XDrawPoint(b->dpy, b->w, b->gc, 0, h-1); +} + +void +gadget_button_set_depressed(struct gadget_button *b, int depressed) +{ + b->depressed = depressed; +} + +void +gadget_button_toggle(struct gadget_button *b) +{ + int pen; + + pen = (b->depressed) ? FILLPEN : BACKGROUNDPEN; + + + XSetWindowBackground(b->dpy, b->w, b->dri->dri_Pens[pen]); + XClearWindow(b->dpy, b->w); + gadget_button_refresh(b); +} + +void +gadget_button_free(struct gadget_button *b) +{ + XDestroyWindow(b->dpy, b->w); + free(b->txt); + free(b); +} diff --git a/libami/gadget_button.h b/libami/gadget_button.h new file mode 100644 index 0000000..d33c9d8 --- /dev/null +++ b/libami/gadget_button.h @@ -0,0 +1,35 @@ +#ifndef __LIBAMI__GADGET_BUTTON_H__ +#define __LIBAMI__GADGET_BUTTON_H__ + +#define BOT_SPACE 4 +#define TEXT_SIDE 8 +#define BUT_SIDE 12 +#define TOP_SPACE 4 +#define INT_SPACE 7 +#define BUT_VSPACE 2 +#define BUT_HSPACE 8 + +struct gadget_button { + Display *dpy; + struct DrawInfo *dri; + Window w; + GC gc; + int x; + int y; + int buth; + int butw; + char *txt; + int depressed; +}; + +extern struct gadget_button * gadget_button_init(Display *dpy, + struct DrawInfo *dri, GC gc, Window mainwin, + int x, int y, int butw, int buth); +extern void gadget_button_set_text(struct gadget_button *b, const char *txt); +extern void gadget_button_refresh(struct gadget_button *b); +extern void gadget_button_set_depressed(struct gadget_button *b, + int depressed); +extern void gadget_button_toggle(struct gadget_button *b); +extern void gadget_button_free(struct gadget_button *b); + +#endif /* __LIBAMI__GADGET_BUTTON_H__ */ diff --git a/libami/gadget_textbox.c b/libami/gadget_textbox.c new file mode 100644 index 0000000..087e706 --- /dev/null +++ b/libami/gadget_textbox.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include + +#include "drawinfo.h" +#include "libami.h" + +#ifdef AMIGAOS +#include +extern struct Library *XLibBase; +#endif + +#include "gadget_textbox.h" + +#if 0 +struct gadget_textbox_line { + struct line *next; + const char *text; + int l, w, h; +}; +#endif + +#if 0 +struct gadget_textbox { + struct gadget_textbox_line *firstline, *lastline; +}; +#endif + + +struct gadget_textbox * +gadget_textbox_create(Display *dpy, struct DrawInfo *dri, GC gc, + Window mainwin, int x, int y, int width, int height) +{ + struct gadget_textbox *g; + + g = calloc(1, sizeof(*g)); + if (g == NULL) { + return (NULL); + } + g->dpy = dpy; + g->dri = dri; + g->gc = gc; + g->x = x; + g->y = y; + g->width = width; + g->height = height; + + g->w = XCreateSimpleWindow(g->dpy, mainwin, + g->x, g->y, + g->width, g->height, + 0, + g->dri->dri_Pens[SHADOWPEN], + g->dri->dri_Pens[BACKGROUNDPEN]); + XSelectInput(g->dpy, g->w, ExposureMask); + + return (g); +} + +void +gadget_textbox_free(struct gadget_textbox *g) +{ + /* XXX TODO */ +} + +struct gadget_textbox_line * +gadget_textbox_addline(struct gadget_textbox *g, const char *text) +{ + struct gadget_textbox_line *l; + + l = calloc(1, sizeof(*l)); + if (l == NULL) { + return (NULL); + } + if(g->lastline) + g->lastline->next = l; + else + g->firstline = l; + g->lastline = l; + l->text = strdup(text); + l->l = strlen(text); +#ifdef USE_FONTSETS + l->w = XmbTextEscapement(g->dri->dri_FontSet, l->text, l->l); +#else + l->w = XTextWidth(g->dri->dri_Font, l->text, l->l); +#endif + l->h = g->dri->dri_Ascent + g->dri->dri_Descent; + + return (l); +} + +void +gadget_textbox_refresh(struct gadget_textbox *g) +{ + // This is OBVIOUSLY the wrong value for x here, but let's get it going + int x = TXT_HSPACE / 2; + int y = ((g->dri->dri_Ascent+g->dri->dri_Descent)>>1)+g->dri->dri_Ascent; + + struct gadget_textbox_line *l; + + /* Draw the bounding box */ + XSetForeground(g->dpy, g->gc, g->dri->dri_Pens[SHADOWPEN]); + XDrawLine(g->dpy, g->w, g->gc, 0, 0, g->width-2, 0); + XDrawLine(g->dpy, g->w, g->gc, 0, 0, 0, g->height-2); + + XSetForeground(g->dpy, g->gc, g->dri->dri_Pens[SHINEPEN]); + XDrawLine(g->dpy, g->w, g->gc, 0, g->height-1, g->width-1, g->height-1); + XDrawLine(g->dpy, g->w, g->gc, g->width-1, 0, g->width-1, g->height-1); + + /* Draw text lines */ + XSetForeground(g->dpy, g->gc, g->dri->dri_Pens[TEXTPEN]); + for(l = g->firstline; l; l=l->next) { +#ifdef USE_FONTSETS + XmbDrawString(g->dpy, g->w, g->dri->dri_FontSet, g->gc, + x, y, l->text, l->l); +#else + XDrawString(g->dpy, g->w, g->gc, x, y, l->text, l->l); +#endif + y+=g->dri->dri_Ascent + g->dri->dri_Descent; + } +} diff --git a/libami/gadget_textbox.h b/libami/gadget_textbox.h new file mode 100644 index 0000000..2087951 --- /dev/null +++ b/libami/gadget_textbox.h @@ -0,0 +1,35 @@ +#ifndef __LIBAMI_GADGET_TEXTBOX_H__ +#define __LIBAMI_GADGET_TEXTBOX_H__ + +// These are for the text box widget +#define TXT_HSPACE 48 +#define TXT_TOPSPACE 4 +#define TXT_MIDSPACE 3 +#define TXT_BOTSPACE 4 + +struct gadget_textbox_line { + struct gadget_textbox_line *next; + const char *text; + int l, w, h; +}; + +struct gadget_textbox { + Display *dpy; + struct DrawInfo *dri; + GC gc; + Window w; + int x, y; + int width, height; + + struct gadget_textbox_line *firstline, *lastline; +}; + +extern struct gadget_textbox *gadget_textbox_create(Display *dpy, + struct DrawInfo *dri, GC gc, Window mainwin, int x, int y, + int width, int height); +extern void gadget_textbox_free(struct gadget_textbox *g); +extern struct gadget_textbox_line * gadget_textbox_addline( + struct gadget_textbox *g, const char *text); +extern void gadget_textbox_refresh(struct gadget_textbox *g); + +#endif /* __LIBAMI_GADGET_TEXTBOX_H__ */ diff --git a/libami/gadget_textinput.c b/libami/gadget_textinput.c new file mode 100644 index 0000000..2ac6c66 --- /dev/null +++ b/libami/gadget_textinput.c @@ -0,0 +1,349 @@ +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#include +#ifdef USE_FONTSETS +#include +#include +#endif + +#include "drawinfo.h" + +#include "gadget_textinput.h" + +#ifdef AMIGAOS +#include +extern struct Library *XLibBase; +#endif + +struct gadget_textinput * +gadget_textinput_create(Display *dpy, struct DrawInfo *dri, + GC gc, Window mainwin, int x, int y, int width, int height, + int textsize) +{ + struct gadget_textinput *b; + + b = calloc(1, sizeof(*b)); + if (b == NULL) + return (NULL); + b->dpy = dpy; + b->dri = dri; + b->gc = gc; + b->x = x; + b->y = y; + b->width = width; + b->height = height; + b->buf = calloc(textsize + 1, sizeof(char)); + if (b->buf == NULL) { + free(b); + return (NULL); + } + b->cur_x = 6; + b->size = textsize; + b->w = XCreateSimpleWindow(dpy, mainwin, x, y, + width, height, 0, + b->dri->dri_Pens[SHADOWPEN], + b->dri->dri_Pens[BACKGROUNDPEN]); + + XSelectInput(dpy, b->w, ExposureMask|ButtonPressMask); + + return (b); +} + +#ifdef USE_FONTSETS +void +gadget_textinput_set_xic(struct gadget_textinput *g, XIC xic) +{ + g->xic = xic; +} +#endif + +static void +gadget_textinput_repaint_str(struct gadget_textinput *b) +{ + int l, mx=6; + + XSetForeground(b->dpy, b->gc, b->dri->dri_Pens[TEXTPEN]); + if(b->len > b->left_pos) { +#ifdef USE_FONTSETS + int w, c; + + for (l=0; llen - b->left_pos; ) { + c=mbrlen(b->buf+b->left_pos+l, b->len-b->left_pos-l, NULL); + w=6+XmbTextEscapement(b->dri->dri_FontSet, b->buf+b->left_pos, l+c); + if(w>b->width-6) + break; + mx=w; + l+=c; + } + + XmbDrawImageString(b->dpy, b->w, b->dri->dri_FontSet, b->gc, + 6, 3+b->dri->dri_Ascent, + b->buf+b->left_pos, l); +#else + mx+=XTextWidth(b->dri->dri_Font, b->buf+b->left_pos, l=b->len-b->left_pos); + while(mx>b->width-6) + mx-=XTextWidth(b->dri->dri_Font, b->buf+b->left_pos + --l, 1); + XDrawImageString(b->dpy, b->w, b->gc, 6, 3+b->dri->dri_Ascent, + b->buf+b->left_pos, l); +#endif + } + XSetForeground(b->dpy, b->gc, b->dri->dri_Pens[BACKGROUNDPEN]); + XFillRectangle(b->dpy, b->w, b->gc, mx, 3, b->width-mx-6, b->width - 6); + if(b->selected) { + if(b->cur_poslen) { + XSetBackground(b->dpy, b->gc, ~0); +#ifdef USE_FONTSETS + l=mbrlen(b->buf+b->cur_pos, b->len-b->cur_pos, NULL); + XmbDrawImageString(b->dpy, b->w, b->dri->dri_FontSet, b->gc, b->cur_x, + 3+b->dri->dri_Ascent, b->buf+b->cur_pos, l); +#else + XDrawImageString(b->dpy, b->w, b->gc, cur_x, 3+b->dri->dri_Ascent, + b->buf+b->cur_pos, 1); +#endif + XSetBackground(b->dpy, b->gc, b->dri->dri_Pens[BACKGROUNDPEN]); + } else { + XSetForeground(b->dpy, b->gc, ~0); +#ifdef USE_FONTSETS + XFillRectangle(b->dpy, b->w, b->gc, b->cur_x, 3, + XExtentsOfFontSet(b->dri->dri_FontSet)-> + max_logical_extent.width, b->height - 6); +#else + XFillRectangle(b->dpy, b->w, b->gc, cur_x, 3, + b->dri->dri_Font->max_bounds.width, b->height - 6); +#endif + } + } +} + +void +gadget_textinput_repaint(struct gadget_textinput *b) +{ + + gadget_textinput_repaint_str(b); + + XSetForeground(b->dpy, b->gc, b->dri->dri_Pens[SHINEPEN]); + XDrawLine(b->dpy, b->w, b->gc, 0, b->height-1, 0, 0); + XDrawLine(b->dpy, b->w, b->gc, 0, 0, b->width-2, 0); + XDrawLine(b->dpy, b->w, b->gc, 3, b->height-2, b->width-4, + b->height-2); + XDrawLine(b->dpy, b->w, b->gc, b->width-4, b->height-2, b->width-4, 2); + XDrawLine(b->dpy, b->w, b->gc, 1, 1, 1, b->height-2); + XDrawLine(b->dpy, b->w, b->gc, b->width-3, 1, b->width-3, b->height-2); + XSetForeground(b->dpy, b->gc, b->dri->dri_Pens[SHADOWPEN]); + XDrawLine(b->dpy, b->w, b->gc, 1, b->height-1, b->width-1, + b->height-1); + XDrawLine(b->dpy, b->w, b->gc, b->width-1, b->height-1, b->width-1, 0); + XDrawLine(b->dpy, b->w, b->gc, 3, b->height-3, 3, 1); + XDrawLine(b->dpy, b->w, b->gc, 3, 1, b->width-4, 1); + XDrawLine(b->dpy, b->w, b->gc, 2, 1, 2, b->height-2); + XDrawLine(b->dpy, b->w, b->gc, b->width-2, 1, b->width-2, b->height-2); +} + +void +gadget_textinput_free(struct gadget_textinput *b) +{ + if (b->buf) + free(b->buf); + XDestroyWindow(b->dpy, b->w); + free(b); +} + +void +gadget_textinput_keyevent(struct gadget_textinput *b, XKeyEvent *e) +{ +#ifdef USE_FONTSETS + Status stat; +#else + static XComposeStatus stat; +#endif + KeySym ks; + char buf[256]; + int x, i, n; +#ifndef USE_FONTSETS + n=XLookupString(e, buf, sizeof(buf), &ks, &stat); +#else + n=XmbLookupString(b->xic, e, buf, sizeof(buf), &ks, &stat); + if(stat == XLookupKeySym || stat == XLookupBoth) +#endif + switch(ks) { + case XK_Return: + case XK_Linefeed: + b->crlf = 1; + break; + case XK_Left: + if(b->cur_pos) { +#ifdef USE_FONTSETS + int p=b->cur_pos; +// int z; + while(p>0) { + --p; + if(((int)mbrlen(b->buf+p, b->cur_pos-p, NULL))>0) { + b->cur_pos=p; + break; + } + } +#else + --cur_pos; +#endif + } + break; + case XK_Right: + if(b->cur_poslen) { +#ifdef USE_FONTSETS + int l=mbrlen(b->buf+b->cur_pos, b->len-b->cur_pos, NULL); + if(l>0) + b->cur_pos+=l; +#else + b->cur_pos++; +#endif + } + break; + case XK_Begin: + b->cur_pos=0; + break; + case XK_End: + b->cur_pos=b->len; + break; + case XK_Delete: + if(b->cur_poslen) { + int l=1; +#ifdef USE_FONTSETS + l=mbrlen(b->buf+b->cur_pos, b->len-b->cur_pos, NULL); + if(l<=0) + break; +#endif + b->len-=l; + for(x=b->cur_pos; xlen; x++) + b->buf[x]=b->buf[x+l]; + b->buf[x] = 0; + } else XBell(b->dpy, 100); + break; + case XK_BackSpace: + if(b->cur_pos>0) { + int l=1; +#ifdef USE_FONTSETS + int p=b->cur_pos; + while(p>0) { + --p; + if(((int)mbrlen(b->buf+p, b->len-p, NULL))>0) { + l= b->cur_pos - p; + break; + } + } +#endif + b->len -= l; + for(x=(b->cur_pos-=l); xlen; x++) + b->buf[x]=b->buf[x+l]; + b->buf[x] = 0; + } else XBell(b->dpy, 100); + break; +#ifdef USE_FONTSETS + default: + if(stat == XLookupBoth) + stat = XLookupChars; + } + if(stat == XLookupChars) { +#else + default: +#endif + for(i=0; ilensize-1; i++) { + for(x=b->len; x>b->cur_pos; --x) + b->buf[x]=b->buf[x-1]; + b->buf[b->cur_pos++]=buf[i]; + b->len++; + } + if(idpy, 100); + } + if(b->cur_posleft_pos) + b->left_pos=b->cur_pos; + b->cur_x=6; +#ifdef USE_FONTSETS + if(b->cur_pos>b->left_pos) + b->cur_x+=XmbTextEscapement(b->dri->dri_FontSet, b->buf+b->left_pos, + b->cur_pos-b->left_pos); + if(b->cur_pos < b->len) { + int l=mbrlen(b->buf+b->cur_pos, b->len-b->cur_pos, NULL); + x=XmbTextEscapement(b->dri->dri_FontSet, b->buf+b->cur_pos, l); + } else + x=XExtentsOfFontSet(b->dri->dri_FontSet)->max_logical_extent.width; +#else + if(b->cur_pos > b->left_pos) + b->cur_x+=XTextWidth(b->dri->dri_Font, b->buf+b->left_pos, b->cur_pos-b->left_pos); + if(b->cur_posbuf_len) + x=XTextWidth(b->dri->dri_Font, b->buf+b->cur_pos, 1); + else + x=b->dri->dri_Font->max_bounds.width; +#endif + if((x+=b->cur_x-(b->width-6))>0) { + b->cur_x-=x; + while(x>0) { +#ifdef USE_FONTSETS + int l=mbrlen(b->buf+b->left_pos, b->len-b->left_pos, NULL); + x-=XmbTextEscapement(b->dri->dri_FontSet, b->buf+b->left_pos, l); + b->left_pos += l; +#else + x-=XTextWidth(b->dri->dri_Font, b->buf+b->left_pos++, 1); +#endif + } + b->cur_x+=x; + } +} + + +void +gadget_textinput_buttonevent(struct gadget_textinput *b, XButtonEvent *e) +{ + int w, l=1; + b->cur_pos=b->left_pos; + b->cur_x=6; + while(b->cur_xx && b->cur_poslen) { +#ifdef USE_FONTSETS + l=mbrlen(b->buf+b->cur_pos, b->len-b->cur_pos, NULL); + if(l<=0) + break; + w=XmbTextEscapement(b->dri->dri_FontSet, b->buf+b->cur_pos, l); +#else + w=XTextWidth(b->dri->dri_Font, b->buf+b->cur_pos, 1); +#endif + if(b->cur_x+w>e->x) + break; + b->cur_x+=w; + b->cur_pos+=l; + } +} + +#if 0 + +void strbutton(XButtonEvent *e) +{ + refresh_str(); +} + +#endif + +void +gadget_textinput_selected(struct gadget_textinput *b, int selected) +{ + b->selected = selected; +} + +int +gadget_textinput_crlf(struct gadget_textinput *b) +{ + return (b->crlf); +} diff --git a/libami/gadget_textinput.h b/libami/gadget_textinput.h new file mode 100644 index 0000000..283e874 --- /dev/null +++ b/libami/gadget_textinput.h @@ -0,0 +1,46 @@ +#ifndef __LIBAMI__GADGET_TEXTINPUT_H__ +#define __LIBAMI__GADGET_TEXTINPUT_H__ + +struct gadget_textinput { + Display *dpy; + struct DrawInfo *dri; + Window w; + GC gc; +#ifdef USE_FONTSETS + XIC xic; +#endif + int x; + int y; + int width; + int height; + + /* XXX TODO: create a string representation here already */ + char *buf; + int len; + int size; + + /* Position of textbox cursor and rendering start */ + int cur_pos; + int left_pos; + int cur_x; + + int selected; + int crlf; +}; + +extern struct gadget_textinput * gadget_textinput_create(Display *dpy, + struct DrawInfo *dri, GC gc, Window mainwin, + int x, int y, int width, int height, int text_size); +#ifdef USE_FONTSETS +extern void gadget_textinput_set_xic(struct gadget_textinput *g, XIC xic); +#endif +extern void gadget_textinput_repaint(struct gadget_textinput *b); +extern void gadget_textinput_free(struct gadget_textinput *b); +extern void gadget_textinput_keyevent(struct gadget_textinput *b, + XKeyEvent *e); +extern void gadget_textinput_buttonevent(struct gadget_textinput *b, + XButtonEvent *e); +extern void gadget_textinput_selected(struct gadget_textinput *b, int selected); +extern int gadget_textinput_crlf(struct gadget_textinput *b); + +#endif /* __LIBAMI__GADGET_TEXTINPUT_H__ */