#include "lib9.h"#include "draw.h"#include "tk.h" extern void rptwakeup(void*, void*);extern void* rptproc(char*, int, void*, int (*)(void*), int (*)(void*,int), void (*)(void*)); typedef struct Cmd Cmd;struct Cmd{ char* name; char* (*fn)(TkTop*, char*, char**);};static struct Cmd cmdmain[] ={ "bind", tkbind, "button", tkbutton, "canvas", tkcanvas, "checkbutton", tkcheckbutton, "choicebutton", tkchoicebutton, "cursor", tkcursorcmd, "destroy", tkdestroy, "entry", tkentry, "focus", tkfocus, "frame", tkframe, "grab", tkgrab, "grid", tkgrid, "image", tkimage, "label", tklabel, "listbox", tklistbox, "lower", tklower, "menu", tkmenu, "menubutton", tkmenubutton, "pack", tkpack, "panel", tkpanel, "puts", tkputs, "radiobutton", tkradiobutton, "raise", tkraise, "scale", tkscale, "scrollbar", tkscrollbar, "see", tkseecmd, "send", tksend, "text", tktext, "update", tkupdatecmd, "variable", tkvariable, "winfo", tkwinfo,}; char* tkfont; /* auto-repeating support * should perhaps be one rptproc per TkCtxt * This is not done for the moment as there isn't * a mechanism for terminating the rptproc */static void *autorpt;static int rptid;static Tk *rptw;static void *rptnote;static void (*rptcb)(Tk*, void*, int);static long rptto;static int rptint; /* blinking carets - should be per TkCtxt */static void *blinkrpt;static Tk *blinkw;static void (*blinkcb)(Tk*, int);static int blinkignore;static int blinkon; ulongtkrgba(int r, int g, int b, int a){ ulong p; if(r < 0) r = 0; else if(r > 255) r = 255; if(g < 0) g = 0; else if(g > 255) g = 255; if(b < 0) b = 0; else if(b > 255) b = 255; p = (r<<24)|(g<<16)|(b<<8)|0xFF; if(a == 255) return p; return setalpha(p, a);} /* to be replaced */static intrevalpha(int c, int a){ if (a == 0) return 0; return (c & 0xff) * 255 / a;} voidtkrgbavals(ulong rgba, int *R, int *G, int *B, int *A){ int a; a = rgba & 0xff; *A = a; if (a != 0xff) { *R = revalpha(rgba>>24, a); *G = revalpha((rgba>>16) & 0xFF, a); *B = revalpha((rgba >> 8) & 0xFF, a); } else { *R = (rgba>>24); *G = ((rgba>>16) & 0xFF); *B = ((rgba >> 8) & 0xFF); }} voidtkfreecolcache(TkCtxt *c){ TkCol *cc; if(c == nil) return; while((cc = c->chead) != nil){ c->chead = cc->forw; freeimage(cc->i); free(cc); } c->ctail = nil; c->ncol = 0;} Image*tkcolor(TkCtxt *c, ulong pix){ Image *i; TkCol *cc, **l; Display *d; Rectangle r; for(l = &c->chead; (cc = *l) != nil; l = &cc->forw) if(cc->rgba == pix){ /* move it up in the list */ *l = cc->forw; cc->forw = c->chead; c->chead = cc; /* we assume it will be used right away and not stored */ return cc->i; } d = c->display; if(pix == DWhite) return d->white; if(pix == DBlack) return d->black; r.min = ZP; r.max.x = 1; r.max.y = 1; if ((pix & 0xff) == 0xff) i = allocimage(d, r, RGB24, 1, pix); else i = allocimage(d, r, RGBA32, 1, pix); if(i == nil) return d->black; cc = malloc(sizeof(*cc)); if(cc == nil){ freeimage(i); return d->black; } cc->rgba = pix; cc->i = i; cc->forw = c->chead; c->chead = cc; c->ncol++; /* we'll do LRU management at some point */ if(c->ncol > TkColcachesize){ static int warn; if(warn == 0){ warn = 1; print("tk: %d colours cached\n", TkColcachesize); } } return i;} /* * XXX should be in libdraw? */inttkchanhastype(ulong c, int t){ for(; c; c>>=8) if(TYPE(c) == t) return 1; return 0;} voidtksettransparent(Tk *tk, int transparent){ if (transparent) tk->flag |= Tktransparent; else tk->flag &= ~Tktransparent;} inttkhasalpha(TkEnv *e, int col){ return (e->colors[col] & 0xff) != 0xff;} Image*tkgc(TkEnv *e, int col){ return tkcolor(e->top->ctxt, e->colors[col]);} /* * Todo: improve the fixed-point code * the 255 scale factor is used because RGB ranges 0-255 */static voidrgb2hsv(int r, int g, int b, int *h, int *s, int *v){ int min, max, delta; max = r; if(g > max) max = g; if(b > max) max = b; min = r; if(g < min) min = g; if(b < min) min = b; *v = max; if (max != 0) *s = ((max - min)*255) / max; else *s = 0; if (*s == 0) { *h = 0; /* undefined */ } else { delta = max - min; if (r == max) *h = (g - b)*255 / delta; else if (g == max) *h = (2*255) + ((b - r)*255) / delta; else if (b == max) *h = (4*255) + ((r - g)*255)/ delta; *h *= 60; if (*h < 0) *h += 360*255; *h /= 255; }} static voidhsv2rgb(int h, int s, int v, int *r, int *g, int *b){ int i; int f,p,q,t; if (s == 0 && h == 0) { *r = *g = *b = v; /* achromatic case */ } else { if (h >= 360) h = 0; i = h / 60; h *= 255; h /= 60; f = h % 255; p = v * (255 - s); q = v * (255 - ((s * f)/255)); t = v * (255- ((s * (255 - f))/255)); p /= 255; q /= 255; t /= 255; switch (i) { case 0: *r = v; *g = t; *b = p; break; case 1: *r = q; *g = v; *b = p; break; case 2: *r = p; *g = v; *b = t; break; case 3: *r = p; *g = q; *b = v; break; case 4: *r = t; *g = p; *b = v; break; case 5: *r = v; *g = p; *b = q; break; } }} enum { MINDELTA = 0x10, DELTA = 0x30,}; ulongtkrgbashade(ulong rgba, int shade){ int R, G, B, A, h, s, v, vl, vd; if (shade == TkSameshade) return rgba; tkrgbavals(rgba, &R, &G, &B, &A); h = s = v = 0; rgb2hsv(R, G, B, &h, &s, &v); if (v < MINDELTA) { vd = v+DELTA; vl = vd+DELTA; } else if (v > 255-MINDELTA) { vl = v-DELTA; vd = vl-DELTA; } else { vl = v+DELTA; vd = v-DELTA; } v = (shade == TkLightshade)?vl:vd; if (v < 0) v = 0; if (v > 255) v = 255; hsv2rgb(h, s, v, &R, &G, &B); return tkrgba(R, G, B, A);} Image*tkgshade(TkEnv *e, int col, int shade){ ulong rgba; if (col == TkCbackgnd || col == TkCselectbgnd || col == TkCactivebgnd) return tkgc(e, col+shade); rgba = tkrgbashade(e->colors[col], shade); return tkcolor(e->top->ctxt, rgba);} TkEnv*tknewenv(TkTop *t){ TkEnv *e; e = malloc(sizeof(TkEnv)); if(e == nil) return nil; e->ref = 1; e->top = t; return e;} TkEnv*tkdefaultenv(TkTop *t){ int locked; TkEnv *env; Display *d; if(t->env != nil) { t->env->ref++; return t->env; } t->env = malloc(sizeof(TkEnv)); if(t->env == nil) return nil; env = t->env; env->ref = 1; env->top = t; if(tkfont == nil) tkfont = "/fonts/pelm/unicode.8.font"; d = t->display; env->font = font_open(d, tkfont); if(env->font == nil) { static int warn; if(warn == 0) { warn = 1; print("tk: font not found: %s\n", tkfont); } env->font = font_open(d, "*default*"); if(env->font == nil) { free(t->env); t->env = nil; return nil; } } locked = lockdisplay(d); env->wzero = stringwidth(env->font, "0"); if ( env->wzero <= 0 ) env->wzero = env->font->height / 2; if(locked) unlockdisplay(d); tksetenvcolours(env); return env;} voidtkputenv(TkEnv *env){ Display *d; int locked; if(env == nil) return; env->ref--; if(env->ref != 0) return; d = env->top->display; locked = lockdisplay(d); if(env->font != nil) font_close(env->font); if(locked) unlockdisplay(d); free(env);} TkEnv*tkdupenv(TkEnv **env){ Display *d; TkEnv *e, *ne; e = *env; if(e->ref == 1) return e; ne = malloc(sizeof(TkEnv)); if(ne == nil) return nil; ne->ref = 1; ne->top = e->top; d = e->top->display; memmove(ne->colors, e->colors, sizeof(e->colors)); ne->set = e->set; ne->font = font_open(d, e->font->name); ne->wzero = e->wzero; e->ref--; *env = ne; return ne;} Tk*tknewobj(TkTop *t, int type, int n){ Tk *tk; tk = malloc(n); if(tk == 0) return 0; tk->type = type; /* Defaults */ tk->flag = Tktop; tk->relief = TKflat; tk->env = tkdefaultenv(t); if(tk->env == nil) { free(tk); return nil; } return tk;} voidtkfreebind(TkAction *a){ TkAction *next; while(a != nil) { next = a->link; if((a->type & 0xff) == TkDynamic) free(a->arg); free(a); a = next; }} voidtkfreename(TkName *f)Lines 1–500 of 1952. Load more
#include "lib9.h" #include "draw.h" #include "tk.h" extern void rptwakeup(void*, void*); extern void* rptproc(char*, int, void*, int (*)(void*), int (*)(void*,int), void (*)(void*)); typedef struct Cmd Cmd; struct Cmd { char* name; char* (*fn)(TkTop*, char*, char**); }; static struct Cmd cmdmain[] = { "bind", tkbind, "button", tkbutton, "canvas", tkcanvas, "checkbutton", tkcheckbutton, "choicebutton", tkchoicebutton, "cursor", tkcursorcmd, "destroy", tkdestroy, "entry", tkentry, "focus", tkfocus, "frame", tkframe, "grab", tkgrab, "grid", tkgrid, "image", tkimage, "label", tklabel, "listbox", tklistbox, "lower", tklower, "menu", tkmenu, "menubutton", tkmenubutton, "pack", tkpack, "panel", tkpanel, "puts", tkputs, "radiobutton", tkradiobutton, "raise", tkraise, "scale", tkscale, "scrollbar", tkscrollbar, "see", tkseecmd, "send", tksend, "text", tktext, "update", tkupdatecmd, "variable", tkvariable, "winfo", tkwinfo, }; char* tkfont; /* auto-repeating support * should perhaps be one rptproc per TkCtxt * This is not done for the moment as there isn't * a mechanism for terminating the rptproc */ static void *autorpt; static int rptid; static Tk *rptw; static void *rptnote; static void (*rptcb)(Tk*, void*, int); static long rptto; static int rptint; /* blinking carets - should be per TkCtxt */ static void *blinkrpt; static Tk *blinkw; static void (*blinkcb)(Tk*, int); static int blinkignore; static int blinkon; ulong tkrgba(int r, int g, int b, int a) { ulong p; if(r < 0) r = 0; else if(r > 255) r = 255; if(g < 0) g = 0; else if(g > 255) g = 255; if(b < 0) b = 0; else if(b > 255) b = 255; p = (r<<24)|(g<<16)|(b<<8)|0xFF; if(a == 255) return p; return setalpha(p, a); } /* to be replaced */ static int revalpha(int c, int a) { if (a == 0) return 0; return (c & 0xff) * 255 / a; } void tkrgbavals(ulong rgba, int *R, int *G, int *B, int *A) { int a; a = rgba & 0xff; *A = a; if (a != 0xff) { *R = revalpha(rgba>>24, a); *G = revalpha((rgba>>16) & 0xFF, a); *B = revalpha((rgba >> 8) & 0xFF, a); } else { *R = (rgba>>24); *G = ((rgba>>16) & 0xFF); *B = ((rgba >> 8) & 0xFF); } } void tkfreecolcache(TkCtxt *c) { TkCol *cc; if(c == nil) return; while((cc = c->chead) != nil){ c->chead = cc->forw; freeimage(cc->i); free(cc); } c->ctail = nil; c->ncol = 0; } Image* tkcolor(TkCtxt *c, ulong pix) { Image *i; TkCol *cc, **l; Display *d; Rectangle r; for(l = &c->chead; (cc = *l) != nil; l = &cc->forw) if(cc->rgba == pix){ /* move it up in the list */ *l = cc->forw; cc->forw = c->chead; c->chead = cc; /* we assume it will be used right away and not stored */ return cc->i; } d = c->display; if(pix == DWhite) return d->white; if(pix == DBlack) return d->black; r.min = ZP; r.max.x = 1; r.max.y = 1; if ((pix & 0xff) == 0xff) i = allocimage(d, r, RGB24, 1, pix); else i = allocimage(d, r, RGBA32, 1, pix); if(i == nil) return d->black; cc = malloc(sizeof(*cc)); if(cc == nil){ freeimage(i); return d->black; } cc->rgba = pix; cc->i = i; cc->forw = c->chead; c->chead = cc; c->ncol++; /* we'll do LRU management at some point */ if(c->ncol > TkColcachesize){ static int warn; if(warn == 0){ warn = 1; print("tk: %d colours cached\n", TkColcachesize); } } return i; } /* * XXX should be in libdraw? */ int tkchanhastype(ulong c, int t) { for(; c; c>>=8) if(TYPE(c) == t) return 1; return 0; } void tksettransparent(Tk *tk, int transparent) { if (transparent) tk->flag |= Tktransparent; else tk->flag &= ~Tktransparent; } int tkhasalpha(TkEnv *e, int col) { return (e->colors[col] & 0xff) != 0xff; } Image* tkgc(TkEnv *e, int col) { return tkcolor(e->top->ctxt, e->colors[col]); } /* * Todo: improve the fixed-point code * the 255 scale factor is used because RGB ranges 0-255 */ static void rgb2hsv(int r, int g, int b, int *h, int *s, int *v) { int min, max, delta; max = r; if(g > max) max = g; if(b > max) max = b; min = r; if(g < min) min = g; if(b < min) min = b; *v = max; if (max != 0) *s = ((max - min)*255) / max; else *s = 0; if (*s == 0) { *h = 0; /* undefined */ } else { delta = max - min; if (r == max) *h = (g - b)*255 / delta; else if (g == max) *h = (2*255) + ((b - r)*255) / delta; else if (b == max) *h = (4*255) + ((r - g)*255)/ delta; *h *= 60; if (*h < 0) *h += 360*255; *h /= 255; } } static void hsv2rgb(int h, int s, int v, int *r, int *g, int *b) { int i; int f,p,q,t; if (s == 0 && h == 0) { *r = *g = *b = v; /* achromatic case */ } else { if (h >= 360) h = 0; i = h / 60; h *= 255; h /= 60; f = h % 255; p = v * (255 - s); q = v * (255 - ((s * f)/255)); t = v * (255- ((s * (255 - f))/255)); p /= 255; q /= 255; t /= 255; switch (i) { case 0: *r = v; *g = t; *b = p; break; case 1: *r = q; *g = v; *b = p; break; case 2: *r = p; *g = v; *b = t; break; case 3: *r = p; *g = q; *b = v; break; case 4: *r = t; *g = p; *b = v; break; case 5: *r = v; *g = p; *b = q; break; } } } enum { MINDELTA = 0x10, DELTA = 0x30, }; ulong tkrgbashade(ulong rgba, int shade) { int R, G, B, A, h, s, v, vl, vd; if (shade == TkSameshade) return rgba; tkrgbavals(rgba, &R, &G, &B, &A); h = s = v = 0; rgb2hsv(R, G, B, &h, &s, &v); if (v < MINDELTA) { vd = v+DELTA; vl = vd+DELTA; } else if (v > 255-MINDELTA) { vl = v-DELTA; vd = vl-DELTA; } else { vl = v+DELTA; vd = v-DELTA; } v = (shade == TkLightshade)?vl:vd; if (v < 0) v = 0; if (v > 255) v = 255; hsv2rgb(h, s, v, &R, &G, &B); return tkrgba(R, G, B, A); } Image* tkgshade(TkEnv *e, int col, int shade) { ulong rgba; if (col == TkCbackgnd || col == TkCselectbgnd || col == TkCactivebgnd) return tkgc(e, col+shade); rgba = tkrgbashade(e->colors[col], shade); return tkcolor(e->top->ctxt, rgba); } TkEnv* tknewenv(TkTop *t) { TkEnv *e; e = malloc(sizeof(TkEnv)); if(e == nil) return nil; e->ref = 1; e->top = t; return e; } TkEnv* tkdefaultenv(TkTop *t) { int locked; TkEnv *env; Display *d; if(t->env != nil) { t->env->ref++; return t->env; } t->env = malloc(sizeof(TkEnv)); if(t->env == nil) return nil; env = t->env; env->ref = 1; env->top = t; if(tkfont == nil) tkfont = "/fonts/pelm/unicode.8.font"; d = t->display; env->font = font_open(d, tkfont); if(env->font == nil) { static int warn; if(warn == 0) { warn = 1; print("tk: font not found: %s\n", tkfont); } env->font = font_open(d, "*default*"); if(env->font == nil) { free(t->env); t->env = nil; return nil; } } locked = lockdisplay(d); env->wzero = stringwidth(env->font, "0"); if ( env->wzero <= 0 ) env->wzero = env->font->height / 2; if(locked) unlockdisplay(d); tksetenvcolours(env); return env; } void tkputenv(TkEnv *env) { Display *d; int locked; if(env == nil) return; env->ref--; if(env->ref != 0) return; d = env->top->display; locked = lockdisplay(d); if(env->font != nil) font_close(env->font); if(locked) unlockdisplay(d); free(env); } TkEnv* tkdupenv(TkEnv **env) { Display *d; TkEnv *e, *ne; e = *env; if(e->ref == 1) return e; ne = malloc(sizeof(TkEnv)); if(ne == nil) return nil; ne->ref = 1; ne->top = e->top; d = e->top->display; memmove(ne->colors, e->colors, sizeof(e->colors)); ne->set = e->set; ne->font = font_open(d, e->font->name); ne->wzero = e->wzero; e->ref--; *env = ne; return ne; } Tk* tknewobj(TkTop *t, int type, int n) { Tk *tk; tk = malloc(n); if(tk == 0) return 0; tk->type = type; /* Defaults */ tk->flag = Tktop; tk->relief = TKflat; tk->env = tkdefaultenv(t); if(tk->env == nil) { free(tk); return nil; } return tk; } void tkfreebind(TkAction *a) { TkAction *next; while(a != nil) { next = a->link; if((a->type & 0xff) == TkDynamic) free(a->arg); free(a); a = next; } } void tkfreename(TkName *f)