swk

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

commit 4f51b8003075b192d1e5237cce4b5ce4a9109420
parent ab0626c9a9a78fe128fbbdaa1216227b9990a004
Author: pancake <pancake@nopcode.org>
Date:   Tue, 27 Apr 2010 01:42:50 +0200

added FONTBOLD define in config.def.h
use gray instead of white for font color
fix overflow in putpixel function (slow but ok)
use antialiased fonts with SDL_ttf
embed 'running' variable into SwkWindow
swk_gi_fill now supports 'lil' mode (small box)
fix overflow in text rendering
vertical padding now fits better to bottom
swk_exit gets the SwkWindow instance
swk_option supports single or multioption selection mode
Diffstat:
config.def.h | 3++-
gi_sdl.c | 41++++++++++++++++++++++++++++++++++-------
swk.c | 57++++++++++++++++++++++++++++++++++++++-------------------
swk.h | 6++++--
test.c | 9++++++---
5 files changed, 84 insertions(+), 32 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -2,6 +2,7 @@ /* appearance */ #define FONTSIZE 14 +#define FONTBOLD 1 #define WINWIDTH 640 #define WINHEIGHT 480 // SDL @@ -10,7 +11,7 @@ //#define SWK_COLOR(r,g,b) r##g##b #define HICOLOR SWK_COLOR(0,66,ff) -#define FGCOLOR SWK_COLOR(ff,ff,ff) +#define FGCOLOR SWK_COLOR(e0,e0,e0) #define BGCOLOR SWK_COLOR(00,00,00) #define TFCOLOR SWK_COLOR(cc,cc,cc) diff --git a/gi_sdl.c b/gi_sdl.c @@ -1,4 +1,5 @@ /* See LICENSE file for copyright and license details. */ +#define _BSD_SOURCE // strdup #include <SDL/SDL.h> #include <SDL/SDL_ttf.h> #include "swk.h" @@ -11,6 +12,7 @@ static Uint32 pal[ColorLast]; static SDL_Color fontcolor = { TFCOLOR }; +static SDL_Color bgcolor = { BGCOLOR }; static SDL_Surface *screen = NULL; static TTF_Font *font = NULL; /* FIXME: put ugly statics into void *aux of SwkWindow */ @@ -18,9 +20,13 @@ static int has_event = 0; static SDL_Event lastev = { .type=-1 }; static void putpixel(int x, int y, Uint32 pixel) { - int bpp = screen->format->BytesPerPixel; - Uint8 *p; - p = (Uint8 *)screen->pixels + y * screen->pitch + x * bpp; + int delta, bpp = screen->format->BytesPerPixel; + Uint8 *p, *pend; + delta = y * screen->pitch + x * bpp; + p = (Uint8 *)screen->pixels + delta; + pend = (Uint8 *)screen->pixels + ((screen->h*screen->w)*bpp); + if ((p<((Uint8 *)screen->pixels)) || (p>=pend)) + return; #if BPP == 8 *p = pixel; #elif BPP == 16 @@ -58,17 +64,21 @@ swk_gi_init(SwkWindow *w) { pal[ColorFG] = SDL_MapRGB(screen->format, FGCOLOR); pal[ColorBG] = SDL_MapRGB(screen->format, BGCOLOR); pal[ColorHI] = SDL_MapRGB(screen->format, HICOLOR); - font = TTF_OpenFont(FONTNAME, FONTSIZE); + font = TTF_OpenFont(FONTNAME, FS); if(font == NULL) { fprintf(stderr, "Cannot open font '%s'\n", FONTNAME); return 0; - } else TTF_SetFontStyle(font, TTF_STYLE_BOLD); + } else + if (FONTBOLD) + TTF_SetFontStyle(font, TTF_STYLE_BOLD); return 1; } int swk_gi_update(SwkWindow *w) { screen = SDL_GetVideoSurface(); + if (screen == NULL) + return 0; w->r.w = screen->w / FS; w->r.h = screen->h / FS; return 1; @@ -136,6 +146,7 @@ swk_gi_event(SwkWindow *w, int dowait) { fprintf(stderr, "event: key %d %d\n", ret->data.key.modmask, ret->data.key.keycode); } else { + // TODO key aliases defined in config.h switch(event.key.keysym.sym) { case 273: ret->data.key.keycode = KUp; @@ -182,8 +193,15 @@ swk_gi_line(int x1, int y1, int x2, int y2, int color) { } void -swk_gi_fill(Rect r, int color) { +swk_gi_fill(Rect r, int color, int lil) { SDL_Rect area = { r.x*FS, r.y*FS, r.w*FS, r.h*FS }; + if (lil) { + const int s = FS/4; + area.x += s; + area.y += s; + area.w -= (s*2); + area.h -= (s*2); + } SDL_FillRect(screen, &area, pal[color]); } @@ -197,12 +215,21 @@ 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) { - SDL_Surface *ts = TTF_RenderText_Solid(font, text, fontcolor); + 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 }; SDL_BlitSurface(ts, NULL, screen, &to); SDL_FreeSurface(ts); } else fprintf(stderr, "Cannot render string (%s)\n", text); } + free(ptr); } diff --git a/swk.c b/swk.c @@ -5,9 +5,6 @@ #include "swk.h" #include "config.h" -// move into SwkWindow* ? -static int running = 0; - int swk_init(SwkWindow *w) { w->_e.win = w; @@ -18,10 +15,10 @@ swk_init(SwkWindow *w) { w->r.h = WINHEIGHT; } if(swk_gi_init(w)) { - running = 1; + w->running = 1; swk_update(w); } - return running; + return w->running; } void @@ -36,12 +33,12 @@ swk_update(SwkWindow *w) { b->cb(&w->_e); } swk_gi_flip(); - } else running = 0; + } else w->running = 0; } void -swk_exit(void) { - running = 0; +swk_exit(SwkWindow *w) { + w->running = 0; } void @@ -96,7 +93,7 @@ swk_fit(SwkWindow *w) { } else { swk_fit_row(w, b2, b, y); b2 = b+1; - y += (w->r.h-countrows(b2)); + y += 1+(w->r.h-countrows(b2)); if (y<0) { fprintf(stderr, "overflow: must scroll\n"); y=0; @@ -120,7 +117,7 @@ swk_focus_activate(SwkWindow *w) { SwkEvent * swk_next_event(SwkWindow *w) { - if(running) + if(w->running) return swk_gi_event(w, 1); w->_e.type = EQuit; w->_e.win = w; @@ -144,7 +141,7 @@ swk_handle_event(SwkEvent *e) { if (e->data.key.keycode==27) { e->box = e->win->box; e->type = EQuit; - swk_exit(); + swk_exit(e->win); break; } // send key to focused box @@ -222,16 +219,17 @@ swk_focus_prev(SwkWindow *w) { } } -/* widgets */ +/* -- widgets -- */ + void swk_label(SwkEvent *e) { Rect r; switch(e->type) { case EExpose: r = e->box->r; + swk_gi_text(r, e->box->text); if(e->win->box == e->box) swk_gi_line(r.x, r.y+1, r.w, 0, ColorHI); - swk_gi_text(r, e->box->text); break; default: break; @@ -302,11 +300,12 @@ swk_button(SwkEvent *e) { switch(e->type) { case EExpose: r = e->box->r; + r.x++; + swk_gi_text(r, e->box->text); + r.x--; if(e->win->box == e->box) swk_gi_rect(r, ColorHI); else swk_gi_rect(r, ColorFG); - r.x++; - swk_gi_text(r, e->box->text); break; default: break; @@ -320,19 +319,24 @@ swk_filler(SwkEvent *e) { void swk_option(SwkEvent *e) { - SwkBox **b = (SwkBox**)e->box->data; Rect r; + SwkBox **b = (SwkBox**)e->box->data; switch(e->type) { case EClick: - *b = (e->box==*b)?NULL:e->box; + if (b==(void*)0) e->box->data = (void*)1; + else if (b==(void*)1) e->box->data = (void*)0; + else *b = (e->box==*b)?NULL:e->box; break; case EExpose: r = e->box->r; if(e->win->box == e->box) swk_gi_line(r.x, r.y+1, r.w, 0, ColorHI); r.w = r.h = 1; - if(e->box==*b) swk_gi_fill(r, ColorFG); - else swk_gi_rect(r, ColorFG); + if (b==(void*)1) swk_gi_fill(r, ColorHI, 1); + else if (b==(void*)0) swk_gi_fill(r, ColorFG, 1); + else if (e->box==*b) swk_gi_fill(r, ColorHI, 1); + else swk_gi_fill(r, ColorFG, 1); + r = e->box->r; r.x += 2; swk_gi_text(r, e->box->text); break; @@ -340,3 +344,18 @@ swk_option(SwkEvent *e) { break; } } + +void +swk_separator(SwkEvent *e) { + Rect r; + switch(e->type) { + case EExpose: + r = e->box->r; + if(e->win->box == e->box) + swk_gi_line(r.x, r.y+1, r.w, 0, ColorHI); + else swk_gi_line(r.x, r.y+1, r.w, 0, ColorFG); + break; + default: + break; + } +} diff --git a/swk.h b/swk.h @@ -66,6 +66,7 @@ struct SwkBox { struct SwkWindow { char *title; + int running; Rect r; SwkBox *boxes; /* internal use */ @@ -75,7 +76,7 @@ struct SwkWindow { int swk_init(SwkWindow *w); void swk_update(SwkWindow *w); -void swk_exit(void); +void swk_exit(SwkWindow *w); void swk_fit(SwkWindow *w); void swk_loop(SwkWindow *w); SwkEvent *swk_next_event(SwkWindow *w); @@ -93,6 +94,7 @@ void swk_entry(SwkEvent *e); void swk_password(SwkEvent *e); void swk_filler(SwkEvent *e); void swk_option(SwkEvent *e); +void swk_separator(SwkEvent *e); /* graphic backend */ @@ -107,6 +109,6 @@ void swk_gi_clear(); void swk_gi_flip(); void swk_gi_line(int x1, int y1, int x2, int y2, int color); -void swk_gi_fill(Rect r, int color); +void swk_gi_fill(Rect r, int color, int lil); void swk_gi_rect(Rect r, int color); void swk_gi_text(Rect r, const char *text); diff --git a/test.c b/test.c @@ -14,27 +14,30 @@ static void mybutton(SwkEvent *e) { printf("Option: none\n"); else printf("Option: %s\n", opt->text); if(count-- == 0) - swk_exit(); + swk_exit(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="____", }, - { .cb=swk_filler, }, SWK_BOX_NEWLINE(1), { .cb=swk_label, .text="Password:", }, { .cb=swk_password, .text="1234", }, - { .cb=swk_filler, }, SWK_BOX_NEWLINE(-1), { .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(5),