colormessage.c (3204B)
1 #include <X11/extensions/Xinerama.h> 2 3 /* global count to prevent repeated error messages */ 4 int count_error = 0; 5 6 static int 7 readescapedint(const char *str, int *i) { 8 int n = 0; 9 if (str[*i]) 10 ++*i; 11 while(str[*i] && str[*i] != ';' && str[*i] != 'm') { 12 n = 10 * n + str[*i] - '0'; 13 ++*i; 14 } 15 return n; 16 } 17 18 static void 19 writemessage(Display *dpy, Window win, int screen) 20 { 21 int len, line_len, width, height, s_width, s_height, i, k, tab_size, r, g, b, escaped_int, curr_line_len; 22 XGCValues gr_values; 23 XFontStruct *fontinfo; 24 XColor color, dummy; 25 XineramaScreenInfo *xsi; 26 GC gc; 27 fontinfo = XLoadQueryFont(dpy, font_name); 28 29 if (fontinfo == NULL) { 30 if (count_error == 0) { 31 fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name); 32 fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n"); 33 count_error++; 34 } 35 return; 36 } 37 38 tab_size = 8 * XTextWidth(fontinfo, " ", 1); 39 40 XAllocNamedColor(dpy, DefaultColormap(dpy, screen), 41 text_color, &color, &dummy); 42 43 gr_values.font = fontinfo->fid; 44 gr_values.foreground = color.pixel; 45 gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values); 46 47 /* To prevent "Uninitialized" warnings. */ 48 xsi = NULL; 49 50 /* 51 * Start formatting and drawing text 52 */ 53 54 len = strlen(message); 55 56 /* Max max line length (cut at '\n') */ 57 line_len = curr_line_len = 0; 58 k = 0; 59 for (i = 0; i < len; i++) { 60 if (message[i] == '\n') { 61 curr_line_len = 0; 62 k++; 63 } else if (message[i] == 0x1b) { 64 while (i < len && message[i] != 'm') { 65 i++; 66 } 67 if (i == len) 68 die("slock: unclosed escape sequence\n"); 69 } else { 70 curr_line_len += XTextWidth(fontinfo, message + i, 1); 71 if (curr_line_len > line_len) 72 line_len = curr_line_len; 73 } 74 } 75 /* If there is only one line */ 76 if (line_len == 0) 77 line_len = len; 78 79 if (XineramaIsActive(dpy)) { 80 xsi = XineramaQueryScreens(dpy, &i); 81 s_width = xsi[0].width; 82 s_height = xsi[0].height; 83 } else { 84 s_width = DisplayWidth(dpy, screen); 85 s_height = DisplayHeight(dpy, screen); 86 } 87 height = s_height*3/7 - (k*20)/3; 88 width = (s_width - line_len)/2; 89 90 line_len = 0; 91 /* print the text while parsing 24 bit color ANSI escape codes*/ 92 for (i = k = 0; i < len; i++) { 93 switch (message[i]) { 94 case '\n': 95 line_len = 0; 96 while (message[i + 1] == '\t') { 97 line_len += tab_size; 98 i++; 99 } 100 k++; 101 break; 102 case 0x1b: 103 i++; 104 if (message[i] == '[') { 105 escaped_int = readescapedint(message, &i); 106 if (escaped_int == 39) 107 continue; 108 if (escaped_int != 38) 109 die("slock: unknown escape sequence%d\n", escaped_int); 110 if (readescapedint(message, &i) != 2) 111 die("slock: only 24 bit color supported\n"); 112 r = readescapedint(message, &i) & 0xff; 113 g = readescapedint(message, &i) & 0xff; 114 b = readescapedint(message, &i) & 0xff; 115 XSetForeground(dpy, gc, r << 16 | g << 8 | b); 116 } else 117 die("slock: unknown escape sequence\n"); 118 break; 119 default: 120 XDrawString(dpy, win, gc, width + line_len, height + 20 * k, message + i, 1); 121 line_len += XTextWidth(fontinfo, message + i, 1); 122 } 123 } 124 125 /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ 126 if (XineramaIsActive(dpy) && xsi != NULL) 127 XFree(xsi); 128 }