Blame


1 24c02865 2005-01-04 devnull /*
2 24c02865 2005-01-04 devnull * the actual viewer that handles screen stuff
3 24c02865 2005-01-04 devnull */
4 24c02865 2005-01-04 devnull
5 24c02865 2005-01-04 devnull #include <u.h>
6 24c02865 2005-01-04 devnull #include <libc.h>
7 24c02865 2005-01-04 devnull #include <draw.h>
8 24c02865 2005-01-04 devnull #include <cursor.h>
9 17157e4a 2006-03-20 devnull #include <cursor.h>
10 24c02865 2005-01-04 devnull #include <event.h>
11 24c02865 2005-01-04 devnull #include <bio.h>
12 24c02865 2005-01-04 devnull #include <plumb.h>
13 24c02865 2005-01-04 devnull #include <ctype.h>
14 24c02865 2005-01-04 devnull #include <keyboard.h>
15 24c02865 2005-01-04 devnull #include "page.h"
16 24c02865 2005-01-04 devnull
17 24c02865 2005-01-04 devnull Document *doc;
18 24c02865 2005-01-04 devnull Image *im;
19 24c02865 2005-01-04 devnull int page;
20 17157e4a 2006-03-20 devnull int angle = 0;
21 24c02865 2005-01-04 devnull int showbottom = 0; /* on the next showpage, move the image so the bottom is visible. */
22 24c02865 2005-01-04 devnull
23 24c02865 2005-01-04 devnull Rectangle ulrange; /* the upper left corner of the image must be in this rectangle */
24 24c02865 2005-01-04 devnull Point ul; /* the upper left corner of the image is at this point on the screen */
25 24c02865 2005-01-04 devnull
26 24c02865 2005-01-04 devnull Point pclip(Point, Rectangle);
27 24c02865 2005-01-04 devnull Rectangle mkrange(Rectangle screenr, Rectangle imr);
28 24c02865 2005-01-04 devnull void redraw(Image*);
29 24c02865 2005-01-04 devnull
30 24c02865 2005-01-04 devnull Cursor reading={
31 24c02865 2005-01-04 devnull {-1, -1},
32 24c02865 2005-01-04 devnull {0xff, 0x80, 0xff, 0x80, 0xff, 0x00, 0xfe, 0x00,
33 24c02865 2005-01-04 devnull 0xff, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xef, 0xe0,
34 24c02865 2005-01-04 devnull 0xc7, 0xf0, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0xc0,
35 24c02865 2005-01-04 devnull 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, },
36 24c02865 2005-01-04 devnull {0x00, 0x00, 0x7f, 0x00, 0x7e, 0x00, 0x7c, 0x00,
37 24c02865 2005-01-04 devnull 0x7e, 0x00, 0x7f, 0x00, 0x6f, 0x80, 0x47, 0xc0,
38 24c02865 2005-01-04 devnull 0x03, 0xe0, 0x01, 0xf0, 0x00, 0xe0, 0x00, 0x40,
39 24c02865 2005-01-04 devnull 0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
40 24c02865 2005-01-04 devnull };
41 24c02865 2005-01-04 devnull
42 24c02865 2005-01-04 devnull Cursor query = {
43 24c02865 2005-01-04 devnull {-7,-7},
44 24c02865 2005-01-04 devnull {0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe,
45 24c02865 2005-01-04 devnull 0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8,
46 24c02865 2005-01-04 devnull 0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0,
47 24c02865 2005-01-04 devnull 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, },
48 24c02865 2005-01-04 devnull {0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c,
49 24c02865 2005-01-04 devnull 0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0,
50 24c02865 2005-01-04 devnull 0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80,
51 24c02865 2005-01-04 devnull 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
52 24c02865 2005-01-04 devnull };
53 24c02865 2005-01-04 devnull
54 24c02865 2005-01-04 devnull enum {
55 24c02865 2005-01-04 devnull Left = 1,
56 24c02865 2005-01-04 devnull Middle = 2,
57 24c02865 2005-01-04 devnull Right = 4,
58 24c02865 2005-01-04 devnull
59 cbeb0b26 2006-04-01 devnull RMenu = 3
60 24c02865 2005-01-04 devnull };
61 24c02865 2005-01-04 devnull
62 24c02865 2005-01-04 devnull void
63 24c02865 2005-01-04 devnull unhide(void)
64 24c02865 2005-01-04 devnull {
65 24c02865 2005-01-04 devnull static int wctl = -1;
66 24c02865 2005-01-04 devnull
67 24c02865 2005-01-04 devnull if(wctl < 0)
68 24c02865 2005-01-04 devnull wctl = open("/dev/wctl", OWRITE);
69 24c02865 2005-01-04 devnull if(wctl < 0)
70 24c02865 2005-01-04 devnull return;
71 24c02865 2005-01-04 devnull
72 24c02865 2005-01-04 devnull write(wctl, "unhide", 6);
73 24c02865 2005-01-04 devnull }
74 24c02865 2005-01-04 devnull
75 24c02865 2005-01-04 devnull int
76 24c02865 2005-01-04 devnull max(int a, int b)
77 24c02865 2005-01-04 devnull {
78 24c02865 2005-01-04 devnull return a > b ? a : b;
79 24c02865 2005-01-04 devnull }
80 24c02865 2005-01-04 devnull
81 24c02865 2005-01-04 devnull int
82 24c02865 2005-01-04 devnull min(int a, int b)
83 24c02865 2005-01-04 devnull {
84 24c02865 2005-01-04 devnull return a < b ? a : b;
85 24c02865 2005-01-04 devnull }
86 24c02865 2005-01-04 devnull
87 24c02865 2005-01-04 devnull
88 24c02865 2005-01-04 devnull char*
89 24c02865 2005-01-04 devnull menugen(int n)
90 24c02865 2005-01-04 devnull {
91 24c02865 2005-01-04 devnull static char menustr[32];
92 24c02865 2005-01-04 devnull char *p;
93 24c02865 2005-01-04 devnull int len;
94 24c02865 2005-01-04 devnull
95 24c02865 2005-01-04 devnull if(n == doc->npage)
96 24c02865 2005-01-04 devnull return "exit";
97 24c02865 2005-01-04 devnull if(n > doc->npage)
98 24c02865 2005-01-04 devnull return nil;
99 24c02865 2005-01-04 devnull
100 24c02865 2005-01-04 devnull if(reverse)
101 24c02865 2005-01-04 devnull n = doc->npage-1-n;
102 24c02865 2005-01-04 devnull
103 24c02865 2005-01-04 devnull p = doc->pagename(doc, n);
104 24c02865 2005-01-04 devnull len = (sizeof menustr)-2;
105 24c02865 2005-01-04 devnull
106 24c02865 2005-01-04 devnull if(strlen(p) > len && strrchr(p, '/'))
107 24c02865 2005-01-04 devnull p = strrchr(p, '/')+1;
108 24c02865 2005-01-04 devnull if(strlen(p) > len)
109 24c02865 2005-01-04 devnull p = p+strlen(p)-len;
110 24c02865 2005-01-04 devnull
111 24c02865 2005-01-04 devnull strcpy(menustr+1, p);
112 24c02865 2005-01-04 devnull if(page == n)
113 24c02865 2005-01-04 devnull menustr[0] = '>';
114 24c02865 2005-01-04 devnull else
115 24c02865 2005-01-04 devnull menustr[0] = ' ';
116 24c02865 2005-01-04 devnull return menustr;
117 24c02865 2005-01-04 devnull }
118 24c02865 2005-01-04 devnull
119 24c02865 2005-01-04 devnull void
120 24c02865 2005-01-04 devnull showpage(int page, Menu *m)
121 24c02865 2005-01-04 devnull {
122 24c02865 2005-01-04 devnull Image *tmp;
123 24c02865 2005-01-04 devnull
124 24c02865 2005-01-04 devnull if(doc->fwdonly)
125 24c02865 2005-01-04 devnull m->lasthit = 0; /* this page */
126 24c02865 2005-01-04 devnull else
127 24c02865 2005-01-04 devnull m->lasthit = reverse ? doc->npage-1-page : page;
128 24c02865 2005-01-04 devnull
129 24c02865 2005-01-04 devnull esetcursor(&reading);
130 24c02865 2005-01-04 devnull freeimage(im);
131 24c02865 2005-01-04 devnull if((page < 0 || page >= doc->npage) && !doc->fwdonly){
132 24c02865 2005-01-04 devnull im = nil;
133 24c02865 2005-01-04 devnull return;
134 24c02865 2005-01-04 devnull }
135 24c02865 2005-01-04 devnull im = doc->drawpage(doc, page);
136 24c02865 2005-01-04 devnull if(im == nil) {
137 24c02865 2005-01-04 devnull if(doc->fwdonly) /* this is how we know we're out of pages */
138 24c02865 2005-01-04 devnull wexits(0);
139 24c02865 2005-01-04 devnull
140 24c02865 2005-01-04 devnull im = xallocimage(display, Rect(0,0,50,50), GREY1, 1, DBlack);
141 24c02865 2005-01-04 devnull if(im == nil) {
142 24c02865 2005-01-04 devnull fprint(2, "out of memory: %r\n");
143 24c02865 2005-01-04 devnull wexits("memory");
144 24c02865 2005-01-04 devnull }
145 24c02865 2005-01-04 devnull string(im, ZP, display->white, ZP, display->defaultfont, "?");
146 24c02865 2005-01-04 devnull }else if(resizing){
147 24c02865 2005-01-04 devnull resize(Dx(im->r), Dy(im->r));
148 24c02865 2005-01-04 devnull }
149 24c02865 2005-01-04 devnull if(im->r.min.x > 0 || im->r.min.y > 0) {
150 24c02865 2005-01-04 devnull tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill);
151 24c02865 2005-01-04 devnull if(tmp == nil) {
152 24c02865 2005-01-04 devnull fprint(2, "out of memory during showpage: %r\n");
153 24c02865 2005-01-04 devnull wexits("memory");
154 24c02865 2005-01-04 devnull }
155 24c02865 2005-01-04 devnull drawop(tmp, tmp->r, im, nil, im->r.min, S);
156 24c02865 2005-01-04 devnull freeimage(im);
157 24c02865 2005-01-04 devnull im = tmp;
158 24c02865 2005-01-04 devnull }
159 24c02865 2005-01-04 devnull
160 17157e4a 2006-03-20 devnull switch(angle){
161 17157e4a 2006-03-20 devnull case 90:
162 17157e4a 2006-03-20 devnull im = rot90(im);
163 17157e4a 2006-03-20 devnull break;
164 17157e4a 2006-03-20 devnull case 180:
165 24c02865 2005-01-04 devnull rot180(im);
166 17157e4a 2006-03-20 devnull break;
167 17157e4a 2006-03-20 devnull case 270:
168 17157e4a 2006-03-20 devnull im = rot270(im);
169 17157e4a 2006-03-20 devnull break;
170 17157e4a 2006-03-20 devnull }
171 24c02865 2005-01-04 devnull
172 24c02865 2005-01-04 devnull esetcursor(nil);
173 24c02865 2005-01-04 devnull if(showbottom){
174 24c02865 2005-01-04 devnull ul.y = screen->r.max.y - Dy(im->r);
175 24c02865 2005-01-04 devnull showbottom = 0;
176 24c02865 2005-01-04 devnull }
177 24c02865 2005-01-04 devnull
178 24c02865 2005-01-04 devnull redraw(screen);
179 24c02865 2005-01-04 devnull flushimage(display, 1);
180 24c02865 2005-01-04 devnull }
181 24c02865 2005-01-04 devnull
182 24c02865 2005-01-04 devnull char*
183 24c02865 2005-01-04 devnull writebitmap(void)
184 24c02865 2005-01-04 devnull {
185 24c02865 2005-01-04 devnull char basename[64];
186 24c02865 2005-01-04 devnull char name[64+30];
187 24c02865 2005-01-04 devnull static char result[200];
188 24c02865 2005-01-04 devnull char *p, *q;
189 24c02865 2005-01-04 devnull int fd;
190 24c02865 2005-01-04 devnull
191 24c02865 2005-01-04 devnull if(im == nil)
192 24c02865 2005-01-04 devnull return "no image";
193 24c02865 2005-01-04 devnull
194 24c02865 2005-01-04 devnull memset(basename, 0, sizeof basename);
195 24c02865 2005-01-04 devnull if(doc->docname)
196 24c02865 2005-01-04 devnull strncpy(basename, doc->docname, sizeof(basename)-1);
197 24c02865 2005-01-04 devnull else if((p = menugen(page)) && p[0] != '\0')
198 24c02865 2005-01-04 devnull strncpy(basename, p+1, sizeof(basename)-1);
199 24c02865 2005-01-04 devnull
200 24c02865 2005-01-04 devnull if(basename[0]) {
201 24c02865 2005-01-04 devnull if(q = strrchr(basename, '/'))
202 24c02865 2005-01-04 devnull q++;
203 24c02865 2005-01-04 devnull else
204 24c02865 2005-01-04 devnull q = basename;
205 24c02865 2005-01-04 devnull if(p = strchr(q, '.'))
206 24c02865 2005-01-04 devnull *p = 0;
207 24c02865 2005-01-04 devnull
208 24c02865 2005-01-04 devnull memset(name, 0, sizeof name);
209 24c02865 2005-01-04 devnull snprint(name, sizeof(name)-1, "%s.%d.bit", q, page+1);
210 24c02865 2005-01-04 devnull if(access(name, 0) >= 0) {
211 24c02865 2005-01-04 devnull strcat(name, "XXXX");
212 24c02865 2005-01-04 devnull mktemp(name);
213 24c02865 2005-01-04 devnull }
214 24c02865 2005-01-04 devnull if(access(name, 0) >= 0)
215 24c02865 2005-01-04 devnull return "couldn't think of a name for bitmap";
216 24c02865 2005-01-04 devnull } else {
217 24c02865 2005-01-04 devnull strcpy(name, "bitXXXX");
218 24c02865 2005-01-04 devnull mktemp(name);
219 24c02865 2005-01-04 devnull if(access(name, 0) >= 0)
220 24c02865 2005-01-04 devnull return "couldn't think of a name for bitmap";
221 24c02865 2005-01-04 devnull }
222 24c02865 2005-01-04 devnull
223 24c02865 2005-01-04 devnull if((fd = create(name, OWRITE, 0666)) < 0) {
224 24c02865 2005-01-04 devnull snprint(result, sizeof result, "cannot create %s: %r", name);
225 24c02865 2005-01-04 devnull return result;
226 24c02865 2005-01-04 devnull }
227 24c02865 2005-01-04 devnull
228 24c02865 2005-01-04 devnull if(writeimage(fd, im, 0) < 0) {
229 24c02865 2005-01-04 devnull snprint(result, sizeof result, "cannot writeimage: %r");
230 24c02865 2005-01-04 devnull close(fd);
231 24c02865 2005-01-04 devnull return result;
232 24c02865 2005-01-04 devnull }
233 24c02865 2005-01-04 devnull close(fd);
234 24c02865 2005-01-04 devnull
235 24c02865 2005-01-04 devnull snprint(result, sizeof result, "wrote %s", name);
236 24c02865 2005-01-04 devnull return result;
237 24c02865 2005-01-04 devnull }
238 24c02865 2005-01-04 devnull
239 24c02865 2005-01-04 devnull static void translate(Point);
240 24c02865 2005-01-04 devnull
241 24c02865 2005-01-04 devnull static int
242 24c02865 2005-01-04 devnull showdata(Plumbmsg *msg)
243 24c02865 2005-01-04 devnull {
244 24c02865 2005-01-04 devnull char *s;
245 24c02865 2005-01-04 devnull
246 24c02865 2005-01-04 devnull s = plumblookup(msg->attr, "action");
247 24c02865 2005-01-04 devnull return s && strcmp(s, "showdata")==0;
248 24c02865 2005-01-04 devnull }
249 24c02865 2005-01-04 devnull
250 24c02865 2005-01-04 devnull /* correspond to entries in miditems[] below,
251 24c02865 2005-01-04 devnull * changing one means you need to change
252 24c02865 2005-01-04 devnull */
253 24c02865 2005-01-04 devnull enum{
254 24c02865 2005-01-04 devnull Restore = 0,
255 24c02865 2005-01-04 devnull Zin,
256 24c02865 2005-01-04 devnull Fit,
257 24c02865 2005-01-04 devnull Rot,
258 24c02865 2005-01-04 devnull Upside,
259 24c02865 2005-01-04 devnull Empty1,
260 24c02865 2005-01-04 devnull Next,
261 24c02865 2005-01-04 devnull Prev,
262 24c02865 2005-01-04 devnull Zerox,
263 24c02865 2005-01-04 devnull Empty2,
264 24c02865 2005-01-04 devnull Reverse,
265 24c02865 2005-01-04 devnull Del,
266 24c02865 2005-01-04 devnull Write,
267 24c02865 2005-01-04 devnull Empty3,
268 cbeb0b26 2006-04-01 devnull Exit
269 24c02865 2005-01-04 devnull };
270 24c02865 2005-01-04 devnull
271 24c02865 2005-01-04 devnull void
272 24c02865 2005-01-04 devnull viewer(Document *dd)
273 24c02865 2005-01-04 devnull {
274 24c02865 2005-01-04 devnull int i, fd, n, oldpage;
275 24c02865 2005-01-04 devnull int nxt;
276 24c02865 2005-01-04 devnull Menu menu, midmenu;
277 24c02865 2005-01-04 devnull Mouse m;
278 24c02865 2005-01-04 devnull Event e;
279 24c02865 2005-01-04 devnull Point dxy, oxy, xy0;
280 24c02865 2005-01-04 devnull Rectangle r;
281 24c02865 2005-01-04 devnull Image *tmp;
282 24c02865 2005-01-04 devnull static char *fwditems[] = { "this page", "next page", "exit", 0 };
283 24c02865 2005-01-04 devnull static char *miditems[] = {
284 24c02865 2005-01-04 devnull "orig size",
285 24c02865 2005-01-04 devnull "zoom in",
286 24c02865 2005-01-04 devnull "fit window",
287 24c02865 2005-01-04 devnull "rotate 90",
288 24c02865 2005-01-04 devnull "upside down",
289 24c02865 2005-01-04 devnull "",
290 24c02865 2005-01-04 devnull "next",
291 24c02865 2005-01-04 devnull "prev",
292 24c02865 2005-01-04 devnull "zerox",
293 24c02865 2005-01-04 devnull "",
294 24c02865 2005-01-04 devnull "reverse",
295 24c02865 2005-01-04 devnull "discard",
296 24c02865 2005-01-04 devnull "write",
297 24c02865 2005-01-04 devnull "",
298 24c02865 2005-01-04 devnull "quit",
299 24c02865 2005-01-04 devnull 0
300 24c02865 2005-01-04 devnull };
301 24c02865 2005-01-04 devnull char *s;
302 24c02865 2005-01-04 devnull enum { Eplumb = 4 };
303 24c02865 2005-01-04 devnull Plumbmsg *pm;
304 24c02865 2005-01-04 devnull
305 24c02865 2005-01-04 devnull doc = dd; /* save global for menuhit */
306 24c02865 2005-01-04 devnull ul = screen->r.min;
307 24c02865 2005-01-04 devnull einit(Emouse|Ekeyboard);
308 24c02865 2005-01-04 devnull if(doc->addpage != nil)
309 24c02865 2005-01-04 devnull eplumb(Eplumb, "image");
310 24c02865 2005-01-04 devnull
311 24c02865 2005-01-04 devnull esetcursor(&reading);
312 24c02865 2005-01-04 devnull r.min = ZP;
313 24c02865 2005-01-04 devnull
314 24c02865 2005-01-04 devnull /*
315 24c02865 2005-01-04 devnull * im is a global pointer to the current image.
316 24c02865 2005-01-04 devnull * eventually, i think we will have a layer between
317 24c02865 2005-01-04 devnull * the display routines and the ps/pdf/whatever routines
318 24c02865 2005-01-04 devnull * to perhaps cache and handle images of different
319 24c02865 2005-01-04 devnull * sizes, etc.
320 24c02865 2005-01-04 devnull */
321 24c02865 2005-01-04 devnull im = 0;
322 24c02865 2005-01-04 devnull page = reverse ? doc->npage-1 : 0;
323 24c02865 2005-01-04 devnull
324 24c02865 2005-01-04 devnull if(doc->fwdonly) {
325 24c02865 2005-01-04 devnull menu.item = fwditems;
326 24c02865 2005-01-04 devnull menu.gen = 0;
327 24c02865 2005-01-04 devnull menu.lasthit = 0;
328 24c02865 2005-01-04 devnull } else {
329 24c02865 2005-01-04 devnull menu.item = 0;
330 24c02865 2005-01-04 devnull menu.gen = menugen;
331 24c02865 2005-01-04 devnull menu.lasthit = 0;
332 24c02865 2005-01-04 devnull }
333 24c02865 2005-01-04 devnull
334 24c02865 2005-01-04 devnull midmenu.item = miditems;
335 24c02865 2005-01-04 devnull midmenu.gen = 0;
336 24c02865 2005-01-04 devnull midmenu.lasthit = Next;
337 24c02865 2005-01-04 devnull
338 24c02865 2005-01-04 devnull showpage(page, &menu);
339 24c02865 2005-01-04 devnull esetcursor(nil);
340 24c02865 2005-01-04 devnull
341 24c02865 2005-01-04 devnull nxt = 0;
342 24c02865 2005-01-04 devnull for(;;) {
343 24c02865 2005-01-04 devnull /*
344 24c02865 2005-01-04 devnull * throughout, if doc->fwdonly is set, we restrict the functionality
345 24c02865 2005-01-04 devnull * a fair amount. we don't care about doc->npage anymore, and
346 24c02865 2005-01-04 devnull * all that can be done is select the next page.
347 24c02865 2005-01-04 devnull */
348 24c02865 2005-01-04 devnull switch(eread(Emouse|Ekeyboard|Eplumb, &e)){
349 24c02865 2005-01-04 devnull case Ekeyboard:
350 24c02865 2005-01-04 devnull if(e.kbdc <= 0xFF && isdigit(e.kbdc)) {
351 24c02865 2005-01-04 devnull nxt = nxt*10+e.kbdc-'0';
352 24c02865 2005-01-04 devnull break;
353 24c02865 2005-01-04 devnull } else if(e.kbdc != '\n')
354 24c02865 2005-01-04 devnull nxt = 0;
355 24c02865 2005-01-04 devnull switch(e.kbdc) {
356 24c02865 2005-01-04 devnull case 'r': /* reverse page order */
357 24c02865 2005-01-04 devnull if(doc->fwdonly)
358 24c02865 2005-01-04 devnull break;
359 24c02865 2005-01-04 devnull reverse = !reverse;
360 24c02865 2005-01-04 devnull menu.lasthit = doc->npage-1-menu.lasthit;
361 24c02865 2005-01-04 devnull
362 24c02865 2005-01-04 devnull /*
363 24c02865 2005-01-04 devnull * the theory is that if we are reversing the
364 24c02865 2005-01-04 devnull * document order and are on the first or last
365 24c02865 2005-01-04 devnull * page then we're just starting and really want
366 24c02865 2005-01-04 devnull * to view the other end. maybe the if
367 24c02865 2005-01-04 devnull * should be dropped and this should happen always.
368 24c02865 2005-01-04 devnull */
369 24c02865 2005-01-04 devnull if(page == 0 || page == doc->npage-1) {
370 24c02865 2005-01-04 devnull page = doc->npage-1-page;
371 24c02865 2005-01-04 devnull showpage(page, &menu);
372 24c02865 2005-01-04 devnull }
373 24c02865 2005-01-04 devnull break;
374 24c02865 2005-01-04 devnull case 'w': /* write bitmap of current screen */
375 24c02865 2005-01-04 devnull esetcursor(&reading);
376 24c02865 2005-01-04 devnull s = writebitmap();
377 24c02865 2005-01-04 devnull if(s)
378 24c02865 2005-01-04 devnull string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP,
379 24c02865 2005-01-04 devnull display->defaultfont, s);
380 24c02865 2005-01-04 devnull esetcursor(nil);
381 24c02865 2005-01-04 devnull flushimage(display, 1);
382 24c02865 2005-01-04 devnull break;
383 24c02865 2005-01-04 devnull case 'd': /* remove image from working set */
384 24c02865 2005-01-04 devnull if(doc->rmpage && page < doc->npage) {
385 24c02865 2005-01-04 devnull if(doc->rmpage(doc, page) >= 0) {
386 24c02865 2005-01-04 devnull if(doc->npage < 0)
387 24c02865 2005-01-04 devnull wexits(0);
388 24c02865 2005-01-04 devnull if(page >= doc->npage)
389 24c02865 2005-01-04 devnull page = doc->npage-1;
390 24c02865 2005-01-04 devnull showpage(page, &menu);
391 24c02865 2005-01-04 devnull }
392 24c02865 2005-01-04 devnull }
393 24c02865 2005-01-04 devnull break;
394 24c02865 2005-01-04 devnull case 'q':
395 24c02865 2005-01-04 devnull case 0x04: /* ctrl-d */
396 24c02865 2005-01-04 devnull wexits(0);
397 24c02865 2005-01-04 devnull case 'u':
398 24c02865 2005-01-04 devnull if(im==nil)
399 24c02865 2005-01-04 devnull break;
400 24c02865 2005-01-04 devnull esetcursor(&reading);
401 24c02865 2005-01-04 devnull rot180(im);
402 24c02865 2005-01-04 devnull esetcursor(nil);
403 17157e4a 2006-03-20 devnull angle = (angle+180) % 360;
404 24c02865 2005-01-04 devnull redraw(screen);
405 24c02865 2005-01-04 devnull flushimage(display, 1);
406 24c02865 2005-01-04 devnull break;
407 24c02865 2005-01-04 devnull case '-':
408 24c02865 2005-01-04 devnull case '\b':
409 24c02865 2005-01-04 devnull case Kleft:
410 24c02865 2005-01-04 devnull if(page > 0 && !doc->fwdonly) {
411 24c02865 2005-01-04 devnull --page;
412 24c02865 2005-01-04 devnull showpage(page, &menu);
413 24c02865 2005-01-04 devnull }
414 24c02865 2005-01-04 devnull break;
415 24c02865 2005-01-04 devnull case '\n':
416 24c02865 2005-01-04 devnull if(nxt) {
417 24c02865 2005-01-04 devnull nxt--;
418 24c02865 2005-01-04 devnull if(nxt >= 0 && nxt < doc->npage && !doc->fwdonly)
419 24c02865 2005-01-04 devnull showpage(page=nxt, &menu);
420 24c02865 2005-01-04 devnull nxt = 0;
421 24c02865 2005-01-04 devnull break;
422 24c02865 2005-01-04 devnull }
423 24c02865 2005-01-04 devnull goto Gotonext;
424 24c02865 2005-01-04 devnull case Kright:
425 24c02865 2005-01-04 devnull case ' ':
426 24c02865 2005-01-04 devnull Gotonext:
427 24c02865 2005-01-04 devnull if(doc->npage && ++page >= doc->npage && !doc->fwdonly)
428 24c02865 2005-01-04 devnull wexits(0);
429 24c02865 2005-01-04 devnull showpage(page, &menu);
430 24c02865 2005-01-04 devnull break;
431 24c02865 2005-01-04 devnull
432 24c02865 2005-01-04 devnull /*
433 24c02865 2005-01-04 devnull * The upper y coordinate of the image is at ul.y in screen->r.
434 24c02865 2005-01-04 devnull * Panning up means moving the upper left corner down. If the
435 24c02865 2005-01-04 devnull * upper left corner is currently visible, we need to go back a page.
436 24c02865 2005-01-04 devnull */
437 24c02865 2005-01-04 devnull case Kup:
438 24c02865 2005-01-04 devnull if(screen->r.min.y <= ul.y && ul.y < screen->r.max.y){
439 24c02865 2005-01-04 devnull if(page > 0 && !doc->fwdonly){
440 24c02865 2005-01-04 devnull --page;
441 24c02865 2005-01-04 devnull showbottom = 1;
442 24c02865 2005-01-04 devnull showpage(page, &menu);
443 24c02865 2005-01-04 devnull }
444 24c02865 2005-01-04 devnull } else {
445 24c02865 2005-01-04 devnull i = Dy(screen->r)/2;
446 24c02865 2005-01-04 devnull if(i > 10)
447 24c02865 2005-01-04 devnull i -= 10;
448 24c02865 2005-01-04 devnull if(i+ul.y > screen->r.min.y)
449 24c02865 2005-01-04 devnull i = screen->r.min.y - ul.y;
450 24c02865 2005-01-04 devnull translate(Pt(0, i));
451 24c02865 2005-01-04 devnull }
452 24c02865 2005-01-04 devnull break;
453 24c02865 2005-01-04 devnull
454 24c02865 2005-01-04 devnull /*
455 24c02865 2005-01-04 devnull * If the lower y coordinate is on the screen, we go to the next page.
456 24c02865 2005-01-04 devnull * The lower y coordinate is at ul.y + Dy(im->r).
457 24c02865 2005-01-04 devnull */
458 24c02865 2005-01-04 devnull case Kdown:
459 24c02865 2005-01-04 devnull i = ul.y + Dy(im->r);
460 24c02865 2005-01-04 devnull if(screen->r.min.y <= i && i <= screen->r.max.y){
461 24c02865 2005-01-04 devnull ul.y = screen->r.min.y;
462 24c02865 2005-01-04 devnull goto Gotonext;
463 24c02865 2005-01-04 devnull } else {
464 24c02865 2005-01-04 devnull i = -Dy(screen->r)/2;
465 24c02865 2005-01-04 devnull if(i < -10)
466 24c02865 2005-01-04 devnull i += 10;
467 24c02865 2005-01-04 devnull if(i+ul.y+Dy(im->r) <= screen->r.max.y)
468 24c02865 2005-01-04 devnull i = screen->r.max.y - Dy(im->r) - ul.y - 1;
469 24c02865 2005-01-04 devnull translate(Pt(0, i));
470 24c02865 2005-01-04 devnull }
471 24c02865 2005-01-04 devnull break;
472 24c02865 2005-01-04 devnull default:
473 24c02865 2005-01-04 devnull esetcursor(&query);
474 24c02865 2005-01-04 devnull sleep(1000);
475 24c02865 2005-01-04 devnull esetcursor(nil);
476 24c02865 2005-01-04 devnull break;
477 24c02865 2005-01-04 devnull }
478 24c02865 2005-01-04 devnull break;
479 24c02865 2005-01-04 devnull
480 24c02865 2005-01-04 devnull case Emouse:
481 24c02865 2005-01-04 devnull m = e.mouse;
482 24c02865 2005-01-04 devnull switch(m.buttons){
483 24c02865 2005-01-04 devnull case Left:
484 24c02865 2005-01-04 devnull oxy = m.xy;
485 24c02865 2005-01-04 devnull xy0 = oxy;
486 24c02865 2005-01-04 devnull do {
487 24c02865 2005-01-04 devnull dxy = subpt(m.xy, oxy);
488 24c02865 2005-01-04 devnull oxy = m.xy;
489 24c02865 2005-01-04 devnull translate(dxy);
490 24c02865 2005-01-04 devnull m = emouse();
491 24c02865 2005-01-04 devnull } while(m.buttons == Left);
492 24c02865 2005-01-04 devnull if(m.buttons) {
493 24c02865 2005-01-04 devnull dxy = subpt(xy0, oxy);
494 24c02865 2005-01-04 devnull translate(dxy);
495 24c02865 2005-01-04 devnull }
496 24c02865 2005-01-04 devnull break;
497 24c02865 2005-01-04 devnull
498 24c02865 2005-01-04 devnull case Middle:
499 24c02865 2005-01-04 devnull if(doc->npage == 0)
500 24c02865 2005-01-04 devnull break;
501 24c02865 2005-01-04 devnull
502 24c02865 2005-01-04 devnull n = emenuhit(Middle, &m, &midmenu);
503 24c02865 2005-01-04 devnull if(n == -1)
504 24c02865 2005-01-04 devnull break;
505 24c02865 2005-01-04 devnull switch(n){
506 24c02865 2005-01-04 devnull case Next: /* next */
507 24c02865 2005-01-04 devnull if(reverse)
508 24c02865 2005-01-04 devnull page--;
509 24c02865 2005-01-04 devnull else
510 24c02865 2005-01-04 devnull page++;
511 24c02865 2005-01-04 devnull if(page < 0) {
512 24c02865 2005-01-04 devnull if(reverse) return;
513 24c02865 2005-01-04 devnull else page = 0;
514 24c02865 2005-01-04 devnull }
515 24c02865 2005-01-04 devnull
516 24c02865 2005-01-04 devnull if((page >= doc->npage) && !doc->fwdonly)
517 24c02865 2005-01-04 devnull return;
518 24c02865 2005-01-04 devnull
519 24c02865 2005-01-04 devnull showpage(page, &menu);
520 24c02865 2005-01-04 devnull nxt = 0;
521 24c02865 2005-01-04 devnull break;
522 24c02865 2005-01-04 devnull case Prev: /* prev */
523 24c02865 2005-01-04 devnull if(reverse)
524 24c02865 2005-01-04 devnull page++;
525 24c02865 2005-01-04 devnull else
526 24c02865 2005-01-04 devnull page--;
527 24c02865 2005-01-04 devnull if(page < 0) {
528 24c02865 2005-01-04 devnull if(reverse) return;
529 24c02865 2005-01-04 devnull else page = 0;
530 24c02865 2005-01-04 devnull }
531 24c02865 2005-01-04 devnull
532 24c02865 2005-01-04 devnull if((page >= doc->npage) && !doc->fwdonly && !reverse)
533 24c02865 2005-01-04 devnull return;
534 24c02865 2005-01-04 devnull
535 24c02865 2005-01-04 devnull showpage(page, &menu);
536 24c02865 2005-01-04 devnull nxt = 0;
537 24c02865 2005-01-04 devnull break;
538 24c02865 2005-01-04 devnull case Zerox: /* prev */
539 24c02865 2005-01-04 devnull zerox();
540 24c02865 2005-01-04 devnull break;
541 24c02865 2005-01-04 devnull case Zin: /* zoom in */
542 24c02865 2005-01-04 devnull {
543 24c02865 2005-01-04 devnull double delta;
544 24c02865 2005-01-04 devnull Rectangle r;
545 24c02865 2005-01-04 devnull
546 24c02865 2005-01-04 devnull r = egetrect(Middle, &m);
547 24c02865 2005-01-04 devnull if((rectclip(&r, rectaddpt(im->r, ul)) == 0) ||
548 24c02865 2005-01-04 devnull Dx(r) == 0 || Dy(r) == 0)
549 24c02865 2005-01-04 devnull break;
550 24c02865 2005-01-04 devnull /* use the smaller side to expand */
551 24c02865 2005-01-04 devnull if(Dx(r) < Dy(r))
552 24c02865 2005-01-04 devnull delta = (double)Dx(im->r)/(double)Dx(r);
553 24c02865 2005-01-04 devnull else
554 24c02865 2005-01-04 devnull delta = (double)Dy(im->r)/(double)Dy(r);
555 24c02865 2005-01-04 devnull
556 24c02865 2005-01-04 devnull esetcursor(&reading);
557 24c02865 2005-01-04 devnull tmp = xallocimage(display,
558 24c02865 2005-01-04 devnull Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)),
559 24c02865 2005-01-04 devnull im->chan, 0, DBlack);
560 24c02865 2005-01-04 devnull if(tmp == nil) {
561 24c02865 2005-01-04 devnull fprint(2, "out of memory during zoom: %r\n");
562 24c02865 2005-01-04 devnull wexits("memory");
563 24c02865 2005-01-04 devnull }
564 24c02865 2005-01-04 devnull resample(im, tmp);
565 24c02865 2005-01-04 devnull freeimage(im);
566 24c02865 2005-01-04 devnull im = tmp;
567 24c02865 2005-01-04 devnull esetcursor(nil);
568 24c02865 2005-01-04 devnull ul = screen->r.min;
569 24c02865 2005-01-04 devnull redraw(screen);
570 24c02865 2005-01-04 devnull flushimage(display, 1);
571 24c02865 2005-01-04 devnull break;
572 24c02865 2005-01-04 devnull }
573 24c02865 2005-01-04 devnull case Fit: /* fit */
574 24c02865 2005-01-04 devnull {
575 24c02865 2005-01-04 devnull double delta;
576 24c02865 2005-01-04 devnull Rectangle r;
577 24c02865 2005-01-04 devnull
578 24c02865 2005-01-04 devnull delta = (double)Dx(screen->r)/(double)Dx(im->r);
579 24c02865 2005-01-04 devnull if((double)Dy(im->r)*delta > Dy(screen->r))
580 24c02865 2005-01-04 devnull delta = (double)Dy(screen->r)/(double)Dy(im->r);
581 24c02865 2005-01-04 devnull
582 24c02865 2005-01-04 devnull r = Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta));
583 24c02865 2005-01-04 devnull esetcursor(&reading);
584 24c02865 2005-01-04 devnull tmp = xallocimage(display, r, im->chan, 0, DBlack);
585 24c02865 2005-01-04 devnull if(tmp == nil) {
586 24c02865 2005-01-04 devnull fprint(2, "out of memory during fit: %r\n");
587 24c02865 2005-01-04 devnull wexits("memory");
588 24c02865 2005-01-04 devnull }
589 24c02865 2005-01-04 devnull resample(im, tmp);
590 24c02865 2005-01-04 devnull freeimage(im);
591 24c02865 2005-01-04 devnull im = tmp;
592 24c02865 2005-01-04 devnull esetcursor(nil);
593 24c02865 2005-01-04 devnull ul = screen->r.min;
594 24c02865 2005-01-04 devnull redraw(screen);
595 24c02865 2005-01-04 devnull flushimage(display, 1);
596 24c02865 2005-01-04 devnull break;
597 24c02865 2005-01-04 devnull }
598 24c02865 2005-01-04 devnull case Rot: /* rotate 90 */
599 24c02865 2005-01-04 devnull esetcursor(&reading);
600 24c02865 2005-01-04 devnull im = rot90(im);
601 24c02865 2005-01-04 devnull esetcursor(nil);
602 17157e4a 2006-03-20 devnull angle = (angle+90) % 360;
603 24c02865 2005-01-04 devnull redraw(screen);
604 24c02865 2005-01-04 devnull flushimage(display, 1);
605 24c02865 2005-01-04 devnull break;
606 24c02865 2005-01-04 devnull case Upside: /* upside-down */
607 24c02865 2005-01-04 devnull if(im==nil)
608 24c02865 2005-01-04 devnull break;
609 24c02865 2005-01-04 devnull esetcursor(&reading);
610 24c02865 2005-01-04 devnull rot180(im);
611 24c02865 2005-01-04 devnull esetcursor(nil);
612 17157e4a 2006-03-20 devnull angle = (angle+180) % 360;
613 24c02865 2005-01-04 devnull redraw(screen);
614 24c02865 2005-01-04 devnull flushimage(display, 1);
615 24c02865 2005-01-04 devnull break;
616 24c02865 2005-01-04 devnull case Restore: /* restore */
617 24c02865 2005-01-04 devnull showpage(page, &menu);
618 24c02865 2005-01-04 devnull break;
619 24c02865 2005-01-04 devnull case Reverse: /* reverse */
620 24c02865 2005-01-04 devnull if(doc->fwdonly)
621 24c02865 2005-01-04 devnull break;
622 24c02865 2005-01-04 devnull reverse = !reverse;
623 24c02865 2005-01-04 devnull menu.lasthit = doc->npage-1-menu.lasthit;
624 24c02865 2005-01-04 devnull
625 24c02865 2005-01-04 devnull if(page == 0 || page == doc->npage-1) {
626 24c02865 2005-01-04 devnull page = doc->npage-1-page;
627 24c02865 2005-01-04 devnull showpage(page, &menu);
628 24c02865 2005-01-04 devnull }
629 24c02865 2005-01-04 devnull break;
630 24c02865 2005-01-04 devnull case Write: /* write */
631 24c02865 2005-01-04 devnull esetcursor(&reading);
632 24c02865 2005-01-04 devnull s = writebitmap();
633 24c02865 2005-01-04 devnull if(s)
634 24c02865 2005-01-04 devnull string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP,
635 24c02865 2005-01-04 devnull display->defaultfont, s);
636 24c02865 2005-01-04 devnull esetcursor(nil);
637 24c02865 2005-01-04 devnull flushimage(display, 1);
638 24c02865 2005-01-04 devnull break;
639 24c02865 2005-01-04 devnull case Del: /* delete */
640 24c02865 2005-01-04 devnull if(doc->rmpage && page < doc->npage) {
641 24c02865 2005-01-04 devnull if(doc->rmpage(doc, page) >= 0) {
642 24c02865 2005-01-04 devnull if(doc->npage < 0)
643 24c02865 2005-01-04 devnull wexits(0);
644 24c02865 2005-01-04 devnull if(page >= doc->npage)
645 24c02865 2005-01-04 devnull page = doc->npage-1;
646 24c02865 2005-01-04 devnull showpage(page, &menu);
647 24c02865 2005-01-04 devnull }
648 24c02865 2005-01-04 devnull }
649 24c02865 2005-01-04 devnull break;
650 24c02865 2005-01-04 devnull case Exit: /* exit */
651 24c02865 2005-01-04 devnull return;
652 24c02865 2005-01-04 devnull case Empty1:
653 24c02865 2005-01-04 devnull case Empty2:
654 24c02865 2005-01-04 devnull case Empty3:
655 24c02865 2005-01-04 devnull break;
656 24c02865 2005-01-04 devnull
657 24c02865 2005-01-04 devnull };
658 24c02865 2005-01-04 devnull
659 24c02865 2005-01-04 devnull
660 24c02865 2005-01-04 devnull
661 24c02865 2005-01-04 devnull case Right:
662 24c02865 2005-01-04 devnull if(doc->npage == 0)
663 24c02865 2005-01-04 devnull break;
664 24c02865 2005-01-04 devnull
665 24c02865 2005-01-04 devnull oldpage = page;
666 24c02865 2005-01-04 devnull n = emenuhit(RMenu, &m, &menu);
667 24c02865 2005-01-04 devnull if(n == -1)
668 24c02865 2005-01-04 devnull break;
669 24c02865 2005-01-04 devnull
670 24c02865 2005-01-04 devnull if(doc->fwdonly) {
671 24c02865 2005-01-04 devnull switch(n){
672 24c02865 2005-01-04 devnull case 0: /* this page */
673 24c02865 2005-01-04 devnull break;
674 24c02865 2005-01-04 devnull case 1: /* next page */
675 24c02865 2005-01-04 devnull showpage(++page, &menu);
676 24c02865 2005-01-04 devnull break;
677 24c02865 2005-01-04 devnull case 2: /* exit */
678 24c02865 2005-01-04 devnull return;
679 24c02865 2005-01-04 devnull }
680 24c02865 2005-01-04 devnull break;
681 24c02865 2005-01-04 devnull }
682 24c02865 2005-01-04 devnull
683 24c02865 2005-01-04 devnull if(n == doc->npage)
684 24c02865 2005-01-04 devnull return;
685 24c02865 2005-01-04 devnull else
686 24c02865 2005-01-04 devnull page = reverse ? doc->npage-1-n : n;
687 24c02865 2005-01-04 devnull
688 24c02865 2005-01-04 devnull if(oldpage != page)
689 24c02865 2005-01-04 devnull showpage(page, &menu);
690 24c02865 2005-01-04 devnull nxt = 0;
691 24c02865 2005-01-04 devnull break;
692 24c02865 2005-01-04 devnull }
693 24c02865 2005-01-04 devnull break;
694 24c02865 2005-01-04 devnull
695 24c02865 2005-01-04 devnull case Eplumb:
696 24c02865 2005-01-04 devnull pm = e.v;
697 24c02865 2005-01-04 devnull if(pm->ndata <= 0){
698 24c02865 2005-01-04 devnull plumbfree(pm);
699 24c02865 2005-01-04 devnull break;
700 24c02865 2005-01-04 devnull }
701 24c02865 2005-01-04 devnull if(showdata(pm)) {
702 24c02865 2005-01-04 devnull s = estrdup("/tmp/pageplumbXXXXXXX");
703 24c02865 2005-01-04 devnull fd = opentemp(s);
704 24c02865 2005-01-04 devnull write(fd, pm->data, pm->ndata);
705 24c02865 2005-01-04 devnull /* lose fd reference on purpose; the file is open ORCLOSE */
706 24c02865 2005-01-04 devnull } else if(pm->data[0] == '/') {
707 24c02865 2005-01-04 devnull s = estrdup(pm->data);
708 24c02865 2005-01-04 devnull } else {
709 24c02865 2005-01-04 devnull s = emalloc(strlen(pm->wdir)+1+pm->ndata+1);
710 24c02865 2005-01-04 devnull sprint(s, "%s/%s", pm->wdir, pm->data);
711 24c02865 2005-01-04 devnull cleanname(s);
712 24c02865 2005-01-04 devnull }
713 24c02865 2005-01-04 devnull if((i = doc->addpage(doc, s)) >= 0) {
714 24c02865 2005-01-04 devnull page = i;
715 24c02865 2005-01-04 devnull unhide();
716 24c02865 2005-01-04 devnull showpage(page, &menu);
717 24c02865 2005-01-04 devnull }
718 24c02865 2005-01-04 devnull free(s);
719 24c02865 2005-01-04 devnull plumbfree(pm);
720 24c02865 2005-01-04 devnull break;
721 24c02865 2005-01-04 devnull }
722 24c02865 2005-01-04 devnull }
723 24c02865 2005-01-04 devnull }
724 24c02865 2005-01-04 devnull
725 24c02865 2005-01-04 devnull Image *gray;
726 24c02865 2005-01-04 devnull
727 24c02865 2005-01-04 devnull /*
728 24c02865 2005-01-04 devnull * A draw operation that touches only the area contained in bot but not in top.
729 24c02865 2005-01-04 devnull * mp and sp get aligned with bot.min.
730 24c02865 2005-01-04 devnull */
731 24c02865 2005-01-04 devnull static void
732 24c02865 2005-01-04 devnull gendrawdiff(Image *dst, Rectangle bot, Rectangle top,
733 24c02865 2005-01-04 devnull Image *src, Point sp, Image *mask, Point mp, int op)
734 24c02865 2005-01-04 devnull {
735 24c02865 2005-01-04 devnull Rectangle r;
736 24c02865 2005-01-04 devnull Point origin;
737 24c02865 2005-01-04 devnull Point delta;
738 24c02865 2005-01-04 devnull
739 24c02865 2005-01-04 devnull USED(op);
740 24c02865 2005-01-04 devnull
741 24c02865 2005-01-04 devnull if(Dx(bot)*Dy(bot) == 0)
742 24c02865 2005-01-04 devnull return;
743 24c02865 2005-01-04 devnull
744 24c02865 2005-01-04 devnull /* no points in bot - top */
745 24c02865 2005-01-04 devnull if(rectinrect(bot, top))
746 24c02865 2005-01-04 devnull return;
747 24c02865 2005-01-04 devnull
748 24c02865 2005-01-04 devnull /* bot - top ≡ bot */
749 24c02865 2005-01-04 devnull if(Dx(top)*Dy(top)==0 || rectXrect(bot, top)==0){
750 24c02865 2005-01-04 devnull gendrawop(dst, bot, src, sp, mask, mp, op);
751 24c02865 2005-01-04 devnull return;
752 24c02865 2005-01-04 devnull }
753 24c02865 2005-01-04 devnull
754 24c02865 2005-01-04 devnull origin = bot.min;
755 24c02865 2005-01-04 devnull /* split bot into rectangles that don't intersect top */
756 24c02865 2005-01-04 devnull /* left side */
757 24c02865 2005-01-04 devnull if(bot.min.x < top.min.x){
758 24c02865 2005-01-04 devnull r = Rect(bot.min.x, bot.min.y, top.min.x, bot.max.y);
759 24c02865 2005-01-04 devnull delta = subpt(r.min, origin);
760 24c02865 2005-01-04 devnull gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
761 24c02865 2005-01-04 devnull bot.min.x = top.min.x;
762 24c02865 2005-01-04 devnull }
763 24c02865 2005-01-04 devnull
764 24c02865 2005-01-04 devnull /* right side */
765 24c02865 2005-01-04 devnull if(bot.max.x > top.max.x){
766 24c02865 2005-01-04 devnull r = Rect(top.max.x, bot.min.y, bot.max.x, bot.max.y);
767 24c02865 2005-01-04 devnull delta = subpt(r.min, origin);
768 24c02865 2005-01-04 devnull gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
769 24c02865 2005-01-04 devnull bot.max.x = top.max.x;
770 24c02865 2005-01-04 devnull }
771 24c02865 2005-01-04 devnull
772 24c02865 2005-01-04 devnull /* top */
773 24c02865 2005-01-04 devnull if(bot.min.y < top.min.y){
774 24c02865 2005-01-04 devnull r = Rect(bot.min.x, bot.min.y, bot.max.x, top.min.y);
775 24c02865 2005-01-04 devnull delta = subpt(r.min, origin);
776 24c02865 2005-01-04 devnull gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
777 24c02865 2005-01-04 devnull bot.min.y = top.min.y;
778 24c02865 2005-01-04 devnull }
779 24c02865 2005-01-04 devnull
780 24c02865 2005-01-04 devnull /* bottom */
781 24c02865 2005-01-04 devnull if(bot.max.y > top.max.y){
782 24c02865 2005-01-04 devnull r = Rect(bot.min.x, top.max.y, bot.max.x, bot.max.y);
783 24c02865 2005-01-04 devnull delta = subpt(r.min, origin);
784 24c02865 2005-01-04 devnull gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
785 24c02865 2005-01-04 devnull bot.max.y = top.max.y;
786 24c02865 2005-01-04 devnull }
787 24c02865 2005-01-04 devnull }
788 24c02865 2005-01-04 devnull
789 24c02865 2005-01-04 devnull static void
790 24c02865 2005-01-04 devnull drawdiff(Image *dst, Rectangle bot, Rectangle top, Image *src, Image *mask, Point p, int op)
791 24c02865 2005-01-04 devnull {
792 24c02865 2005-01-04 devnull gendrawdiff(dst, bot, top, src, p, mask, p, op);
793 24c02865 2005-01-04 devnull }
794 24c02865 2005-01-04 devnull
795 24c02865 2005-01-04 devnull /*
796 24c02865 2005-01-04 devnull * Translate the image in the window by delta.
797 24c02865 2005-01-04 devnull */
798 24c02865 2005-01-04 devnull static void
799 24c02865 2005-01-04 devnull translate(Point delta)
800 24c02865 2005-01-04 devnull {
801 24c02865 2005-01-04 devnull Point u;
802 24c02865 2005-01-04 devnull Rectangle r, or;
803 24c02865 2005-01-04 devnull
804 24c02865 2005-01-04 devnull if(im == nil)
805 24c02865 2005-01-04 devnull return;
806 24c02865 2005-01-04 devnull
807 24c02865 2005-01-04 devnull u = pclip(addpt(ul, delta), ulrange);
808 24c02865 2005-01-04 devnull delta = subpt(u, ul);
809 24c02865 2005-01-04 devnull if(delta.x == 0 && delta.y == 0)
810 24c02865 2005-01-04 devnull return;
811 24c02865 2005-01-04 devnull
812 24c02865 2005-01-04 devnull /*
813 24c02865 2005-01-04 devnull * The upper left corner of the image is currently at ul.
814 24c02865 2005-01-04 devnull * We want to move it to u.
815 24c02865 2005-01-04 devnull */
816 24c02865 2005-01-04 devnull or = rectaddpt(Rpt(ZP, Pt(Dx(im->r), Dy(im->r))), ul);
817 24c02865 2005-01-04 devnull r = rectaddpt(or, delta);
818 24c02865 2005-01-04 devnull
819 24c02865 2005-01-04 devnull drawop(screen, r, screen, nil, ul, S);
820 24c02865 2005-01-04 devnull ul = u;
821 24c02865 2005-01-04 devnull
822 24c02865 2005-01-04 devnull /* fill in gray where image used to be but isn't. */
823 24c02865 2005-01-04 devnull drawdiff(screen, insetrect(or, -2), insetrect(r, -2), gray, nil, ZP, S);
824 24c02865 2005-01-04 devnull
825 24c02865 2005-01-04 devnull /* fill in black border */
826 24c02865 2005-01-04 devnull drawdiff(screen, insetrect(r, -2), r, display->black, nil, ZP, S);
827 24c02865 2005-01-04 devnull
828 24c02865 2005-01-04 devnull /* fill in image where it used to be off the screen. */
829 24c02865 2005-01-04 devnull if(rectclip(&or, screen->r))
830 24c02865 2005-01-04 devnull drawdiff(screen, r, rectaddpt(or, delta), im, nil, im->r.min, S);
831 24c02865 2005-01-04 devnull else
832 24c02865 2005-01-04 devnull drawop(screen, r, im, nil, im->r.min, S);
833 24c02865 2005-01-04 devnull flushimage(display, 1);
834 24c02865 2005-01-04 devnull }
835 24c02865 2005-01-04 devnull
836 24c02865 2005-01-04 devnull void
837 24c02865 2005-01-04 devnull redraw(Image *screen)
838 24c02865 2005-01-04 devnull {
839 24c02865 2005-01-04 devnull Rectangle r;
840 24c02865 2005-01-04 devnull
841 24c02865 2005-01-04 devnull if(im == nil)
842 24c02865 2005-01-04 devnull return;
843 24c02865 2005-01-04 devnull
844 24c02865 2005-01-04 devnull ulrange.max = screen->r.max;
845 24c02865 2005-01-04 devnull ulrange.min = subpt(screen->r.min, Pt(Dx(im->r), Dy(im->r)));
846 24c02865 2005-01-04 devnull
847 24c02865 2005-01-04 devnull ul = pclip(ul, ulrange);
848 24c02865 2005-01-04 devnull drawop(screen, screen->r, im, nil, subpt(im->r.min, subpt(ul, screen->r.min)), S);
849 24c02865 2005-01-04 devnull
850 24c02865 2005-01-04 devnull if(im->repl)
851 24c02865 2005-01-04 devnull return;
852 24c02865 2005-01-04 devnull
853 24c02865 2005-01-04 devnull /* fill in any outer edges */
854 24c02865 2005-01-04 devnull /* black border */
855 24c02865 2005-01-04 devnull r = rectaddpt(im->r, subpt(ul, im->r.min));
856 24c02865 2005-01-04 devnull border(screen, r, -2, display->black, ZP);
857 24c02865 2005-01-04 devnull r.min = subpt(r.min, Pt(2,2));
858 24c02865 2005-01-04 devnull r.max = addpt(r.max, Pt(2,2));
859 24c02865 2005-01-04 devnull
860 24c02865 2005-01-04 devnull /* gray for the rest */
861 24c02865 2005-01-04 devnull if(gray == nil) {
862 24c02865 2005-01-04 devnull gray = xallocimage(display, Rect(0,0,1,1), RGB24, 1, 0x888888FF);
863 24c02865 2005-01-04 devnull if(gray == nil) {
864 24c02865 2005-01-04 devnull fprint(2, "g out of memory: %r\n");
865 24c02865 2005-01-04 devnull wexits("mem");
866 24c02865 2005-01-04 devnull }
867 24c02865 2005-01-04 devnull }
868 24c02865 2005-01-04 devnull border(screen, r, -4000, gray, ZP);
869 cbeb0b26 2006-04-01 devnull /* flushimage(display, 0); */
870 24c02865 2005-01-04 devnull }
871 24c02865 2005-01-04 devnull
872 24c02865 2005-01-04 devnull void
873 24c02865 2005-01-04 devnull eresized(int new)
874 24c02865 2005-01-04 devnull {
875 24c02865 2005-01-04 devnull Rectangle r;
876 24c02865 2005-01-04 devnull r = screen->r;
877 24c02865 2005-01-04 devnull if(new && getwindow(display, Refnone) < 0)
878 24c02865 2005-01-04 devnull fprint(2,"can't reattach to window");
879 24c02865 2005-01-04 devnull ul = addpt(ul, subpt(screen->r.min, r.min));
880 24c02865 2005-01-04 devnull redraw(screen);
881 24c02865 2005-01-04 devnull }
882 24c02865 2005-01-04 devnull
883 24c02865 2005-01-04 devnull /* clip p to be in r */
884 24c02865 2005-01-04 devnull Point
885 24c02865 2005-01-04 devnull pclip(Point p, Rectangle r)
886 24c02865 2005-01-04 devnull {
887 24c02865 2005-01-04 devnull if(p.x < r.min.x)
888 24c02865 2005-01-04 devnull p.x = r.min.x;
889 24c02865 2005-01-04 devnull else if(p.x >= r.max.x)
890 24c02865 2005-01-04 devnull p.x = r.max.x-1;
891 24c02865 2005-01-04 devnull
892 24c02865 2005-01-04 devnull if(p.y < r.min.y)
893 24c02865 2005-01-04 devnull p.y = r.min.y;
894 24c02865 2005-01-04 devnull else if(p.y >= r.max.y)
895 24c02865 2005-01-04 devnull p.y = r.max.y-1;
896 24c02865 2005-01-04 devnull
897 24c02865 2005-01-04 devnull return p;
898 24c02865 2005-01-04 devnull }
899 24c02865 2005-01-04 devnull
900 24c02865 2005-01-04 devnull /*
901 24c02865 2005-01-04 devnull * resize is perhaps a misnomer.
902 24c02865 2005-01-04 devnull * this really just grows the window to be at least dx across
903 24c02865 2005-01-04 devnull * and dy high. if the window hits the bottom or right edge,
904 24c02865 2005-01-04 devnull * it is backed up until it hits the top or left edge.
905 24c02865 2005-01-04 devnull */
906 24c02865 2005-01-04 devnull void
907 24c02865 2005-01-04 devnull resize(int dx, int dy)
908 24c02865 2005-01-04 devnull {
909 24c02865 2005-01-04 devnull static Rectangle sr;
910 24c02865 2005-01-04 devnull Rectangle r, or;
911 24c02865 2005-01-04 devnull
912 24c02865 2005-01-04 devnull dx += 2*Borderwidth;
913 24c02865 2005-01-04 devnull dy += 2*Borderwidth;
914 24c02865 2005-01-04 devnull if(wctlfd < 0){
915 24c02865 2005-01-04 devnull wctlfd = open("/dev/wctl", OWRITE);
916 24c02865 2005-01-04 devnull if(wctlfd < 0)
917 24c02865 2005-01-04 devnull return;
918 24c02865 2005-01-04 devnull }
919 24c02865 2005-01-04 devnull
920 24c02865 2005-01-04 devnull r = insetrect(screen->r, -Borderwidth);
921 24c02865 2005-01-04 devnull if(Dx(r) >= dx && Dy(r) >= dy)
922 24c02865 2005-01-04 devnull return;
923 24c02865 2005-01-04 devnull
924 24c02865 2005-01-04 devnull if(Dx(sr)*Dy(sr) == 0)
925 24c02865 2005-01-04 devnull sr = screenrect();
926 24c02865 2005-01-04 devnull
927 24c02865 2005-01-04 devnull or = r;
928 24c02865 2005-01-04 devnull
929 24c02865 2005-01-04 devnull r.max.x = max(r.min.x+dx, r.max.x);
930 24c02865 2005-01-04 devnull r.max.y = max(r.min.y+dy, r.max.y);
931 24c02865 2005-01-04 devnull if(r.max.x > sr.max.x){
932 24c02865 2005-01-04 devnull if(Dx(r) > Dx(sr)){
933 24c02865 2005-01-04 devnull r.min.x = 0;
934 24c02865 2005-01-04 devnull r.max.x = sr.max.x;
935 24c02865 2005-01-04 devnull }else
936 24c02865 2005-01-04 devnull r = rectaddpt(r, Pt(sr.max.x-r.max.x, 0));
937 24c02865 2005-01-04 devnull }
938 24c02865 2005-01-04 devnull if(r.max.y > sr.max.y){
939 24c02865 2005-01-04 devnull if(Dy(r) > Dy(sr)){
940 24c02865 2005-01-04 devnull r.min.y = 0;
941 24c02865 2005-01-04 devnull r.max.y = sr.max.y;
942 24c02865 2005-01-04 devnull }else
943 24c02865 2005-01-04 devnull r = rectaddpt(r, Pt(0, sr.max.y-r.max.y));
944 24c02865 2005-01-04 devnull }
945 24c02865 2005-01-04 devnull
946 24c02865 2005-01-04 devnull /*
947 24c02865 2005-01-04 devnull * Sometimes we can't actually grow the window big enough,
948 24c02865 2005-01-04 devnull * and resizing it to the same shape makes it flash.
949 24c02865 2005-01-04 devnull */
950 24c02865 2005-01-04 devnull if(Dx(r) == Dx(or) && Dy(r) == Dy(or))
951 24c02865 2005-01-04 devnull return;
952 24c02865 2005-01-04 devnull
953 24c02865 2005-01-04 devnull fprint(wctlfd, "resize -minx %d -miny %d -maxx %d -maxy %d\n",
954 24c02865 2005-01-04 devnull r.min.x, r.min.y, r.max.x, r.max.y);
955 24c02865 2005-01-04 devnull }
956 24c02865 2005-01-04 devnull
957 24c02865 2005-01-04 devnull /*
958 24c02865 2005-01-04 devnull * If we allocimage after a resize but before flushing the draw buffer,
959 24c02865 2005-01-04 devnull * we won't have seen the reshape event, and we won't have called
960 24c02865 2005-01-04 devnull * getwindow, and allocimage will fail. So we flushimage before every alloc.
961 24c02865 2005-01-04 devnull */
962 24c02865 2005-01-04 devnull Image*
963 24c02865 2005-01-04 devnull xallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val)
964 24c02865 2005-01-04 devnull {
965 24c02865 2005-01-04 devnull flushimage(display, 0);
966 24c02865 2005-01-04 devnull return allocimage(d, r, chan, repl, val);
967 24c02865 2005-01-04 devnull }
968 24c02865 2005-01-04 devnull
969 24c02865 2005-01-04 devnull /* all code below this line should be in the library, but is stolen from colors instead */
970 24c02865 2005-01-04 devnull static char*
971 24c02865 2005-01-04 devnull rdenv(char *name)
972 24c02865 2005-01-04 devnull {
973 24c02865 2005-01-04 devnull char *v;
974 24c02865 2005-01-04 devnull int fd, size;
975 24c02865 2005-01-04 devnull
976 24c02865 2005-01-04 devnull fd = open(name, OREAD);
977 24c02865 2005-01-04 devnull if(fd < 0)
978 24c02865 2005-01-04 devnull return 0;
979 24c02865 2005-01-04 devnull size = seek(fd, 0, 2);
980 24c02865 2005-01-04 devnull v = malloc(size+1);
981 24c02865 2005-01-04 devnull if(v == 0){
982 24c02865 2005-01-04 devnull fprint(2, "page: can't malloc: %r\n");
983 24c02865 2005-01-04 devnull wexits("no mem");
984 24c02865 2005-01-04 devnull }
985 24c02865 2005-01-04 devnull seek(fd, 0, 0);
986 24c02865 2005-01-04 devnull read(fd, v, size);
987 24c02865 2005-01-04 devnull v[size] = 0;
988 24c02865 2005-01-04 devnull close(fd);
989 24c02865 2005-01-04 devnull return v;
990 17157e4a 2006-03-20 devnull }
991 17157e4a 2006-03-20 devnull
992 17157e4a 2006-03-20 devnull void
993 17157e4a 2006-03-20 devnull newwin(void)
994 17157e4a 2006-03-20 devnull {
995 17157e4a 2006-03-20 devnull char *srv, *mntsrv;
996 17157e4a 2006-03-20 devnull char spec[100];
997 17157e4a 2006-03-20 devnull int srvfd, cons, pid;
998 17157e4a 2006-03-20 devnull
999 17157e4a 2006-03-20 devnull switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){
1000 17157e4a 2006-03-20 devnull case -1:
1001 17157e4a 2006-03-20 devnull fprint(2, "page: can't fork: %r\n");
1002 17157e4a 2006-03-20 devnull wexits("no fork");
1003 17157e4a 2006-03-20 devnull case 0:
1004 17157e4a 2006-03-20 devnull break;
1005 17157e4a 2006-03-20 devnull default:
1006 17157e4a 2006-03-20 devnull wexits(0);
1007 17157e4a 2006-03-20 devnull }
1008 17157e4a 2006-03-20 devnull
1009 17157e4a 2006-03-20 devnull srv = rdenv("/env/wsys");
1010 17157e4a 2006-03-20 devnull if(srv == 0){
1011 17157e4a 2006-03-20 devnull mntsrv = rdenv("/mnt/term/env/wsys");
1012 17157e4a 2006-03-20 devnull if(mntsrv == 0){
1013 17157e4a 2006-03-20 devnull fprint(2, "page: can't find $wsys\n");
1014 17157e4a 2006-03-20 devnull wexits("srv");
1015 17157e4a 2006-03-20 devnull }
1016 17157e4a 2006-03-20 devnull srv = malloc(strlen(mntsrv)+10);
1017 17157e4a 2006-03-20 devnull sprint(srv, "/mnt/term%s", mntsrv);
1018 17157e4a 2006-03-20 devnull free(mntsrv);
1019 17157e4a 2006-03-20 devnull pid = 0; /* can't send notes to remote processes! */
1020 17157e4a 2006-03-20 devnull }else
1021 17157e4a 2006-03-20 devnull pid = getpid();
1022 17157e4a 2006-03-20 devnull srvfd = open(srv, ORDWR);
1023 17157e4a 2006-03-20 devnull free(srv);
1024 17157e4a 2006-03-20 devnull if(srvfd == -1){
1025 17157e4a 2006-03-20 devnull fprint(2, "page: can't open %s: %r\n", srv);
1026 17157e4a 2006-03-20 devnull wexits("no srv");
1027 17157e4a 2006-03-20 devnull }
1028 17157e4a 2006-03-20 devnull sprint(spec, "new -pid %d", pid);
1029 17157e4a 2006-03-20 devnull if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){
1030 17157e4a 2006-03-20 devnull fprint(2, "page: can't mount /mnt/wsys: %r (spec=%s)\n", spec);
1031 17157e4a 2006-03-20 devnull wexits("no mount");
1032 17157e4a 2006-03-20 devnull }
1033 17157e4a 2006-03-20 devnull close(srvfd);
1034 17157e4a 2006-03-20 devnull unmount("/mnt/acme", "/dev");
1035 17157e4a 2006-03-20 devnull bind("/mnt/wsys", "/dev", MBEFORE);
1036 17157e4a 2006-03-20 devnull cons = open("/dev/cons", OREAD);
1037 17157e4a 2006-03-20 devnull if(cons==-1){
1038 17157e4a 2006-03-20 devnull NoCons:
1039 17157e4a 2006-03-20 devnull fprint(2, "page: can't open /dev/cons: %r");
1040 17157e4a 2006-03-20 devnull wexits("no cons");
1041 17157e4a 2006-03-20 devnull }
1042 17157e4a 2006-03-20 devnull dup(cons, 0);
1043 17157e4a 2006-03-20 devnull close(cons);
1044 17157e4a 2006-03-20 devnull cons = open("/dev/cons", OWRITE);
1045 17157e4a 2006-03-20 devnull if(cons==-1)
1046 17157e4a 2006-03-20 devnull goto NoCons;
1047 17157e4a 2006-03-20 devnull dup(cons, 1);
1048 17157e4a 2006-03-20 devnull dup(cons, 2);
1049 17157e4a 2006-03-20 devnull close(cons);
1050 cbeb0b26 2006-04-01 devnull /* wctlfd = open("/dev/wctl", OWRITE); */
1051 24c02865 2005-01-04 devnull }
1052 24c02865 2005-01-04 devnull
1053 24c02865 2005-01-04 devnull Rectangle
1054 24c02865 2005-01-04 devnull screenrect(void)
1055 24c02865 2005-01-04 devnull {
1056 24c02865 2005-01-04 devnull int fd;
1057 24c02865 2005-01-04 devnull char buf[12*5];
1058 24c02865 2005-01-04 devnull
1059 24c02865 2005-01-04 devnull fd = open("/dev/screen", OREAD);
1060 24c02865 2005-01-04 devnull if(fd == -1)
1061 24c02865 2005-01-04 devnull fd=open("/mnt/term/dev/screen", OREAD);
1062 24c02865 2005-01-04 devnull if(fd == -1){
1063 24c02865 2005-01-04 devnull fprint(2, "page: can't open /dev/screen: %r\n");
1064 24c02865 2005-01-04 devnull wexits("window read");
1065 24c02865 2005-01-04 devnull }
1066 24c02865 2005-01-04 devnull if(read(fd, buf, sizeof buf) != sizeof buf){
1067 24c02865 2005-01-04 devnull fprint(2, "page: can't read /dev/screen: %r\n");
1068 24c02865 2005-01-04 devnull wexits("screen read");
1069 24c02865 2005-01-04 devnull }
1070 24c02865 2005-01-04 devnull close(fd);
1071 24c02865 2005-01-04 devnull return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));
1072 24c02865 2005-01-04 devnull }
1073 24c02865 2005-01-04 devnull
1074 24c02865 2005-01-04 devnull void
1075 24c02865 2005-01-04 devnull zerox(void)
1076 24c02865 2005-01-04 devnull {
1077 24c02865 2005-01-04 devnull int pfd[2];
1078 24c02865 2005-01-04 devnull
1079 24c02865 2005-01-04 devnull pipe(pfd);
1080 24c02865 2005-01-04 devnull switch(rfork(RFFDG|RFPROC)) {
1081 24c02865 2005-01-04 devnull case -1:
1082 24c02865 2005-01-04 devnull wexits("cannot fork in zerox: %r");
1083 24c02865 2005-01-04 devnull case 0:
1084 24c02865 2005-01-04 devnull dup(pfd[1], 0);
1085 24c02865 2005-01-04 devnull close(pfd[0]);
1086 17157e4a 2006-03-20 devnull execl("/bin/page", "page", "-w", nil);
1087 24c02865 2005-01-04 devnull wexits("cannot exec in zerox: %r\n");
1088 24c02865 2005-01-04 devnull default:
1089 24c02865 2005-01-04 devnull close(pfd[1]);
1090 24c02865 2005-01-04 devnull writeimage(pfd[0], im, 0);
1091 24c02865 2005-01-04 devnull close(pfd[0]);
1092 24c02865 2005-01-04 devnull break;
1093 24c02865 2005-01-04 devnull }
1094 24c02865 2005-01-04 devnull }