2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2007-2008 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <X11/Xutil.h>
28 #include <X11/Xosdefs.h>
29 #include <X11/Xproto.h>
30 #include <X11/keysym.h>
31 #include <X11/Xatom.h>
34 #include <X11/extensions/Xinerama.h>
41 #if defined(__alpha__) && defined(__GNUC__) && ((__GNUC__ == 2) && (__GNUC_MINOR__ < 96)) /* gets rid of some misalignment in GCC */
45 #define EDOX_DEFAULT_W 512
46 #define EDOX_DEFAULT_H 400
51 Window win_main, win_title, win_exit, win_next, win_prev, win_text,
55 Imlib_Image im_prev1, im_prev2;
56 Imlib_Image im_next1, im_next2;
57 Imlib_Image im_exit1, im_exit2;
59 static const char doxdir[] = ENLIGHTENMENT_ROOT "/E-docs";
62 static Atom ATOM_WM_DELETE_WINDOW = None;
63 static Atom ATOM_WM_PROTOCOLS = None;
66 FindRootWindow(Display * dpy)
68 Window win1, win2, win3, root_win;
72 unsigned long bytes_after, num_ret;
73 unsigned char *retval;
75 root_win = DefaultRootWindow(dpy);
77 str = getenv("ENL_WM_ROOT");
80 win1 = strtoul(str, NULL, 0);
82 a = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", True);
84 XGetWindowProperty(dpy, win1, a, 0, 1, False, XA_WINDOW, &at,
85 &format_ret, &num_ret, &bytes_after, &retval);
88 win2 = *((Window *) retval);
91 XGetWindowProperty(dpy, win2, a, 0, 1, False, XA_WINDOW, &at,
92 &format_ret, &num_ret, &bytes_after, &retval);
95 win3 = *((Window *) retval);
111 int x_return, y_return;
112 unsigned int border_width_return;
114 VRoot.scr = DefaultScreen(disp);
115 VRoot.win = FindRootWindow(disp);
116 XGetGeometry(disp, VRoot.win, &root_return, &x_return, &y_return,
117 &VRoot.w, &VRoot.h, &border_width_return, &VRoot.depth);
118 VRoot.vis = DefaultVisual(disp, VRoot.scr);
119 VRoot.depth = DefaultDepth(disp, VRoot.scr);
120 VRoot.cmap = DefaultColormap(disp, VRoot.scr);
122 imlib_set_color_usage(128);
124 imlib_context_set_display(disp);
125 imlib_context_set_visual(VRoot.vis);
126 imlib_context_set_colormap(VRoot.cmap);
127 imlib_context_set_dither(1);
128 imlib_context_set_dither_mask(0);
132 CreateWindow(Window parent, int x, int y, int ww, int hh)
135 XSetWindowAttributes attr;
138 attr.backing_store = NotUseful;
139 attr.override_redirect = False;
140 attr.colormap = VRoot.cmap;
141 attr.border_pixel = 0;
142 attr.background_pixel = 0;
143 attr.save_under = False;
144 win = XCreateWindow(disp, parent, x, y, ww, hh, 0, VRoot.depth,
145 InputOutput, VRoot.vis,
146 CWOverrideRedirect | CWSaveUnder | CWBackingStore |
147 CWColormap | CWBackPixel | CWBorderPixel, &attr);
148 XSetWindowBackground(disp, win, 0);
149 XStoreName(disp, win, "DOX: Enlightenment Document Viewer");
150 hnt.flags = USPosition | USSize | PPosition | PSize | PMinSize | PMaxSize;
159 XSetWMNormalHints(disp, win, &hnt);
161 ATOM_WM_PROTOCOLS = XInternAtom(disp, "WM_PROTOCOLS", False);
162 ATOM_WM_DELETE_WINDOW = XInternAtom(disp, "WM_DELETE_WINDOW", False);
163 XSetWMProtocols(disp, win, &ATOM_WM_DELETE_WINDOW, 1);
169 ImageLoad(const char *dir, const char *file)
173 Esnprintf(tmp, sizeof(tmp), "%s/%s", dir, file);
177 return imlib_load_image(tmp);
181 ImageLoadDox(const char *file)
183 return ImageLoad(doxdir, file);
187 ImageLoadDoc(const char *file)
191 im = ImageLoad(docdir, file);
195 im = ImageLoadDox(file);
201 ApplyImage1(Window win, Imlib_Image im)
203 Pixmap pmap = 0, mask = 0;
205 imlib_context_set_image(im);
206 imlib_context_set_drawable(win);
207 imlib_render_pixmaps_for_whole_image(&pmap, &mask);
208 XSetWindowBackgroundPixmap(disp, win, pmap);
209 imlib_free_pixmap_and_mask(pmap);
213 ApplyImage2(Window win, Imlib_Image im)
215 imlib_context_set_image(im);
216 imlib_context_set_drawable(win);
217 imlib_render_image_on_drawable(0, 0);
221 LoadFile(const char *file, const char *docfile)
226 f = fopen(file, "r");
235 printf("Edoc_dir %s does not contain a %s file\n", docdir,
245 #define ApplyImage3(win, im) \
246 XClearWindow(disp, win)
260 XSetWindowBackgroundPixmap(disp, win_text, draw); \
261 XClearWindow(disp, win_text); \
267 int up_lut[16] = { 0, 8, 4, 12, 2, 6, 10, 14, \
268 3, 11, 1, 9, 7, 13, 5, 15}; \
269 XSetWindowBackgroundPixmap(disp, win_text, draw); \
270 for (up_j = 0; up_j < 16; up_j++) \
272 for (up_i = 0; up_i < h; up_i += 16) \
274 XClearArea(disp, win_text, 0, up_i + up_lut[up_j], w, 1, False); \
276 XSync(disp, False); \
281 main(int argc, char **argv)
283 int pagenum, prev_pagenum;
284 int i, w, h, t, x, y;
289 Link *l = NULL, *ll = NULL;
291 int *page_hist = NULL;
292 int page_hist_len = 1;
293 int page_hist_pos = 0;
304 "%s [-page page_number] [-file Edoc_fname] [-size width height] [Edoc_dir]\n",
309 if ((disp = XOpenDisplay(NULL)) == NULL)
311 printf("%s: Cannot open X display.\n", argv[0]);
315 /* now we'll set the locale */
316 setlocale(LC_ALL, "");
317 if (!XSupportsLocale())
318 setlocale(LC_ALL, "C");
319 XSetLocaleModifiers("");
320 setlocale(LC_ALL, NULL);
322 /* I dont want any internationalisation of my numeric input & output */
323 setlocale(LC_NUMERIC, "C");
328 for (i = 1; i < argc; i++)
330 if ((!strcmp(argv[i], "-page")) && (i < (argc - 1)))
331 pagenum = atoi(argv[++i]);
332 else if ((!strcmp(argv[i], "-file")) && (i < (argc - 1)))
334 else if ((!strcmp(argv[i], "-size")) && (i < (argc - 2)))
340 docdir = strdup(argv[i]);
343 docdir = strdup(doxdir);
344 s = EMALLOC(char, strlen(docdir) + strlen(docfile) + 2 + 20);
346 sprintf(s, "%s/%s", docdir, docfile);
347 findLocalizedFile(s);
349 im_title = ImageLoadDox("title.png");
350 imlib_context_set_image(im_title);
355 imlib_image_set_border(&ibd);
357 im_prev1 = ImageLoadDox("prev1.png");
358 im_prev2 = ImageLoadDox("prev2.png");
359 im_next1 = ImageLoadDox("next1.png");
360 im_next2 = ImageLoadDox("next2.png");
361 im_exit1 = ImageLoadDox("exit1.png");
362 im_exit2 = ImageLoadDox("exit2.png");
365 wx = (VRoot.w - w) / 2;
366 wy = (VRoot.h - (h + t)) / 2;
368 if (VRoot.win == DefaultRootWindow(disp) && XineramaIsActive(disp))
373 int pointer_x, pointer_y;
375 XineramaScreenInfo *screens;
377 XQueryPointer(disp, VRoot.win, &rt, &ch, &pointer_x, &pointer_y,
380 screens = XineramaQueryScreens(disp, &num);
381 for (i = 0; i < num; i++)
383 if (pointer_x >= screens[i].x_org &&
384 pointer_x <= (screens[i].width + screens[i].x_org) &&
385 pointer_y >= screens[i].y_org &&
386 pointer_y <= (screens[i].height + screens[i].y_org))
388 wx = ((screens[i].width - w) / 2) + screens[i].x_org;
389 wy = ((screens[i].height - (h + t)) / 2) + screens[i].y_org;
396 win_main = CreateWindow(VRoot.win, wx, wy, w, h + t);
398 XCreateSimpleWindow(disp, win_main, 0, 0, (w - 64 - 64 - t), t, 0, 0, 0);
400 XCreateSimpleWindow(disp, win_main, (w - 64 - 64 - t), 0, 64, t, 0, 0, 0);
402 XCreateSimpleWindow(disp, win_main, (w - 64 - 64 - t) + 64, 0, 64, t, 0,
405 XCreateSimpleWindow(disp, win_main, (w - 64 - 64 - t) + 64 + 64, 0, t, t,
407 win_text = XCreateSimpleWindow(disp, win_main, 0, t, w, h, 0, 0, 0);
409 XSelectInput(disp, win_main, KeyPressMask | KeyReleaseMask);
410 XSelectInput(disp, win_prev, ButtonPressMask | ButtonReleaseMask);
411 XSelectInput(disp, win_next, ButtonPressMask | ButtonReleaseMask);
412 XSelectInput(disp, win_exit, ButtonPressMask | ButtonReleaseMask);
413 XSelectInput(disp, win_text, ButtonPressMask | ButtonReleaseMask |
416 draw = XCreatePixmap(disp, win_text, w, h, VRoot.depth);
418 ApplyImage1(win_title, im_title);
419 ApplyImage1(win_prev, im_prev1);
420 ApplyImage1(win_next, im_next1);
421 ApplyImage1(win_exit, im_exit1);
423 LoadFile(s, docfile);
425 l = RenderPage(draw, pagenum, w, h);
428 XMapWindow(disp, win_title);
429 XMapWindow(disp, win_prev);
430 XMapWindow(disp, win_next);
431 XMapWindow(disp, win_exit);
432 XMapWindow(disp, win_text);
433 XMapWindow(disp, win_main);
437 page_hist = EMALLOC(int, 1);
446 prev_pagenum = pagenum;
448 XNextEvent(disp, &ev);
452 key = XLookupKeysym(&ev.xkey, 0);
472 page_hist_len = page_hist_pos + 1;
477 page_hist_len = page_hist_pos + 1;
480 LoadFile(s, docfile);
486 if (page_hist_pos >= page_hist_len - 1)
489 pagenum = page_hist[page_hist_pos];
493 if (pagenum == page_hist[page_hist_pos])
496 if (page_hist_pos < 0)
499 pagenum = page_hist[page_hist_pos];
503 pagenum = FixPage(pagenum);
504 if (pagenum == prev_pagenum)
507 if (page_hist_pos >= page_hist_len)
510 page_hist = EREALLOC(int, page_hist, page_hist_len);
512 page_hist_len = page_hist_pos + 1;
513 page_hist[page_hist_pos] = pagenum;
517 pagenum = FixPage(pagenum);
518 if (pagenum == prev_pagenum)
522 l = RenderPage(draw, pagenum, w, h);
527 if (ev.xbutton.window == win_prev)
528 ApplyImage2(win_prev, im_prev2);
529 else if (ev.xbutton.window == win_next)
530 ApplyImage2(win_next, im_next2);
531 else if (ev.xbutton.window == win_exit)
532 ApplyImage2(win_exit, im_exit2);
540 if ((x >= ll->x) && (y >= ll->y) &&
541 (x < (ll->x + ll->w)) && (y < (ll->y + ll->h)))
545 if (!strncmp("EXEC.", ll->name, 5))
551 exe = &(ll->name[5]);
552 execl("/bin/sh", "/bin/sh", "-c", exe,
557 else if (!strncmp("INPUT.", ll->name, 6))
560 char *exe, tmp[1024];
562 exe = &(ll->name[6]);
565 sprintf(tmp, "%s/%s", docdir, exe);
566 findLocalizedFile(tmp);
576 while ((*sp) && (*sp != ' '))
578 while ((*sp != '/') && (sp != exe))
584 docdir = EMALLOC(char, dirlen + 1);
586 memcpy(docdir, exe, dirlen);
592 page_hist = EMALLOC(int, 1);
599 l = RenderPage(draw, pagenum, w, h);
605 pg = GetPage(ll->name);
620 if (ev.xbutton.window == win_prev)
622 ApplyImage3(win_prev, im_prev1);
625 else if (ev.xbutton.window == win_next)
627 ApplyImage3(win_next, im_next1);
631 else if (ev.xbutton.window == win_exit)
633 ApplyImage3(win_exit, im_exit1);
643 while (XCheckTypedEvent(disp, ev.type, &ev))
646 static Link *pl = NULL;
654 if ((x >= ll->x) && (y >= ll->y) &&
655 (x < (ll->x + ll->w)) && (y < (ll->y + ll->h)))
668 GetLinkColors(pagenum, &r, &g, &b);
669 ESetColor(&xclr, r, g, b);
671 gc = XCreateGC(disp, win_text, 0, &gcv);
672 XSetForeground(disp, gc, xclr.pixel);
673 XDrawRectangle(disp, win_text, gc, ll->x, ll->y,
693 if (ev.xclient.message_type == ATOM_WM_PROTOCOLS &&
694 (Atom) ev.xclient.data.l[0] == ATOM_WM_DELETE_WINDOW)
707 ESetColor(XColor * pxc, int r, int g, int b)
709 pxc->red = (r << 8) | r;
710 pxc->green = (g << 8) | g;
711 pxc->blue = (b << 8) | b;
715 EGetColor(XColor * pxc, int *pr, int *pg, int *pb)
718 *pg = pxc->green >> 8;
719 *pb = pxc->blue >> 8;