swk

static widget kit
git clone git://git.suckless.org/swk
Log | Files | Refs | README | LICENSE

commit f29cef34d65fa4d36bafb1bc542c24a93f7b1b33
parent ab43f010479fc493e5ef3b21762924a8dc5720b9
Author: pancake <nopcode.org>
Date:   Fri,  7 May 2010 13:42:46 +0200

move example programs to 't/' directory
fix swk.mk and use it from t/Makefile
remove <enter> key from desktop config.h
doublescroll also with mouse wheel
fix segfault in swk_gi_text when passing null string
initial working version of the ascii-art ui api (t/ui.c)
Diffstat:
Makefile | 19+++++++++----------
config.def.h | 3+--
gi_sdl.c | 18++++++++----------
swk.c | 4++--
t/Makefile | 14++++++++++++++
t/test.c | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
t/ui.c | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
test.c | 158-------------------------------------------------------------------------------
ui.c | 107-------------------------------------------------------------------------------
9 files changed, 391 insertions(+), 289 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,3 +1,4 @@ +.PHONY: all t clean install CC?=gcc CFLAGS?=-Wall -g -std=c99 VERSION=0.1 @@ -14,19 +15,16 @@ GI_LIBS=-lSDL -lSDL_ttf -lSDL_image GI_OBJS=gi_${GI}.o GI_SRCS=gi_${GI}.c -all: static shared test ui +all: static shared t + +t: + cd t && ${MAKE} all config.h: cp config.def.h config.h -test: config.h test.o libswk.a - ${CC} test.o -o test libswk.a ${GI_LIBS} - -ui: ui.o - ${CC} ui.o -o ui libswk.a ${GI_LIBS} - clean: - rm -f swk.pc swk.mk libswk.a libswk.so test.o swk.o test ${GI_OBJS} + rm -f swk.pc swk.mk ui.o ui libswk.a libswk.so test.o swk.o test ${GI_OBJS} install: mkdir -p ${DESTDIR}/${INCDIR} @@ -51,8 +49,9 @@ swk.o: config.h libswk.a: config.h swk.o ${GI_OBJS} rm -f libswk.a ar qcvf libswk.a swk.o ${GI_OBJS} - echo CFLAGS+=-I${PREFIX}/include > swk.mk - echo LDFLAGS+=${PREFIX}/lib/libswk.a ${GI_LIBS} >> swk.mk + echo SWKINCS+=-I${PREFIX}/include > swk.mk + echo SWKLIB+=${PREFIX}/lib/libswk.a >> swk.mk + echo SWKLIBS+=${GI_LIBS} >> swk.mk echo prefix=${PREFIX} > swk.pc echo libdir=${LIBDIR} >> swk.pc echo >> swk.pc diff --git a/config.def.h b/config.def.h @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -#define FONTSIZE 28 +#define FONTSIZE 18 #define FONTBOLD 0 #define WINWIDTH 640 #define WINHEIGHT 480 @@ -26,7 +26,6 @@ static SwkKeyBind keys[] = { { Ctrl, 10 , swk_focus_next }, { Ctrl, 11 , swk_focus_prev }, { Ctrl, 12 , swk_focus_activate }, - { 0, 225 , swk_focus_activate }, // n900 return { 0 , KUp, swk_focus_prev }, { 0 , KDown, swk_focus_next }, { 0 , 13 , swk_focus_activate }, diff --git a/gi_sdl.c b/gi_sdl.c @@ -128,7 +128,7 @@ swk_gi_event(SwkWindow *w, int dowait) { switch(event.type) { default: ret = NULL; break; case SDL_VIDEORESIZE: - fprintf(stderr, "resize %d %d\n", event.resize.w, event.resize.h); + //fprintf(stderr, "resize %d %d\n", event.resize.w, event.resize.h); SDL_SetVideoMode(event.resize.w, event.resize.h, BPP, SDLFLAGS); case SDL_ACTIVEEVENT: case SDL_VIDEOEXPOSE: @@ -145,12 +145,10 @@ swk_gi_event(SwkWindow *w, int dowait) { if(event.motion.y>mousedowny+fs) { mousedowny = event.motion.y; swk_scroll_up(w); - swk_scroll_up(w); } else if(event.motion.y<mousedowny-fs) { mousedowny = event.motion.y; swk_scroll_down(w); - swk_scroll_down(w); } ret->type = EExpose; ret->data.expose.x = ret->data.expose.y = \ @@ -266,14 +264,14 @@ swk_gi_rect(Rect r, int color) { void swk_gi_text(Rect r, const char *text) { char *ptr = NULL; - int len = strlen(text); int w = (int)((double)r.w * 1.6); // hacky - if(len>w) { - ptr = strdup(text); - text = (const char *)ptr; - ptr[w] = '\0'; - } - if(*text) { + if(text && *text) { + int len = text?strlen(text):0; + if(len>w) { + ptr = strdup(text); + text = (const char *)ptr; + ptr[w] = '\0'; + } SDL_Surface *ts = TTF_RenderText_Shaded(font, text, fontcolor, bgcolor); if(ts) { SDL_Rect to = { (r.x)*fs, r.y*fs, ts->w, ts->h }; diff --git a/swk.c b/swk.c @@ -96,12 +96,12 @@ setscrollbox(SwkWindow *w, int delta) { void swk_scroll_up(SwkWindow *w) { - setscrollbox(w, 1); + setscrollbox(w, 2); } void swk_scroll_down(SwkWindow *w) { - setscrollbox(w, -1); + setscrollbox(w, -2); } static void swk_fit_row(SwkWindow *w, SwkBox *a, SwkBox *b, int y) { diff --git a/t/Makefile b/t/Makefile @@ -0,0 +1,14 @@ +include ../swk.mk + +CFLAGS=-I.. + +all: test ui + +test: test.o + ${CC} ${SWKLIBS} test.o -o test ../libswk.a + +ui: ui.o + ${CC} ${SWKLIBS} ui.o -o ui ../libswk.a + +clean: + rm -f test test.o ui ui.o diff --git a/t/test.c b/t/test.c @@ -0,0 +1,159 @@ +#include <stdio.h> +#include <swk.h> + +static int count = 3; +static int pccount = 0; +static char text[64]; +static char pctext[64]; +static SwkBox helloworld[]; +static SwkBox about[]; +static SwkBox *opt = NULL; +static void mybutton(SwkEvent *e); +static void mybutton_about(SwkEvent *e); +static void mybutton_about_ok(SwkEvent *e); + +static void mybutton(SwkEvent *e) { + if(e->type == EClick) { + sprintf(text, "Do it again %d times\n", count); + helloworld[0].text = text; + if(opt == NULL) + printf("Option: none\n"); + else printf("Option: %s\n", opt->text); + if(count-- == 0) + swk_exit(e->win); + } + swk_button(e); +} + +static void myprogressbutton(SwkEvent *e) { + if(e->type == EClick) { + pccount+=6; + if(pccount > 100) { + pccount = 0; + e->win->boxes = helloworld; + swk_update(e->win); + } + sprintf(pctext, "%d%%", pccount); + about[11].text = pctext; + } + swk_button(e); +} + +static SwkBox about[] = { + SWK_BOX_NEWLINE(0), + { .cb=swk_label, .text="About this program...", }, + SWK_BOX_NEWLINE(1), + { .cb=swk_separator }, + SWK_BOX_NEWLINE(-1), + //SWK_BOX_NEWLINE(2), + { .cb=swk_label, .text="This is a test program for swk" }, + SWK_BOX_NEWLINE(1), + { .cb=swk_label, .text=" ... a simple widget kit " }, + SWK_BOX_NEWLINE(1), + { .cb=swk_label, .text=" ... from the suckless.org project" }, + SWK_BOX_NEWLINE(2), + { .cb=swk_progress, .text="0%", }, + SWK_BOX_NEWLINE(2), + { .cb=swk_filler }, + { .cb=myprogressbutton, .text="next", }, + { .cb=swk_filler }, + //SWK_BOX_NEWLINE(3), + { .cb=swk_filler }, + { .cb=mybutton_about_ok, .text="Ok" }, + { .cb=NULL } +}; + +static void mybutton_about_ok(SwkEvent *e) { + if(e->type == EClick) { + e->win->boxes = helloworld; + swk_update(e->win); + } + swk_button(e); +} + +static void mybutton_about(SwkEvent *e) { + if(e->type == EClick) { + e->win->boxes = about; + swk_update(e->win); + } + swk_button(e); +} +//--------- +static SwkBox scrollwin[] = { + SWK_BOX_NEWLINE(0), + { .cb=swk_label, .text="Scroll to change value", }, + SWK_BOX_NEWLINE(1), + { .cb=swk_separator }, + SWK_BOX_NEWLINE(1), + { .cb=swk_label, .text=" /etc" }, + SWK_BOX_NEWLINE(1), + { .cb=swk_button, .text="/bin" }, + SWK_BOX_NEWLINE(1), + { .cb=swk_label, .text=" /sbin" }, + SWK_BOX_NEWLINE(-1), + { .cb=NULL } +}; + +static void mybutton_numscroll(SwkEvent *e) { + if(e->type == EClick) { + e->win->boxes = scrollwin; + swk_update(e->win); + } + swk_button(e); +} + +static SwkBox helloworld[] = { + { .cb=swk_label, .text="Press a button", }, + SWK_BOX_NEWLINE(1), + { .cb=swk_separator }, + SWK_BOX_NEWLINE(2), + { .cb=swk_label, .text="Username:", }, + { .cb=swk_entry, .text="____", }, + SWK_BOX_NEWLINE(1), + { .cb=swk_label, .text="Password:", }, + { .cb=swk_password, .text="1234", }, + SWK_BOX_NEWLINE(-1), + { .cb=swk_label, .text="Click here ->" }, + { .cb=swk_sketch }, + SWK_BOX_NEWLINE(2), + { .cb=swk_image, .text="image.png" }, + { .cb=swk_image, .text="image.png" }, + { .cb=swk_image, .text="image.png" }, + { .cb=swk_image, .text="image.png" }, + { .cb=swk_filler, }, + SWK_BOX_NEWLINE(2), + { .cb=mybutton, .text="yes" }, + { .cb=mybutton, .text="no" }, + { .cb=swk_filler, }, + SWK_BOX_NEWLINE(2), + { .cb=swk_option, .text="zoot" }, + SWK_BOX_NEWLINE(1), + { .cb=swk_option, .text="remember values", .data=&opt }, +// { .cb=swk_option, .text="null" }, + SWK_BOX_NEWLINE(1), + { .cb=swk_option, .text="pasta barata", .data=&opt }, + SWK_BOX_NEWLINE(2), + { .cb=swk_label, .text="--swktest", }, + { .cb=mybutton_about, .text="about" }, + { .cb=mybutton_numscroll, .text="num" }, + { .cb=NULL } +}; + +int +main() { + SwkWindow w = { + .title="Hello World", + .boxes=helloworld, + .box=helloworld+10, + //.r = { 0, 0, 320, 240 }, +/* + // TODO: application workflow + .ok=cb + .cancel=cb +*/ + }; + if(!swk_init(&w)) + return 1; + swk_loop(&w); + return 0; +} diff --git a/t/ui.c b/t/ui.c @@ -0,0 +1,198 @@ +/* See LICENSE file for copyright and license details. */ +// ascii-art user interface // +#if 0 + {HelloWorld + 'Press a button' + ---------------- + (save password) + (store options) + [Ok] [Cancel] + ================ + 'This is new' + <image.png> + } + +SwkBox *b = swk_ui_get(w, "ok"); +#endif + +#include <swk.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +// TODO: Rename to swk_win_ swk_window_ ? +void +swk_ui_free(SwkWindow *w) { + // leaks in box->text ? + free(w->boxes); + free(w->title); + free(w); +} + +SwkWindow * +swk_ui(const char *text) { + SwkWindow *w = (SwkWindow*)malloc(sizeof(SwkWindow)); + int sz, stri = 0, mode = 0; + int count = 0; + char str[128]; + const char *ptr = text; + + if(!w) return NULL; + memset(w, 0, sizeof(SwkWindow)); + + // TODO: count widgets and allocate stuff + for(sz=0; ptr && *ptr; ptr++) { + // TODO + switch(*ptr) { + case '\n': + case '[': + case '{': + case '\'': + sz++; + sz++; + default: + break; + } + } + printf("WINDETS=%d\n", sz); + + w->box = w->boxes = (SwkBox*)malloc(128*sizeof(SwkBox)); // Use sz after counting + memset(w->box, 0, 128*sizeof(SwkBox)); + + while(text && *text) { + switch(mode) { + case '\'': + if ((*text=='\''&&str[stri-1]!='\\') || *text=='\n') { + printf("label(%s)\n", str); + stri = mode = 0; + w->boxes[count].cb = swk_label; + w->boxes[count].text = strdup (str); + count++; + } else { + str[stri++] = *text; + str[stri] = 0; + } + break; + case '<': + if ((*text=='>'&&str[stri-1]!='\\') || *text=='\n') { + printf("image(%s)\n", str); + stri = mode = 0; + w->boxes[count].cb = swk_image; + w->boxes[count].text = strdup (str); + count++; + } else { + str[stri++] = *text; + str[stri] = 0; + } + break; + case '*': + if (*text=='\n') { + w->boxes[count].cb = swk_filler; + count++; + mode = 0; + } + break; + case '=': + if (*text=='\n') { + SwkBox b = SWK_BOX_NEWLINE(-1); + w->boxes[count] = b; + count++; + mode = 0; + } + break; + case '-': + if (*text=='\n') { + w->boxes[count].cb = swk_separator; + count++; + mode = 0; + } + break; + case '(': + if ((*text==')'&&str[stri-1]!='\\') || *text=='\n') { + printf("option(%s)\n", str); + stri = mode = 0; + w->boxes[count].cb = swk_option; + w->boxes[count].text = strdup (str); + count++; + } else { + str[stri++] = *text; + str[stri] = 0; + } + break; + case '$': + if ((*text=='$'&&str[stri-1]!='\\') || *text=='\n') { + stri = mode = 0; + if (*str=='*') { + printf("pass(%s)\n", str); + w->boxes[count].cb = swk_password; + w->boxes[count].text = ""; + } else { + printf("entry(%s)\n", str); + w->boxes[count].cb = swk_entry; + w->boxes[count].text = strdup (str); + } + count++; + } else { + str[stri++] = *text; + str[stri] = 0; + } + break; + case '[': + if ((*text==']'&&str[stri-1]!='\\') || *text=='\n') { + printf("button(%s)\n", str); + stri = mode = 0; + w->boxes[count].cb = swk_button; + w->boxes[count].text = strdup (str); + count++; + } else { + str[stri++] = *text; + str[stri] = 0; + } + break; + case '{': + if (*text=='}' || *text=='\n') { + printf("WINDOW TITLE(%s)\n", str); + stri = mode = 0; + w->title = strdup(str); + } else { + str[stri++] = *text; + str[stri] = 0; + } + break; + default: + if (*text=='\n') { + SwkBox b = SWK_BOX_NEWLINE(1); + w->boxes[count] = b; + count++; + } else { + mode = *text; + stri = 0; + str[0] = 0; + } + break; + } + text++; + } + w->running = 1; + swk_init(w); + return w; +} + +#define UI \ + "{Hello World}\n" \ + "'This is a label'\n" \ + "-----------------\n" \ + "\n\n" \ + "$$\n" \ + "=================\n" \ + "[yes][no]\n" + +static SwkWindow *w = NULL; + +int main() { + w = swk_ui(UI); + if(!w||!swk_init(w)) + return 1; + swk_loop(w); + return 0; +} diff --git a/test.c b/test.c @@ -1,158 +0,0 @@ -#include <stdio.h> -#include "swk.h" - -static int count = 3; -static int pccount = 0; -static char text[64]; -static char pctext[64]; -static SwkBox helloworld[]; -static SwkBox about[]; -static SwkBox *opt = NULL; -static void mybutton(SwkEvent *e); -static void mybutton_about(SwkEvent *e); -static void mybutton_about_ok(SwkEvent *e); - -static void mybutton(SwkEvent *e) { - if(e->type == EClick) { - sprintf(text, "Do it again %d times\n", count); - helloworld[0].text = text; - if(opt == NULL) - printf("Option: none\n"); - else printf("Option: %s\n", opt->text); - if(count-- == 0) - swk_exit(e->win); - } - swk_button(e); -} - -static void myprogressbutton(SwkEvent *e) { - if(e->type == EClick) { - pccount+=6; - if(pccount > 100) { - pccount = 0; - e->win->boxes = helloworld; - swk_update(e->win); - } - sprintf(pctext, "%d%%", pccount); - about[11].text = pctext; - } - swk_button(e); -} - -static SwkBox about[] = { - SWK_BOX_NEWLINE(0), - { .cb=swk_label, .text="About this program...", }, - SWK_BOX_NEWLINE(1), - { .cb=swk_separator }, - SWK_BOX_NEWLINE(-1), - //SWK_BOX_NEWLINE(2), - { .cb=swk_label, .text="This is a test program for swk" }, - SWK_BOX_NEWLINE(1), - { .cb=swk_label, .text=" ... a simple widget kit " }, - SWK_BOX_NEWLINE(1), - { .cb=swk_label, .text=" ... from the suckless.org project" }, - SWK_BOX_NEWLINE(2), - { .cb=swk_progress, .text="0%", }, - SWK_BOX_NEWLINE(2), - { .cb=swk_filler }, - { .cb=myprogressbutton, .text="next", }, - { .cb=swk_filler }, - //SWK_BOX_NEWLINE(3), - { .cb=swk_filler }, - { .cb=mybutton_about_ok, .text="Ok" }, - { .cb=NULL } -}; - -static void mybutton_about_ok(SwkEvent *e) { - if(e->type == EClick) { - e->win->boxes = helloworld; - swk_update(e->win); - } - swk_button(e); -} - -static void mybutton_about(SwkEvent *e) { - if(e->type == EClick) { - e->win->boxes = about; - swk_update(e->win); - } - swk_button(e); -} -//--------- -static SwkBox scrollwin[] = { - SWK_BOX_NEWLINE(0), - { .cb=swk_label, .text="Scroll to change value", }, - SWK_BOX_NEWLINE(1), - { .cb=swk_separator }, - { .cb=swk_label, .text=".." }, - SWK_BOX_NEWLINE(1), - { .cb=swk_label, .text="bin" }, - SWK_BOX_NEWLINE(1), - { .cb=swk_label, .text="sbin" }, - SWK_BOX_NEWLINE(-1), - { .cb=NULL } -}; - -static void mybutton_numscroll(SwkEvent *e) { - if(e->type == EClick) { - e->win->boxes = scrollwin; - swk_update(e->win); - } - swk_button(e); -} - -static SwkBox helloworld[] = { - { .cb=swk_label, .text="Press a button", }, - SWK_BOX_NEWLINE(1), - { .cb=swk_separator }, - SWK_BOX_NEWLINE(2), - { .cb=swk_label, .text="Username:", }, - { .cb=swk_entry, .text="____", }, - SWK_BOX_NEWLINE(1), - { .cb=swk_label, .text="Password:", }, - { .cb=swk_password, .text="1234", }, - SWK_BOX_NEWLINE(-1), - { .cb=swk_label, .text="Click here ->" }, - { .cb=swk_sketch }, - SWK_BOX_NEWLINE(2), - { .cb=swk_image, .text="image.png" }, - { .cb=swk_image, .text="image.png" }, - { .cb=swk_image, .text="image.png" }, - { .cb=swk_image, .text="image.png" }, - { .cb=swk_filler, }, - SWK_BOX_NEWLINE(2), - { .cb=mybutton, .text="yes" }, - { .cb=mybutton, .text="no" }, - { .cb=swk_filler, }, - SWK_BOX_NEWLINE(2), - { .cb=swk_option, .text="zoot" }, - SWK_BOX_NEWLINE(1), - { .cb=swk_option, .text="remember values", .data=&opt }, -// { .cb=swk_option, .text="null" }, - SWK_BOX_NEWLINE(1), - { .cb=swk_option, .text="pasta barata", .data=&opt }, - SWK_BOX_NEWLINE(2), - { .cb=swk_label, .text="--swktest", }, - { .cb=mybutton_about, .text="about" }, - { .cb=mybutton_numscroll, .text="num" }, - { .cb=NULL } -}; - -int -main() { - SwkWindow w = { - .title="Hello World", - .boxes=helloworld, - .box=helloworld+10, - //.r = { 0, 0, 320, 240 }, -/* - // TODO: application workflow - .ok=cb - .cancel=cb -*/ - }; - if(!swk_init(&w)) - return 1; - swk_loop(&w); - return 0; -} diff --git a/ui.c b/ui.c @@ -1,107 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -// ascii-art user interface // -#if 0 - {HelloWorld - 'Press a button' - ---------------- - (save password) - (store options) - [Ok] [Cancel] - ================ - 'This is new' - <image.png> - } -#endif - -#include <swk.h> -#include <stdio.h> - -// TODO: Rename to swk_win_ swk_window_ ? -void -swk_ui_free(SwkWindow *w) { - // leaks in box->text ? - free(w->boxes); - free(w->title); - free(w); -} - -SwkWindow * -swk_ui(const char *text) { - SwkBox *b; - SwkWindow *w = (SwkWindow*)malloc(sizeof(SwkWindow)); - int sz, stri = 0, mode = 0; - char str[128]; - const char *ptr = text; - - if(!w) return NULL; - memset(w, 0, sizeof(SwkWindow)); - - // TODO: count widgets and allocate stuff - for(sz=0; ptr && *ptr; ptr++) { - // TODO - switch(*ptr) { - case '\n': - case '[': - case '{': - case '\'': - sz++; - sz++; - default: - break; - } - } - printf("WINDETS=%d\n", sz); - - w->box = w->boxes = malloc(128*sizeof(SwkBox)); // Use sz after counting - memset(w->box, 0, 128*sizeof(SwkBox)); - - while(text && *text) { - switch(mode) { - case '\'': - if ((*text=='\''&&str[stri-1]!='\\') || *text=='\n') { - printf("label(%s)\n", str); - stri = 0; - mode = 0; - //w->boxes[count++] ... - w->title = strdup(str); - } else { - str[stri++] = *text; - str[stri] = 0; - } - break; - case '{': - if (*text=='}' || *text=='\n') { - printf("WINDOW TITLE(%s)\n", str); - stri = 0; - mode = 0; - w->title = strdup(str); - } else { - str[stri++] = *text; - str[stri] = 0; - } - break; - default: - mode = *text; - break; - } - text++; - } - return w; -} - -#define UI \ - "{Hello World}\n" \ - "'This is a label'\n" \ - "-----------------\n" \ - "^\n" \ - "[yes][no]\n" - -static SwkWindow *w = NULL; - -int main() { - w = swk_ui(UI); - if(!w||!swk_init(w)) - return 1; - swk_loop(w); - return 0; -}