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