My dmenu build
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

draw.c 4.4 KiB

13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /* See LICENSE file for copyright and license details. */
  2. #include <locale.h>
  3. #include <stdarg.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <X11/Xlib.h>
  8. #include "draw.h"
  9. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  10. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  11. #define DEFFONT "fixed"
  12. static Bool loadfont(DC *dc, const char *fontstr);
  13. void
  14. drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color) {
  15. XRectangle r = { dc->x + x, dc->y + y, w, h };
  16. if(!fill) {
  17. r.width -= 1;
  18. r.height -= 1;
  19. }
  20. XSetForeground(dc->dpy, dc->gc, color);
  21. (fill ? XFillRectangles : XDrawRectangles)(dc->dpy, dc->canvas, dc->gc, &r, 1);
  22. }
  23. void
  24. drawtext(DC *dc, const char *text, unsigned long col[ColLast]) {
  25. char buf[BUFSIZ];
  26. size_t mn, n = strlen(text);
  27. /* shorten text if necessary */
  28. for(mn = MIN(n, sizeof buf); textnw(dc, text, mn) + dc->font.height/2 > dc->w; mn--)
  29. if(mn == 0)
  30. return;
  31. memcpy(buf, text, mn);
  32. if(mn < n)
  33. for(n = MAX(mn-3, 0); n < mn; buf[n++] = '.');
  34. drawrect(dc, 0, 0, dc->w, dc->h, True, BG(dc, col));
  35. drawtextn(dc, buf, mn, col);
  36. }
  37. void
  38. drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]) {
  39. int x = dc->x + dc->font.height/2;
  40. int y = dc->y + dc->font.ascent+1;
  41. XSetForeground(dc->dpy, dc->gc, FG(dc, col));
  42. if(dc->font.set)
  43. XmbDrawString(dc->dpy, dc->canvas, dc->font.set, dc->gc, x, y, text, n);
  44. else {
  45. XSetFont(dc->dpy, dc->gc, dc->font.xfont->fid);
  46. XDrawString(dc->dpy, dc->canvas, dc->gc, x, y, text, n);
  47. }
  48. }
  49. void
  50. eprintf(const char *fmt, ...) {
  51. va_list ap;
  52. va_start(ap, fmt);
  53. vfprintf(stderr, fmt, ap);
  54. va_end(ap);
  55. if(fmt[strlen(fmt)-1] == ':') {
  56. fputc(' ', stderr);
  57. perror(NULL);
  58. }
  59. exit(EXIT_FAILURE);
  60. }
  61. void
  62. freedc(DC *dc) {
  63. if(dc->font.set)
  64. XFreeFontSet(dc->dpy, dc->font.set);
  65. if(dc->font.xfont)
  66. XFreeFont(dc->dpy, dc->font.xfont);
  67. if(dc->canvas)
  68. XFreePixmap(dc->dpy, dc->canvas);
  69. XFreeGC(dc->dpy, dc->gc);
  70. XCloseDisplay(dc->dpy);
  71. free(dc);
  72. }
  73. unsigned long
  74. getcolor(DC *dc, const char *colstr) {
  75. Colormap cmap = DefaultColormap(dc->dpy, DefaultScreen(dc->dpy));
  76. XColor color;
  77. if(!XAllocNamedColor(dc->dpy, cmap, colstr, &color, &color))
  78. eprintf("cannot allocate color '%s'\n", colstr);
  79. return color.pixel;
  80. }
  81. DC *
  82. initdc(void) {
  83. DC *dc;
  84. if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
  85. fprintf(stderr, "no locale support\n");
  86. if(!(dc = calloc(1, sizeof *dc)))
  87. eprintf("cannot malloc %u bytes:", sizeof *dc);
  88. if(!(dc->dpy = XOpenDisplay(NULL)))
  89. eprintf("cannot open display\n");
  90. dc->gc = XCreateGC(dc->dpy, DefaultRootWindow(dc->dpy), 0, NULL);
  91. XSetLineAttributes(dc->dpy, dc->gc, 1, LineSolid, CapButt, JoinMiter);
  92. return dc;
  93. }
  94. void
  95. initfont(DC *dc, const char *fontstr) {
  96. if(!loadfont(dc, fontstr ? fontstr : DEFFONT)) {
  97. if(fontstr != NULL)
  98. fprintf(stderr, "cannot load font '%s'\n", fontstr);
  99. if(fontstr == NULL || !loadfont(dc, DEFFONT))
  100. eprintf("cannot load font '%s'\n", DEFFONT);
  101. }
  102. dc->font.height = dc->font.ascent + dc->font.descent;
  103. }
  104. Bool
  105. loadfont(DC *dc, const char *fontstr) {
  106. char *def, **missing;
  107. int i, n;
  108. if(!*fontstr)
  109. return False;
  110. if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) {
  111. char **names;
  112. XFontStruct **xfonts;
  113. n = XFontsOfFontSet(dc->font.set, &xfonts, &names);
  114. for(i = dc->font.ascent = dc->font.descent = 0; i < n; i++) {
  115. dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent);
  116. dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent);
  117. }
  118. }
  119. else if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))) {
  120. dc->font.ascent = dc->font.xfont->ascent;
  121. dc->font.descent = dc->font.xfont->descent;
  122. }
  123. if(missing)
  124. XFreeStringList(missing);
  125. return (dc->font.set || dc->font.xfont);
  126. }
  127. void
  128. mapdc(DC *dc, Window win, unsigned int w, unsigned int h) {
  129. XCopyArea(dc->dpy, dc->canvas, win, dc->gc, 0, 0, w, h, 0, 0);
  130. }
  131. void
  132. resizedc(DC *dc, unsigned int w, unsigned int h) {
  133. if(dc->canvas)
  134. XFreePixmap(dc->dpy, dc->canvas);
  135. dc->canvas = XCreatePixmap(dc->dpy, DefaultRootWindow(dc->dpy), w, h,
  136. DefaultDepth(dc->dpy, DefaultScreen(dc->dpy)));
  137. dc->w = w;
  138. dc->h = h;
  139. }
  140. int
  141. textnw(DC *dc, const char *text, size_t len) {
  142. if(dc->font.set) {
  143. XRectangle r;
  144. XmbTextExtents(dc->font.set, text, len, NULL, &r);
  145. return r.width;
  146. }
  147. return XTextWidth(dc->font.xfont, text, len);
  148. }
  149. int
  150. textw(DC *dc, const char *text) {
  151. return textnw(dc, text, strlen(text)) + dc->font.height;
  152. }