ref: 61cc0694649a4d4b109d168032f431751f57f083
dir: /sys/src/cmd/spred/pal.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <thread.h> #include <draw.h> #include <mouse.h> #include <keyboard.h> #include <frame.h> #include "dat.h" #include "fns.h" Pal * newpal(char *f) { Pal *p; p = emalloc(sizeof(*p)); p->type = PAL; p->sel = -1; filinit(p, f); return p; } void putpal(Pal *p) { int i; for(i = 0; i < p->ncol; i++) freeimage(p->ims[i]); free(p->cols); free(p->ims); } int readpal(Pal *p, Biobuf *bp) { char *s, *sp; char *args[8]; int nc, i, c; s = nil; if(tline(bp, &s, args, nelem(args)) != 2) goto err; if(strcmp(args[0], "pal") != 0) goto err; nc = strtol(args[1], &sp, 0); if(*sp != 0 || nc < 0) goto err; free(s); s = nil; p->ncol = nc; p->cols = emalloc(nc * sizeof(*p->cols)); p->ims = emalloc(nc * sizeof(*p->ims)); for(i = 0; i < nc; i++){ if(tline(bp, &s, args, nelem(args)) != 1) goto err; c = strtol(args[0], &sp, 0); if(*sp != 0 || c < 0 || c > 0xffffff) goto err; p->cols[i] = c; free(s); s = nil; } for(i = 0; i < nc; i++) p->ims[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, p->cols[i] << 8 | 0xff); p->id = getident(bp->fid); return 0; err: if(s != nil) free(s); werrstr("invalid format"); return -1; } int writepal(Pal *p, char *f) { Biobuf *bp; int i, rc, n; if(f == nil) f = p->name; bp = Bopen(f, OWRITE); if(bp == nil){ cmdprint("?%r\n"); return -1; } n = 0; rc = Bprint(bp, "pal %d\n", p->ncol); if(rc < 0) goto err; n += rc; for(i = 0; i < p->ncol; i++){ rc = Bprint(bp, "%#.6x\n", p->cols[i]); if(rc < 0) goto err; n += rc; } if(Bterm(bp) < 0){ cmdprint("?%r\n"); return -1; } p->change = 0; cmdprint("%s: #%d\n", f, n); return 0; err: cmdprint("?%r\n"); Bterm(bp); return -1; } Pal * findpal(char *sf, char *fn, int op) { File *f; char *s, *q; Ident i; int fd; Biobuf *bp; Pal *p; if(sf == nil) sf = ""; s = emalloc(strlen(sf) + strlen(fn) + 2); strcpy(s, sf); q = strrchr(s, '/'); if(q != nil) *++q = 0; else *s = 0; strcpy(s, fn); fd = open(s, OREAD); if(fd < 0){ free(s); return nil; } i = getident(fd); if(i.type == (uint)-1){ close(fd); return nil; } for(f = flist.next; f != &flist; f = f->next) if(f->type == PAL && identcmp(&f->id, &i) == 0){ close(fd); putident(i); return (Pal *) f; } putident(i); if(op == 0){ close(fd); return nil; } bp = emalloc(sizeof(*bp)); Binit(bp, fd, OREAD); p = newpal(s); if(readpal(p, bp) < 0){ putfil(p); p = nil; goto end; } end: Bterm(bp); close(fd); free(bp); free(s); return p; } static void palredraw(Pal *p) { File *f; filredraw(p); for(f = flist.next; f != &flist; f = f->next) if(f->type == SPR && ((Spr *) f)->pal == p) filredraw(f); } void palsize(Pal *p, int sz, int ch) { int i; if(sz == p->ncol) return; p->cols = realloc(p->cols, sz * sizeof(*p->cols)); p->ims = realloc(p->ims, sz * sizeof(*p->ims)); if(sz > p->ncol) for(i = p->ncol; i < sz; i++){ p->cols[i] = 0; p->ims[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0); } p->ncol = sz; if(ch) change(p); palredraw(p); } void paldraw(Win *w) { Pal *p; int n, i; Rectangle r; if(w->type != PAL || w->f == nil) sysfatal("paldraw: phase error"); p = (Pal *) w->f; n = Dx(w->inner) / w->zoom; draw(w->im, w->inner, w->tab->cols[BACK], nil, ZP); for(i = 0; i < p->ncol; i++){ r.min = addpt(w->inner.min, mulpt(Pt(i%n, i/n), w->zoom)); r.max.x = r.min.x + w->zoom; r.max.y = r.min.y + w->zoom; draw(w->im, r, p->ims[i], nil, ZP); if(p->sel == i) border(w->im, r, SELSIZ, display->white, ZP); } } void palset(Pal *p, int s, u32int c) { if(s < 0 || s >= p->ncol || p->cols[s] == c) return; p->cols[s] = c; freeimage(p->ims[s]); p->ims[s] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, c << 8 | 0xff); change(p); palredraw(p); } static int palinit(Win *w) { w->zoom = 32; return 0; } static void palzerox(Win *w, Win *v) { v->zoom = w->zoom; } static void palclick(Win *w, Mousectl *mc) { int n, i; Point pt; Pal *p; if(!ptinrect(mc->xy, w->inner)) return; if(w->f == nil) sysfatal("palclick: phase error"); p = (Pal *) w->f; n = Dx(w->inner) / w->zoom; pt = subpt(mc->xy, w->inner.min); if(pt.x >= n * w->zoom) return; i = pt.x / w->zoom + pt.y / w->zoom * n; if(i >= p->ncol) return; p->sel = i; palredraw(p); } Wintab paltab = { .init = palinit, .click = palclick, .draw = paldraw, .zerox = palzerox, .hexcols = { [BORD] 0xAA0000FF, [DISB] 0xCC8888FF, [BACK] 0xFFCCFFFF, }, };