printer.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. Copyright (C) 2014 Olivier Marty <olivier.marty.m at gmail.com>
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  14. */
  15. #include "printer.h"
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <X11/Xlib.h>
  19. #include <X11/Xutil.h>
  20. #include <X11/keysym.h>
  21. #include <X11/XKBlib.h>
  22. #include <string.h>
  23. void loadFont(struct printerEnv *env, XFontStruct **font, char* fontname)
  24. {
  25. *font = XLoadQueryFont(env->d, fontname);
  26. if(!*font)
  27. {
  28. fprintf (stderr, "unable to load font %s - using normal font\n", fontname);
  29. *font = env->fontinfo;
  30. }
  31. else
  32. {
  33. if((*font)->ascent > env->maxascent)
  34. env->maxascent = (*font)->ascent;
  35. if((*font)->descent > env->maxdescent)
  36. env->maxdescent = (*font)->descent;
  37. }
  38. }
  39. struct printerEnv printerOpenWindow(char *font, char *font_i, char *font_b,
  40. char *font_bi)
  41. {
  42. struct printerEnv env;
  43. // open connection
  44. env.d = XOpenDisplay(NULL);
  45. if (env.d == NULL) {
  46. fprintf(stderr, "Unable to open display\n");
  47. exit(1);
  48. }
  49. env.s = DefaultScreen(env.d);
  50. XVisualInfo vinfo;
  51. XMatchVisualInfo(env.d, env.s, 32, TrueColor, &vinfo);
  52. // size of the screen
  53. XWindowAttributes RootAttr;
  54. XGetWindowAttributes(env.d, RootWindow(env.d, env.s), &RootAttr);
  55. env.root_width = RootAttr.width;
  56. env.root_height = RootAttr.height;
  57. // set window attributes
  58. XSetWindowAttributes attr;
  59. attr.colormap = XCreateColormap(env.d, RootWindow(env.d, env.s),
  60. vinfo.visual, AllocNone);
  61. attr.border_pixel = 0;
  62. attr.background_pixel = 0;
  63. attr.override_redirect = 1; // no window manager border
  64. // set colors
  65. env.color_text = XWhitePixel(env.d, env.s);
  66. XColor tmp;
  67. XParseColor(env.d, attr.colormap, "#222222", &tmp);
  68. XAllocColor(env.d, attr.colormap, &tmp);
  69. env.color_background = tmp.pixel;
  70. //unsigned short r = 34, g = 34, b = 34, a = 192; // TODO where is the doc ?
  71. //env.color_background = a*256*256*256 + r*256*256 + g*256 + b;
  72. // create the window
  73. env.width = 1;
  74. env.height = 1;
  75. env.w = XCreateWindow(env.d, RootWindow(env.d, env.s), 0, 0, env.width,
  76. env.height, 0, vinfo.depth, InputOutput, vinfo.visual,
  77. CWColormap | CWBorderPixel | CWBackPixel | CWOverrideRedirect, &attr);
  78. // setting fonts
  79. char *fontname = (font == NULL) ?
  80. "-bitstream-bitstream charter-medium-r-normal--*-280-100-100-p-*-iso8859-1"
  81. : font;
  82. env.fontinfo = XLoadQueryFont(env.d, fontname);
  83. if(!env.fontinfo)
  84. {
  85. fprintf (stderr, "unable to load font %s: using fixed\n", fontname);
  86. env.fontinfo = XLoadQueryFont(env.d, "fixed");
  87. }
  88. env.maxascent = env.fontinfo->ascent;
  89. env.maxdescent = env.fontinfo->descent;
  90. loadFont(&env, &env.fontinfo_i, (font_i == NULL) ?
  91. "-bitstream-bitstream charter-medium-i-normal--*-280-100-100-p-*-iso8859-1"
  92. : font_i);
  93. loadFont(&env, &env.fontinfo_b, (font_b == NULL) ?
  94. "-bitstream-bitstream charter-bold-r-normal--*-280-100-100-p-*-iso8859-1"
  95. : font_b);
  96. loadFont(&env, &env.fontinfo_bi, (font_bi == NULL) ?
  97. "-bitstream-bitstream charter-bold-i-normal--*-280-100-100-p-*-iso8859-1"
  98. : font_bi);
  99. // create GC
  100. XGCValues gr_values;
  101. gr_values.font = env.fontinfo->fid;
  102. gr_values.foreground = XWhitePixel(env.d, env.s);
  103. gr_values.background = XBlackPixel(env.d, env.s);
  104. env.gc = XCreateGC(env.d, env.w, GCFont | GCForeground, &gr_values);
  105. // focused window (for keyboard)
  106. int revert;
  107. XGetInputFocus(env.d, &env.w_focused, &revert);
  108. // event to be listened
  109. XSelectInput(env.d, env.w_focused, KeyPressMask|FocusChangeMask);
  110. return env;
  111. }
  112. void printerCloseWindow(struct printerEnv env)
  113. {
  114. XCloseDisplay(env.d); // window is automatically destroyed
  115. }
  116. XFontStruct* getFont(struct printerEnv env, enum t_type flags)
  117. {
  118. if(flags & T_ITALIC && flags & T_BOLD)
  119. return env.fontinfo_bi;
  120. if(flags & T_ITALIC)
  121. return env.fontinfo_i;
  122. if(flags & T_BOLD)
  123. return env.fontinfo_b;
  124. return env.fontinfo;
  125. }
  126. int drawTextRaw(struct printerEnv env, char *text, int size, enum t_type font,
  127. int *x, int *y, int draw)
  128. {
  129. int font_direction, font_ascent, font_descent;
  130. XCharStruct text_structure;
  131. XTextExtents(getFont(env, font), text, size,
  132. &font_direction, &font_ascent, &font_descent,
  133. &text_structure);
  134. if(draw)
  135. {
  136. XSetFont(env.d, env.gc, getFont(env, font)->fid);
  137. XDrawString(env.d, env.w, env.gc, *x, *y, text, size);
  138. }
  139. *x += text_structure.width;
  140. }
  141. int drawTextLines(struct printerEnv env, char *text, int size, enum t_type font,
  142. int *x, int *y, int *maxw, int draw)
  143. {
  144. char *nl = memchr(text, '\n', size);
  145. if(nl == NULL)
  146. {
  147. drawTextRaw(env, text, size, font, x, y, draw);
  148. if(*x > *maxw)
  149. *maxw = *x;
  150. }
  151. else
  152. {
  153. drawTextRaw(env, text, nl-text, font, x, y, draw);
  154. if(*x > *maxw)
  155. *maxw = *x;
  156. *x = env.padding;
  157. *y += env.maxascent + env.maxdescent + env.gap;
  158. drawTextLines(env, nl+1, text-nl-1+size, font, x, y, maxw, draw);
  159. }
  160. }
  161. // update x and y
  162. int drawText(struct printerEnv env, struct richText *rt,
  163. int *x, int *y, int *maxw, int draw)
  164. {
  165. if(rt->left != NULL && rt->right != NULL)
  166. {
  167. drawText(env, rt->left, x, y, maxw, draw);
  168. drawText(env, rt->right, x, y, maxw, draw);
  169. }
  170. else
  171. drawTextLines(env, rt->pos, rt->size, rt->type, x, y, maxw, draw);
  172. }
  173. void printerShow(struct printerEnv *env, struct richText *rt)
  174. {
  175. int x, y;
  176. // remap the window
  177. XMapWindow(env->d, env->w);
  178. // width and height
  179. x = env->padding;
  180. env->width = x;
  181. env->height = env->padding;
  182. drawText(*env, rt, &x, &env->height, &env->width, 0);
  183. env->width += env->padding;
  184. env->height += env->padding;
  185. XClearWindow(env->d, env->w);
  186. XMoveResizeWindow(env->d, env->w, (env->root_width - env->width)/2,
  187. env->root_height - env->margin_bottom - env->height, env->width,
  188. env->height);
  189. // frame
  190. XSetForeground(env->d, env->gc, env->color_background);
  191. XFillRectangle(env->d, env->w, env->gc, 0, 0, env->width, env->height);
  192. XSetForeground(env->d, env->gc, env->color_text);
  193. // text
  194. x = env->padding; // TODO avant c'était centré
  195. y = env->padding + env->maxascent;
  196. drawText(*env, rt, &x, &y, &x, 1);
  197. XFlush(env->d);
  198. }
  199. void printerClean(struct printerEnv env)
  200. {
  201. XClearWindow(env.d, env.w);
  202. XUnmapWindow(env.d, env.w);
  203. XFlush(env.d);
  204. }
  205. void manageEvent(struct printerEnv *env, void callback(struct printerEnv*,int,void*), void* callback_arg)
  206. {
  207. XEvent event;
  208. int r;
  209. XComposeStatus comp;
  210. while(XPending(env->d))
  211. {
  212. XNextEvent(env->d, &event);
  213. switch(event.type)
  214. {
  215. case FocusOut:
  216. XGetInputFocus(env->d, &env->w_focused, &r);
  217. if(env->w_focused == PointerRoot)
  218. env->w_focused = RootWindow(env->d, env->s); // TODO why ?
  219. XSelectInput(env->d, env->w_focused, KeyPressMask|FocusChangeMask);
  220. break;
  221. case KeyPress:
  222. callback(env, (int)XkbKeycodeToKeysym(env->d, event.xkey.keycode, 0, event.xkey.state & ShiftMask ? 1 : 0), callback_arg);
  223. break;
  224. default:
  225. break;
  226. }
  227. }
  228. }
  229. void waitEvent(struct printerEnv *env)
  230. {
  231. XEvent event;
  232. XPeekEvent(env->d, &event);
  233. }