printer.c 7.7 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.d_fd = ConnectionNumber(env.d);
  50. env.s = DefaultScreen(env.d);
  51. XVisualInfo vinfo;
  52. XMatchVisualInfo(env.d, env.s, 32, TrueColor, &vinfo);
  53. // size of the screen
  54. XWindowAttributes RootAttr;
  55. XGetWindowAttributes(env.d, RootWindow(env.d, env.s), &RootAttr);
  56. env.root_width = RootAttr.width;
  57. env.root_height = RootAttr.height;
  58. // set window attributes
  59. XSetWindowAttributes attr;
  60. attr.colormap = XCreateColormap(env.d, RootWindow(env.d, env.s),
  61. vinfo.visual, AllocNone);
  62. attr.border_pixel = 0;
  63. attr.background_pixel = 0;
  64. attr.override_redirect = 1; // no window manager border
  65. // set colors
  66. env.color_text = XWhitePixel(env.d, env.s);
  67. XColor tmp;
  68. XParseColor(env.d, attr.colormap, "#222222", &tmp);
  69. XAllocColor(env.d, attr.colormap, &tmp);
  70. env.color_background = tmp.pixel;
  71. //unsigned short r = 34, g = 34, b = 34, a = 192; // TODO where is the doc ?
  72. //env.color_background = a*256*256*256 + r*256*256 + g*256 + b;
  73. // create the window
  74. env.width = 1;
  75. env.height = 1;
  76. env.w = XCreateWindow(env.d, RootWindow(env.d, env.s), 0, 0, env.width,
  77. env.height, 0, vinfo.depth, InputOutput, vinfo.visual,
  78. CWColormap | CWBorderPixel | CWBackPixel | CWOverrideRedirect, &attr);
  79. // setting fonts
  80. char *fontname = (font == NULL) ?
  81. "-bitstream-bitstream charter-medium-r-normal--*-280-100-100-p-*-iso8859-1"
  82. : font;
  83. env.fontinfo = XLoadQueryFont(env.d, fontname);
  84. if(!env.fontinfo)
  85. {
  86. fprintf (stderr, "unable to load font %s: using fixed\n", fontname);
  87. env.fontinfo = XLoadQueryFont(env.d, "fixed");
  88. }
  89. env.maxascent = env.fontinfo->ascent;
  90. env.maxdescent = env.fontinfo->descent;
  91. loadFont(&env, &env.fontinfo_i, (font_i == NULL) ?
  92. "-bitstream-bitstream charter-medium-i-normal--*-280-100-100-p-*-iso8859-1"
  93. : font_i);
  94. loadFont(&env, &env.fontinfo_b, (font_b == NULL) ?
  95. "-bitstream-bitstream charter-bold-r-normal--*-280-100-100-p-*-iso8859-1"
  96. : font_b);
  97. loadFont(&env, &env.fontinfo_bi, (font_bi == NULL) ?
  98. "-bitstream-bitstream charter-bold-i-normal--*-280-100-100-p-*-iso8859-1"
  99. : font_bi);
  100. // create GC
  101. XGCValues gr_values;
  102. gr_values.font = env.fontinfo->fid;
  103. gr_values.foreground = XWhitePixel(env.d, env.s);
  104. gr_values.background = XBlackPixel(env.d, env.s);
  105. env.gc = XCreateGC(env.d, env.w, GCFont | GCForeground, &gr_values);
  106. // focused window (for keyboard)
  107. int revert;
  108. XGetInputFocus(env.d, &env.w_focused, &revert);
  109. // event to be listened
  110. XSelectInput(env.d, env.w_focused, KeyPressMask|FocusChangeMask);
  111. return env;
  112. }
  113. void printerCloseWindow(struct printerEnv env)
  114. {
  115. XCloseDisplay(env.d); // window is automatically destroyed
  116. }
  117. XFontStruct* getFont(struct printerEnv env, enum t_type flags)
  118. {
  119. if(flags & T_ITALIC && flags & T_BOLD)
  120. return env.fontinfo_bi;
  121. if(flags & T_ITALIC)
  122. return env.fontinfo_i;
  123. if(flags & T_BOLD)
  124. return env.fontinfo_b;
  125. return env.fontinfo;
  126. }
  127. int drawTextRaw(struct printerEnv env, char *text, int size, enum t_type font,
  128. int *x, int *y, int draw)
  129. {
  130. int font_direction, font_ascent, font_descent;
  131. XCharStruct text_structure;
  132. XTextExtents(getFont(env, font), text, size,
  133. &font_direction, &font_ascent, &font_descent,
  134. &text_structure);
  135. if(draw)
  136. {
  137. XSetFont(env.d, env.gc, getFont(env, font)->fid);
  138. XDrawString(env.d, env.w, env.gc, *x, *y, text, size);
  139. }
  140. *x += text_structure.width;
  141. }
  142. int drawTextLines(struct printerEnv env, char *text, int size, enum t_type font,
  143. int *x, int *y, int *maxw, int draw)
  144. {
  145. char *nl = memchr(text, '\n', size);
  146. if(nl == NULL)
  147. {
  148. drawTextRaw(env, text, size, font, x, y, draw);
  149. if(*x > *maxw)
  150. *maxw = *x;
  151. }
  152. else
  153. {
  154. drawTextRaw(env, text, nl-text, font, x, y, draw);
  155. if(*x > *maxw)
  156. *maxw = *x;
  157. *x = env.padding;
  158. *y += env.maxascent + env.maxdescent + env.gap;
  159. drawTextLines(env, nl+1, text-nl-1+size, font, x, y, maxw, draw);
  160. }
  161. }
  162. // update x and y
  163. int drawText(struct printerEnv env, struct richText *rt,
  164. int *x, int *y, int *maxw, int draw)
  165. {
  166. if(rt->left != NULL && rt->right != NULL)
  167. {
  168. drawText(env, rt->left, x, y, maxw, draw);
  169. drawText(env, rt->right, x, y, maxw, draw);
  170. }
  171. else
  172. drawTextLines(env, rt->pos, rt->size, rt->type, x, y, maxw, draw);
  173. }
  174. // TODO show and hide : show mutliple rt, with id
  175. void printerShow(struct printerEnv *env, struct richText *rt, int id)
  176. {
  177. int x, y;
  178. // remap the window
  179. XMapWindow(env->d, env->w);
  180. // width and height
  181. x = env->padding;
  182. env->width = x;
  183. env->height = env->padding;
  184. drawText(*env, rt, &x, &env->height, &env->width, 0);
  185. env->width += env->padding;
  186. env->height += env->padding;
  187. XClearWindow(env->d, env->w);
  188. XMoveResizeWindow(env->d, env->w, (env->root_width - env->width)/2,
  189. env->root_height - env->margin_bottom - env->height, env->width,
  190. env->height);
  191. // frame
  192. XSetForeground(env->d, env->gc, env->color_background);
  193. XFillRectangle(env->d, env->w, env->gc, 0, 0, env->width, env->height);
  194. XSetForeground(env->d, env->gc, env->color_text);
  195. // text
  196. x = env->padding; // TODO avant c'était centré
  197. y = env->padding + env->maxascent;
  198. drawText(*env, rt, &x, &y, &x, 1);
  199. XFlush(env->d);
  200. }
  201. void printerHide(struct printerEnv *env, int id)
  202. {
  203. XClearWindow(env->d, env->w);
  204. XUnmapWindow(env->d, env->w);
  205. XFlush(env->d);
  206. }
  207. t_event manageEvent(struct printerEnv *env)
  208. {
  209. XEvent event;
  210. int r;
  211. XComposeStatus comp;
  212. t_event e;
  213. XNextEvent(env->d, &event);
  214. switch(event.type)
  215. {
  216. case FocusOut:
  217. XGetInputFocus(env->d, &env->w_focused, &r);
  218. if(env->w_focused == PointerRoot)
  219. env->w_focused = RootWindow(env->d, env->s); // TODO why ?
  220. XSelectInput(env->d, env->w_focused, KeyPressMask|FocusChangeMask);
  221. event.type = T_NONE;
  222. break;
  223. case KeyPress:
  224. e.type = T_KEYPRESSED;
  225. e.keyPressed.key = (int)XkbKeycodeToKeysym(env->d, event.xkey.keycode, 0,
  226. event.xkey.state & ShiftMask ? 1 : 0);
  227. // e.keyPress.time = TODO (event.xkey.time is the number of milliseconds (from uptime ?)
  228. break;
  229. default:
  230. e.type = T_NONE;
  231. break;
  232. }
  233. return e;
  234. }