]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/spred/spr.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / spred / spr.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <thread.h>
5 #include <draw.h>
6 #include <mouse.h>
7 #include <keyboard.h>
8 #include <frame.h>
9 #include "dat.h"
10 #include "fns.h"
11
12 Spr *
13 newspr(char *f)
14 {
15         Spr *s;
16         
17         s = emalloc(sizeof(*s));
18         s->type = SPR;
19         filinit(s, f);
20         return s;
21 }
22
23 void
24 putspr(Spr *s)
25 {
26         if(s->pal != nil && !decref(s->pal) && s->pal->change <= 0)
27                 putfil(s->pal);
28         free(s->palfile);
29         free(s->data);
30 }
31
32 int
33 readspr(Spr *s, Biobuf *bp)
34 {
35         char *args0[8], *p, *ss, **args;
36         int n, i, j;
37
38         args = nil;
39         ss = nil;
40         if(tline(bp, &ss, args0, nelem(args0)) != 4)
41                 goto err;
42         if(strcmp(args0[0], "sprite") != 0)
43                 goto err;
44         n = strtol(args0[1], &p, 0);
45         if(*p != 0 || n < 0)
46                 goto err;
47         s->w = n;
48         n = strtol(args0[2], &p, 0);
49         if(*p != 0 || n < 0)
50                 goto err;
51         s->h = n;
52         if(*args0[3] != 0)
53                 s->palfile = strdup(args0[3]);
54         else
55                 s->palfile = nil;
56         free(ss);
57         ss = nil;
58         s->data = emalloc(s->w * s->h * sizeof(u32int));
59         args = emalloc((s->w + 1) * sizeof(char *));
60         for(i = 0; i < s->h; i++){
61                 if(tline(bp, &ss, args, s->w + 1) != s->w)
62                         goto err;
63                 for(j = 0; j < s->w; j++){
64                         n = strtol(args[j], &p, 0);
65                         if(*p != 0 || n < 0)
66                                 goto err;
67                         s->data[i * s->w + j] = n;
68                 }
69                 free(ss);
70                 ss = nil;
71         }
72         free(args);
73         return 0;
74 err:
75         werrstr("invalid format");
76         free(s->data);
77         free(args);
78         s->w = 0;
79         s->h = 0;
80         return -1;
81 }
82
83 int
84 writespr(Spr *s, char *file)
85 {
86         Biobuf *bp;
87         int n, rc;
88         int i, j;
89
90         if(file == nil)
91                 file = s->name;
92         bp = Bopen(file, OWRITE);
93         if(bp == nil){
94                 cmdprint("?%r\n");
95                 return -1;
96         }
97         rc = Bprint(bp, "sprite %d %d %q\n", s->w, s->h, s->palfile != nil ? s->palfile : "");
98         if(rc < 0) goto err;
99         n = rc;
100         for(i = 0; i < s->h; i++)
101                 for(j = 0; j < s->w; j++){
102                         rc = Bprint(bp, "%d%c", s->data[s->w * i + j], j == s->w - 1 ? '\n' : ' ');
103                         if(rc < 0) goto err;
104                         n += rc;
105                 }
106         if(Bterm(bp) < 0){
107                 cmdprint("?%r\n");
108                 return -1;
109         }
110         s->change = 0;
111         quitok = 0;
112         cmdprint("%s: #%d\n", file, n);
113         return 0;
114 err:
115         cmdprint("?%r\n");
116         Bterm(bp);
117         return -1;
118 }
119
120 int
121 sprinit(Win *w)
122 {
123         w->zoom = 4;
124         return 0;
125 }
126
127 static Rectangle
128 sprrect(Win *w, Rectangle s)
129 {
130         Rectangle r;
131         Point p, q;
132         Spr *t;
133
134         t = (Spr *) w->f;
135         p = Pt(t->w * w->zoom, t->h * w->zoom);
136         q = addpt(divpt(addpt(s.min, s.max), 2), w->scr);
137         r.min = subpt(q, divpt(p, 2));
138         r.max = addpt(r.min, p);
139         return r;
140 }
141
142 static void
143 scrollbars(Win *w)
144 {
145         Rectangle r, s;
146         int dx, dy;
147         int t0, t1;
148
149         if(rectinrect(w->sprr, w->inner))
150                 return;
151         r = w->inner;
152         dx = Dx(r) - SCRTSIZ;
153         dy = Dy(r) - SCRTSIZ;
154         if(dx <= 0 || dy <= 0)
155                 return;
156         s = r;
157         if(!rectclip(&s, w->sprr))
158                 return;
159         draw(w->im, Rect(r.min.x, r.max.y - SCRBSIZ, r.max.x - SCRTSIZ, r.max.y), w->tab->cols[BORD], nil, ZP);
160         draw(w->im, Rect(r.max.x - SCRBSIZ, r.min.y, r.max.x, r.max.y - SCRTSIZ), w->tab->cols[BORD], nil, ZP);
161         t0 = (s.min.x - w->sprr.min.x) * dx / Dx(w->sprr) + r.min.x;
162         t1 = (s.max.x - w->sprr.min.x) * dx / Dx(w->sprr) + r.min.x;
163         draw(w->im, Rect(t0, r.max.y - SCRBSIZ + 1, t1, r.max.y), w->tab->cols[BACK], nil, ZP);
164         t0 = (s.min.y - w->sprr.min.y) * dy / Dy(w->sprr) + r.min.y;
165         t1 = (s.max.y - w->sprr.min.y) * dy / Dy(w->sprr) + r.min.y;
166         draw(w->im, Rect(r.max.x - SCRBSIZ, t0, r.max.x, t1), w->tab->cols[BACK], nil, ZP);
167 }
168
169 void
170 sprdraw(Win *w)
171 {
172         Rectangle r, t;
173         Spr *s;
174         Pal *p;
175         int i, j;
176         Image *im;
177         u32int *d;
178
179         if(w->type != SPR || w->f == nil)
180                 sysfatal("sprdraw: phase error");
181         s = (Spr *) w->f;
182         p = s->pal;
183         draw(w->im, w->inner, w->tab->cols[BACK], nil, ZP);
184         r = sprrect(w, w->inner);
185         w->sprr = r;
186         if(!rectinrect(r, w->inner)){
187                 t = w->inner;
188                 t.max.x -= SCRTSIZ;
189                 t.max.y -= SCRTSIZ;
190                 r = sprrect(w, t);
191                 w->sprr = r;
192                 rectclip(&r, t);
193                 scrollbars(w);
194         }
195         d = s->data;
196         for(j = 0; j < s->h; j++)
197                 for(i = 0; i < s->w; i++, d++){
198                         t.min = addpt(w->sprr.min, Pt(i * w->zoom, j * w->zoom));
199                         t.max = addpt(t.min, Pt(w->zoom, w->zoom));
200                         if(!rectclip(&t, r))
201                                 continue;
202                         if(p != nil && *d < p->ncol)
203                                 im = p->ims[*d];
204                         else
205                                 im = invcol;
206                         draw(w->im, t, im, nil, ZP);
207                 }
208 }
209
210 static int
211 sprbars(Win *w, Mousectl *mc)
212 {
213         int d;
214
215         if(rectinrect(w->sprr, w->inner))
216                 return -1;
217         if(mc->xy.x >= w->inner.max.x - SCRBSIZ){
218                 d = Dy(w->inner) / 5;
219                 switch(mc->buttons){
220                 case 1: w->scr.y += d; break;
221                 case 4: w->scr.y -= d; break;
222                 default: return 0;
223                 }
224                 sprdraw(w);
225                 return 0;
226         }
227         if(mc->xy.y >= w->inner.max.y - SCRBSIZ){
228                 d = Dx(w->inner) / 5;
229                 switch(mc->buttons){
230                 case 1: w->scr.x += d; break;
231                 case 4: w->scr.x -= d; break;
232                 default: return 0;
233                 }
234                 sprdraw(w);
235                 return 0;
236         }
237         return -1;
238 }
239
240 void
241 sprclick(Win *w, Mousectl *mc)
242 {
243         Spr *s;
244         Pal *p;
245         Point q;
246         
247         if(w->f == nil)
248                 sysfatal("sprclick: phase error");
249         if(sprbars(w, mc) >= 0)
250                 return;
251         s = (Spr *) w->f;
252         p = s->pal;
253         if(p == nil || p->sel < 0 || p->sel >= p->ncol)
254                 return;
255         do{
256                 q = divpt(subpt(mc->xy, w->sprr.min), w->zoom);
257                 if(q.x < 0 || q.y < 0 || q.x >= s->w || q.y >= s->h)
258                         continue;
259                 if(s->data[q.y * s->w + q.x] != p->sel){
260                         s->data[q.y * s->w + q.x] = p->sel;
261                         change(s);
262                         sprdraw(w);
263                 }
264         }while(readmouse(mc) >= 0 && (mc->buttons & 1) != 0);
265 }
266
267 void
268 sprsize(Spr *s, int n, int m, int ch)
269 {
270         u32int *v;
271         int i, j, w, h;
272         
273         v = s->data;
274         if(s->w == n && s->h == m)
275                 return;
276         s->data = emalloc(n * m * sizeof(u32int));
277         w = n < s->w ? n : s->w;
278         h = m < s->h ? m : s->h;
279         for(j = 0; j < h; j++)
280                 for(i = 0; i < w; i++)
281                         s->data[j * n + i] = v[j * w + i];
282         s->w = n;
283         s->h = m;
284         if(ch)
285                 change(s);
286         filredraw(s);
287 }
288
289 static char *
290 palfile(char *, char *n)
291 {
292         return strdup(n);
293 }
294
295 static void
296 sprmenu(Win *w, Mousectl *mc)
297 {
298         enum { MPAL };
299         static char *menus[] = {
300                 "pal",
301                 nil,
302         };
303         static Menu menu = {menus};
304         Win *wp;
305         Spr *s;
306         
307         if(w->f == nil)
308                 sysfatal("sprmenu: phase error");
309         s = (Spr *) w->f;
310         switch(menuhit(2, mc, &menu, scr)){
311         case MPAL:
312                 wp = winsel(mc, 2);
313                 if(wp == nil || wp->type != PAL)
314                         break;
315                 if(wp->f == nil)
316                         sysfatal("sprmenu: pal phase error");
317                 if(s->pal != (Pal *) wp->f){
318                         if(s->pal != nil && decref(s->pal) == 0 && s->pal->change <= 0)
319                                 putfil(s->pal);
320                         incref(wp->f);
321                         s->pal = (Pal *) wp->f;
322                         free(s->palfile);
323                         s->palfile = palfile(s->name, s->pal->name);
324                         cmdprint("palette set to %q\n", s->palfile);
325                         change(s);
326                         filredraw(s);
327                 }
328                 break;
329         }
330 }
331
332 static void
333 sprzerox(Win *w, Win *v)
334 {
335         v->zoom = w->zoom;
336         v->scr = w->scr;
337 }
338
339 static void
340 sprkey(Win *w, Rune r)
341 {
342         static char keys[] = "1234567890qwertyuiop";
343         char *p;
344         Spr *s;
345         
346         s = (Spr *) w->f;
347         if(s == nil)
348                 sysfatal("sprkey: phase error");
349         if(r < 0x100 && (p = strchr(keys, r)) != nil){
350                 if(s->pal == nil || p - keys >= s->pal->ncol)
351                         return;
352                 s->pal->sel = p - keys;
353                 filredraw(s->pal);
354         }
355 }
356
357 Wintab sprtab = {
358         .init = sprinit,
359         .click = sprclick,
360         .draw = sprdraw,
361         .menu = sprmenu,
362         .rmb = sprbars,
363         .zerox = sprzerox,
364         .key = sprkey,
365         .hexcols = {
366                 [BORD] 0x00AA00FF,
367                 [DISB] 0x88CC88FF,
368                 [BACK] 0xCCFFCCFF,
369         },
370 };