stupidterm.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /* See LICENSE file for copyright and license details. */
  2. #include <assert.h>
  3. #include <stdint.h>
  4. #include <X11/Xlib.h>
  5. #include <X11/keysym.h>
  6. #include <X11/extensions/Xrender.h>
  7. #include <ft2build.h>
  8. #include FT_FREETYPE_H
  9. #include "dtext.h"
  10. // Configuration
  11. char const *font =
  12. "/usr/share/fonts/fantasque-sans-mono/FantasqueSansMono-Regular.otf:16;"
  13. "/usr/share/fonts/powerline-symbols/PowerlineSymbols.otf:14;"
  14. "/usr/share/fonts/dejavu/DejaVuSansMono.ttf:16";
  15. char const *fontb =
  16. "/usr/share/fonts/fantasque-sans-mono/FantasqueSansMono-Bold.otf:16;"
  17. "/usr/share/fonts/powerline-symbols/PowerlineSymbols.otf:14;"
  18. "/usr/share/fonts/dejavu/DejaVuSansMono-Bold.ttf:16";
  19. char const *fonti =
  20. "/usr/share/fonts/fantasque-sans-mono/FantasqueSansMono-RegItalic.otf:16;"
  21. "/usr/share/fonts/powerline-symbols/PowerlineSymbols.otf:14;"
  22. "/usr/share/fonts/dejavu/DejaVuSansMono-Oblique.ttf:16";
  23. char const *fontbi =
  24. "/usr/share/fonts/fantasque-sans-mono/FantasqueSansMono-BoldItalic.otf:16;"
  25. "/usr/share/fonts/powerline-symbols/PowerlineSymbols.otf:14;"
  26. "/usr/share/fonts/dejavu/DejaVuSansMono-BoldOblique.ttf:16";
  27. // Fantasque is good for testing: its reported height is far too big, so it
  28. // allows testing the boringness of tuning the scales
  29. float chscale = 1.f; // horizontal scale
  30. float cvscale = .51f; // vertical scale
  31. float cascale = .482f; // ascender scale
  32. // \f1: toggle bold
  33. // \f2: toggle italics
  34. // \f3??????: change fgcolor to ?????? (RGB format)
  35. // \f4??????: change bgcolor to ?????? (RGB format)
  36. wchar_t const *text =
  37. L"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
  38. L"Donec a diam lectus. \f1Sed sit amet ipsum mauris.\f1\n"
  39. L"\f2Maecenas\f2 congue ligula ac \f1\f2quam viverra nec\f1\f2\n"
  40. L"consectetur ante hendrerit. \f300FF00Donec et mollis dolor.\f3000000\n"
  41. L"Praesent \f4FF0000et \f1diam \f2eget\f1 libero\f40000FF egestas\f2\f4FFFFFF\n"
  42. L"mattis sit amet vitae augue.\n"
  43. L"\n"
  44. L"\f4000000\f3FF0000 \xe0a0 \f30000FF\x2699 \f3FFFFFFsome text \f3000000\f4FFFFFF This is a pseudo-prompt.\n";
  45. // Implementation
  46. Display *dpy;
  47. Window win;
  48. GC gc;
  49. Colormap cmap;
  50. dt_context *ctx;
  51. dt_font *fnt, *fntb, *fnti, *fntbi;
  52. dt_color color;
  53. static void setup_x();
  54. static void setup_dt();
  55. static void draw(wchar_t const *txt);
  56. int main()
  57. {
  58. XEvent evt;
  59. _Xdebug = 1;
  60. setup_x();
  61. setup_dt();
  62. draw(text);
  63. XSelectInput(dpy, win, ExposureMask | KeyPressMask);
  64. while (1) {
  65. XNextEvent(dpy, &evt);
  66. switch (evt.type) {
  67. case Expose:
  68. draw(text);
  69. break;
  70. case KeyPress:
  71. if (XLookupKeysym(&evt.xkey, 0) == XK_Escape)
  72. return 0;
  73. break;
  74. }
  75. }
  76. dt_free(ctx, fnt);
  77. dt_quit(ctx);
  78. XCloseDisplay(dpy);
  79. }
  80. static void setup_x()
  81. {
  82. unsigned long white, black;
  83. dpy = XOpenDisplay(NULL);
  84. white = XWhitePixel(dpy, DefaultScreen(dpy));
  85. black = XBlackPixel(dpy, DefaultScreen(dpy));
  86. win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
  87. 700, 500, 0, white, white);
  88. XMapWindow(dpy, win);
  89. gc = XDefaultGC(dpy, 0);
  90. XSetForeground(dpy, gc, black);
  91. cmap = DefaultColormap(dpy, 0);
  92. }
  93. static void setup_dt()
  94. {
  95. assert(!dt_init(&ctx, dpy, win));
  96. assert(!dt_load(ctx, &fnt, font));
  97. assert(!dt_load(ctx, &fntb, fontb));
  98. assert(!dt_load(ctx, &fnti, fonti));
  99. assert(!dt_load(ctx, &fntbi, fontbi));
  100. memset(&color, 0, sizeof(color));
  101. color.alpha = 0xFF;
  102. }
  103. static void draw(wchar_t const *txt)
  104. {
  105. dt_bbox bbox;
  106. size_t x, y;
  107. int bold, italics;
  108. dt_font *curfnt;
  109. dt_color fgcol;
  110. XColor bgcol;
  111. char color[8];
  112. size_t i;
  113. x = 0;
  114. y = fnt->ascent * cascale;
  115. bold = italics = 0;
  116. curfnt = fnt;
  117. memset(&fgcol, 0, sizeof(fgcol));
  118. fgcol.alpha = 0xFF;
  119. XParseColor(dpy, cmap, "#FFFFFF", &bgcol);
  120. XAllocColor(dpy, cmap, &bgcol);
  121. XSetForeground(dpy, gc, bgcol.pixel);
  122. memset(color, 0, sizeof(color));
  123. color[0] = '#';
  124. while (*txt) {
  125. if (*txt != L'\f' && *txt != L'\n') {
  126. dt_box(ctx, curfnt, &bbox, txt, 1);
  127. XFillRectangle(dpy, win, gc, x + bbox.x, y - curfnt->ascent * cascale, bbox.w, curfnt->height * cvscale);
  128. dt_draw(ctx, curfnt, &fgcol, x, y, txt, 1);
  129. x += bbox.w * chscale;
  130. } else if (*txt == L'\n') {
  131. x = 0;
  132. y += curfnt->height * cvscale;
  133. } else if (*txt == L'\f') {
  134. ++txt;
  135. switch (*txt) {
  136. case L'1':
  137. bold = !bold;
  138. break;
  139. case L'2':
  140. italics = !italics;
  141. break;
  142. case L'3':
  143. case L'4':
  144. for (i = 0; i < 6; ++i)
  145. color[i + 1] = (char) txt[i + 1];
  146. XParseColor(dpy, cmap, color, &bgcol);
  147. if (*txt == L'3') {
  148. fgcol.red = bgcol.red >> 8;
  149. fgcol.green = bgcol.green >> 8;
  150. fgcol.blue = bgcol.blue >> 8;
  151. } else {
  152. XAllocColor(dpy, cmap, &bgcol);
  153. XSetForeground(dpy, gc, bgcol.pixel);
  154. }
  155. txt += 6;
  156. break;
  157. }
  158. if (bold && italics)
  159. curfnt = fntbi;
  160. else if (bold)
  161. curfnt = fntb;
  162. else if (italics)
  163. curfnt = fnti;
  164. else
  165. curfnt = fnt;
  166. }
  167. ++txt;
  168. }
  169. XFlush(dpy);
  170. }