]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/spred/cmdw.c
added sprite editor spred
[plan9front.git] / sys / src / cmd / spred / cmdw.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 <frame.h>
8 #include "dat.h"
9 #include "fns.h"
10
11 static int
12 cmdinit(Win *)
13 {
14         return 0;
15 }
16
17 static void
18 scrollbar(Win *w)
19 {
20         int h, t0, t1;
21
22         h = Dy(w->inner);
23         draw(w->im, rectaddpt(Rect(0, 0, SCRBSIZ+1, h), w->inner.min), w->tab->cols[BORD], nil, ZP);
24         t0 = w->toprune * h;
25         t1 = (w->toprune + w->fr.nchars) * h;
26         if(w->nrunes == 0){
27                  t0 = 0;
28                  t1 = h;
29         }else{
30                 t0 /= w->nrunes;
31                 t1 /= w->nrunes;
32         }
33         draw(w->im, rectaddpt(Rect(0, t0, SCRBSIZ, t1), w->inner.min), w->tab->cols[BACK], nil, ZP);
34 }
35
36 static void
37 cmddraw(Win *w)
38 {
39         Rectangle r;
40         
41         frclear(&w->fr, 0);
42         r = insetrect(w->inner, 1);
43         r.min.x += SCRTSIZ;
44         scrollbar(w);
45         frinit(&w->fr, r, display->defaultfont, w->im, w->tab->cols);
46         frinsert(&w->fr, w->runes + w->toprune, w->runes + w->nrunes, 0);
47 }
48
49 void
50 cmdscroll(Win *w, int l)
51 {
52         int r;
53         
54         if(l == 0)
55                 return;
56         if(l > 0){
57                 for(r = w->toprune; r < w->nrunes && l != 0; r++)
58                         if(w->runes[r] == '\n')
59                                 l--;
60                 frdelete(&w->fr, 0, r - w->toprune);
61                 w->toprune = r;
62         }else{
63                 for(r = w->toprune; r > 0; r--)
64                         if(w->runes[r] == '\n' && --l == 0)
65                                 break;
66                 frinsert(&w->fr, w->runes + r, w->runes + w->toprune, 0);
67                 w->toprune = r;
68         }
69         scrollbar(w);
70 }
71
72 static void
73 cmdclick(Win *w, Mousectl *mc)
74 {
75         if(mc->xy.x <= w->inner.min.x + SCRBSIZ){
76                 cmdscroll(w, -5);
77                 return;
78         }
79         frselect(&w->fr, mc);
80 }
81
82 static int
83 cmdrmb(Win *w, Mousectl *mc)
84 {
85         if(mc->xy.x > w->inner.min.x + SCRBSIZ)
86                 return -1;
87         cmdscroll(w, 5);
88         return 0;
89 }
90
91 void
92 cmdinsert(Win *w, Rune *r, int nr, int rp)
93 {
94         Rune *s;
95
96         if(nr < 0)
97                 for(nr = 0, s = r; *s++ != 0; nr++)
98                         ;
99         if(rp < 0 || rp > w->nrunes)
100                 rp = w->nrunes;
101         if(w->nrunes + nr > w->arunes){
102                 w->runes = realloc(w->runes, w->arunes = w->arunes + (nr + RUNEBLK - 1) & ~(RUNEBLK - 1));
103                 if(w->runes == nil)
104                         sysfatal("realloc: %r");
105         }
106         if(rp != w->nrunes)
107                 memmove(w->runes + rp, w->runes + rp + nr, (w->nrunes - rp) * sizeof(Rune));
108         memmove(w->runes + rp, r, nr * sizeof(Rune));
109         w->nrunes += nr;
110         if(w->toprune > rp)
111                 w->toprune += nr;
112         else{
113                 frinsert(&w->fr, w->runes + rp, w->runes + rp + nr, rp - w->toprune);
114                 if(rp == w->nrunes - nr){
115                         if(w->fr.lastlinefull)
116                                 cmdscroll(w, 1);
117                 }
118         }
119 }
120
121 static void
122 cmddel(Win *w, int a, int b)
123 {
124         if(a >= b)
125                 return;
126         memmove(w->runes + a, w->runes + b, w->nrunes - b);
127         w->nrunes -= b - a;
128         if(w->toprune >= b)
129                 w->toprune -= b - a;
130         else{
131                 frdelete(&w->fr, a - w->toprune, b - w->toprune);
132                 if(w->toprune >= a)
133                         w->toprune = a;
134         }
135 }
136
137 static void
138 cmdkey(Win *w, Rune r)
139 {
140         static char buf[4096];
141         char *p;
142         Rune *q;
143
144         if(w->fr.p0 < w->fr.p1)
145                 cmddel(w, w->toprune + w->fr.p0, w->toprune + w->fr.p1);
146         switch(r){
147         case 0x00:
148         case 0x1b:
149                 break;
150         case '\b':
151                 if(w->fr.p0 > 0)
152                         cmddel(w, w->toprune + w->fr.p0 - 1, w->toprune + w->fr.p0);
153                 break;
154         case '\n':
155                 cmdinsert(w, &r, 1, w->fr.p0 + w->toprune);
156                 if(w->toprune + w->fr.p0 == w->nrunes){
157                         q = w->runes + w->toprune + w->fr.p0 - 1;
158                         p = buf;
159                         while(*--q != 0xa && q > w->runes)
160                                 ;
161                         if(*q == 0xa)
162                                 q++;
163                         while(q < w->runes + w->nrunes && p < buf + nelem(buf) + 1 && *q != 0xa)
164                                 p += runetochar(p, q++);
165                         *p = 0;
166                         docmd(buf);
167                 }
168                 break;
169         default:
170                 cmdinsert(w, &r, 1, w->fr.p0 + w->toprune);
171         }
172 }
173
174 void
175 cmdprint(char *fmt, ...)
176 {
177         Rune *r;
178         va_list va;
179         
180         va_start(va, fmt);
181         r = runevsmprint(fmt, va);
182         va_end(va);
183         if(r != nil)
184                 cmdinsert(cmdw, r, -1, -1);
185 }
186
187 Wintab cmdtab = {
188         .init = cmdinit,
189         .draw = cmddraw,
190         .click = cmdclick,
191         .rmb = cmdrmb,
192         .key = cmdkey,
193         .hexcols = {
194                 [BORD] DPurpleblue,
195                 [DISB] 0xCCCCEEFF,
196                 [BACK] 0xCCFFFFFF,
197                 [HIGH] DPalegreygreen
198         }
199 };