… | |
… | |
28 | #include <fcntl.h> |
28 | #include <fcntl.h> |
29 | #include <errno.h> |
29 | #include <errno.h> |
30 | #include <sys/time.h> |
30 | #include <sys/time.h> |
31 | #include <sys/stat.h> |
31 | #include <sys/stat.h> |
32 | #include <sys/types.h> |
32 | #include <sys/types.h> |
|
|
33 | #include <locale.h> |
33 | #if HAS_REGEX |
34 | #if HAS_REGEX |
34 | #include <regex.h> |
35 | #include <regex.h> |
35 | #endif |
36 | #endif |
36 | #include <X11/Xlib.h> |
37 | #include <X11/Xlib.h> |
|
|
38 | #include <X11/Xatom.h> |
37 | #include <X11/Xutil.h> |
39 | #include <X11/Xutil.h> |
38 | |
40 | |
39 | /* data structures */ |
41 | /* data structures */ |
40 | struct logfile_entry { |
42 | struct logfile_entry { |
41 | char *fname; /* name of file */ |
43 | char *fname; /* name of file */ |
… | |
… | |
57 | int width = STD_WIDTH, listlen = STD_HEIGHT; |
59 | int width = STD_WIDTH, listlen = STD_HEIGHT; |
58 | int win_x = LOC_X, win_y = LOC_Y; |
60 | int win_x = LOC_X, win_y = LOC_Y; |
59 | int w = -1, h = -1, font_width, font_height, font_descent; |
61 | int w = -1, h = -1, font_width, font_height, font_descent; |
60 | int do_reopen; |
62 | int do_reopen; |
61 | struct timeval interval = { 2, 400000 }; /* see Knuth */ |
63 | struct timeval interval = { 2, 400000 }; /* see Knuth */ |
|
|
64 | XFontSet fontset; |
62 | |
65 | |
63 | /* command line options */ |
66 | /* command line options */ |
64 | int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename, |
67 | int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename, |
65 | geom_mask, reload = 3600; |
68 | geom_mask, reload = 3600; |
66 | const char *command = NULL, |
69 | const char *command = NULL, |
… | |
… | |
122 | do_reopen = 1; |
125 | do_reopen = 1; |
123 | } |
126 | } |
124 | |
127 | |
125 | void force_refresh(int dummy) |
128 | void force_refresh(int dummy) |
126 | { |
129 | { |
127 | XClearWindow(disp, root); |
130 | XClearArea(disp, root, win_x, win_y, w, h + font_descent + 2, False); |
128 | redraw(); |
131 | redraw(); |
129 | } |
132 | } |
130 | |
133 | |
131 | void blank_window(int dummy) |
134 | void blank_window(int dummy) |
132 | { |
135 | { |
133 | XClearWindow(disp, root); |
136 | XClearArea(disp, root, win_x, win_y, w, h + font_descent + 2, False); |
134 | XFlush(disp); |
137 | XFlush(disp); |
135 | exit(0); |
138 | exit(0); |
136 | } |
139 | } |
137 | |
140 | |
138 | /* X related functions */ |
141 | /* X related functions */ |
… | |
… | |
148 | else if (!XAllocColor(disp, Attributes.colormap, &Color)) |
151 | else if (!XAllocColor(disp, Attributes.colormap, &Color)) |
149 | fprintf(stderr, "can't allocate %s\n", ColorName); |
152 | fprintf(stderr, "can't allocate %s\n", ColorName); |
150 | return Color.pixel; |
153 | return Color.pixel; |
151 | } |
154 | } |
152 | |
155 | |
|
|
156 | static Window root_window (Display *display, int screen_number) |
|
|
157 | { |
|
|
158 | Atom __SWM_VROOT = XInternAtom (display, "__SWM_VROOT", False); |
|
|
159 | Window real_root_window = RootWindow (display, screen_number); |
|
|
160 | |
|
|
161 | if (__SWM_VROOT != None) |
|
|
162 | { |
|
|
163 | Window unused, *windows; |
|
|
164 | unsigned int count; |
|
|
165 | |
|
|
166 | if (XQueryTree (display, real_root_window, &unused, &unused, &windows, |
|
|
167 | &count)) |
|
|
168 | { |
|
|
169 | int i; |
|
|
170 | |
|
|
171 | for (i = 0; i < count; i++) |
|
|
172 | { |
|
|
173 | Atom type; |
|
|
174 | int format; |
|
|
175 | unsigned long nitems, bytes_after_return; |
|
|
176 | unsigned char *virtual_root_window; |
|
|
177 | |
|
|
178 | if (XGetWindowProperty (display, windows[i], __SWM_VROOT, |
|
|
179 | 0, 1, False, XA_WINDOW, &type, &format, |
|
|
180 | &nitems, &bytes_after_return, |
|
|
181 | &virtual_root_window) |
|
|
182 | == Success) |
|
|
183 | { |
|
|
184 | if (type != None) |
|
|
185 | { |
|
|
186 | if (type == XA_WINDOW) |
|
|
187 | { |
|
|
188 | XFree (windows); |
|
|
189 | return (Window)virtual_root_window; |
|
|
190 | } |
|
|
191 | else |
|
|
192 | fprintf (stderr, "__SWM_VROOT property type mismatch"); |
|
|
193 | } |
|
|
194 | } |
|
|
195 | else |
|
|
196 | fprintf (stderr, |
|
|
197 | "failed to get __SWM_VROOT property on window 0x%lx", |
|
|
198 | windows[i]); |
|
|
199 | } |
|
|
200 | |
|
|
201 | if (count) |
|
|
202 | XFree (windows); |
|
|
203 | } |
|
|
204 | else |
|
|
205 | fprintf (stderr, "Can't query tree on root window 0x%lx", |
|
|
206 | real_root_window); |
|
|
207 | } |
|
|
208 | else |
|
|
209 | /* This shouldn't happen. The Xlib documentation is wrong BTW. */ |
|
|
210 | fprintf (stderr, "Can't intern atom __SWM_VROOT"); |
|
|
211 | |
|
|
212 | return real_root_window; |
|
|
213 | } |
|
|
214 | |
153 | void InitWindow(void) |
215 | void InitWindow(void) |
154 | { |
216 | { |
155 | XGCValues gcv; |
217 | XGCValues gcv; |
156 | Font font; |
218 | Font font; |
157 | unsigned long gcm; |
219 | unsigned long gcm; |
… | |
… | |
163 | exit(1); |
225 | exit(1); |
164 | } |
226 | } |
165 | screen = DefaultScreen(disp); |
227 | screen = DefaultScreen(disp); |
166 | ScreenHeight = DisplayHeight(disp, screen); |
228 | ScreenHeight = DisplayHeight(disp, screen); |
167 | ScreenWidth = DisplayWidth(disp, screen); |
229 | ScreenWidth = DisplayWidth(disp, screen); |
168 | root = RootWindow(disp, screen); |
230 | root = root_window (disp, screen); |
169 | gcm = GCBackground; |
231 | gcm = GCBackground; |
170 | gcv.graphics_exposures = True; |
232 | gcv.graphics_exposures = True; |
171 | WinGC = XCreateGC(disp, root, gcm, &gcv); |
233 | WinGC = XCreateGC(disp, root, gcm, &gcv); |
172 | XMapWindow(disp, root); |
234 | XMapWindow(disp, root); |
173 | XSetForeground(disp, WinGC, GetColor(DEF_COLOR)); |
235 | XSetForeground(disp, WinGC, GetColor(DEF_COLOR)); |
… | |
… | |
187 | win_y = win_y + ScreenHeight - h; |
249 | win_y = win_y + ScreenHeight - h; |
188 | |
250 | |
189 | XSelectInput(disp, root, ExposureMask|FocusChangeMask); |
251 | XSelectInput(disp, root, ExposureMask|FocusChangeMask); |
190 | } |
252 | } |
191 | |
253 | |
192 | char * |
254 | char * |
193 | detabificate (char *s) |
255 | detabificate (char *s) |
194 | { |
256 | { |
195 | char * out; |
257 | char * out; |
196 | int i, j; |
258 | int i, j; |
197 | |
259 | |
198 | out = malloc (8 * strlen (s) + 1); |
260 | out = malloc (8 * strlen (s) + 1); |
199 | |
261 | |
200 | for(i = 0, j = 0; s[i]; i++) |
262 | for(i = 0, j = 0; s[i]; i++) |
201 | { |
263 | { |
202 | if (s[i] == '\t') |
264 | if (s[i] == '\t') |
203 | do |
265 | do |
204 | out[j++] = ' '; |
266 | out[j++] = ' '; |
205 | while (j % 8); |
267 | while (j % 8); |
206 | else |
268 | else |
207 | out[j++] = s[i]; |
269 | out[j++] = s[i]; |
208 | } |
270 | } |
209 | |
271 | |
210 | out[j] = '\0'; |
272 | out[j] = '\0'; |
211 | return out; |
273 | return out; |
212 | } |
274 | } |
213 | |
275 | |
214 | /* |
276 | /* |
… | |
… | |
232 | maxy -= win_y - font_height; |
294 | maxy -= win_y - font_height; |
233 | |
295 | |
234 | for (lin = listlen; lin--;) |
296 | for (lin = listlen; lin--;) |
235 | { |
297 | { |
236 | char *temp; |
298 | char *temp; |
237 | |
299 | |
238 | offset -= font_height; |
300 | offset -= font_height; |
239 | |
301 | |
240 | if (offset < miny || offset > maxy) |
302 | if (offset < miny || offset > maxy) |
241 | continue; |
303 | continue; |
242 | |
304 | |
243 | #define LIN ((opt_reverse)?(listlen-lin-1):(lin)) |
305 | #define LIN ((opt_reverse)?(listlen-lin-1):(lin)) |
244 | temp = detabificate (lines[LIN].line); |
306 | temp = detabificate (lines[LIN].line); |
245 | |
307 | |
246 | if (opt_shade) |
308 | if (opt_shade) |
247 | { |
309 | { |
248 | XSetForeground (disp, WinGC, black_color); |
310 | XSetForeground (disp, WinGC, black_color); |
|
|
311 | #if 0 |
|
|
312 | XmbDrawString (disp, root, fontset, WinGC, win_x + 2, win_y + offset + 2, |
|
|
313 | temp, strlen (temp)); |
|
|
314 | #endif |
249 | XDrawString (disp, root, WinGC, win_x + 2, win_y + offset + 2, |
315 | XDrawString (disp, root, WinGC, win_x + 2, win_y + offset + 2, |
250 | temp, strlen (temp)); |
316 | temp, strlen (temp)); |
251 | } |
317 | } |
252 | |
318 | |
253 | XSetForeground (disp, WinGC, lines[LIN].color); |
319 | XSetForeground (disp, WinGC, lines[LIN].color); |
|
|
320 | #if 0 |
|
|
321 | XmbDrawString (disp, root, fontset, WinGC, win_x, win_y + offset, |
|
|
322 | temp, strlen (temp)); |
|
|
323 | #endif |
254 | XDrawString (disp, root, WinGC, win_x, win_y + offset, |
324 | XDrawString (disp, root, WinGC, win_x, win_y + offset, |
255 | temp, strlen (temp)); |
325 | temp, strlen (temp)); |
256 | |
|
|
257 | free (temp); |
326 | free (temp); |
258 | } |
327 | } |
259 | |
328 | |
260 | if (opt_frame) { |
329 | if (opt_frame) { |
261 | int bot_y = win_y + h + font_descent + 2; |
330 | int bot_y = win_y + h + font_descent + 2; |
… | |
… | |
291 | #endif |
360 | #endif |
292 | |
361 | |
293 | |
362 | |
294 | /* |
363 | /* |
295 | * This routine should read 'width' characters and not more. However, |
364 | * This routine should read 'width' characters and not more. However, |
296 | * we really want to read width + 1 charachters if the last char is a '\n', |
365 | * we really want to read width + 1 characters if the last char is a '\n', |
297 | * which we should remove afterwards. So, read width+1 chars and ungetc |
366 | * which we should remove afterwards. So, read width+1 chars and ungetc |
298 | * the last character if it's not a newline. This means 'string' must be |
367 | * the last character if it's not a newline. This means 'string' must be |
299 | * width + 2 wide! |
368 | * width + 2 wide! |
300 | */ |
369 | */ |
301 | int lineinput(char *string, int slen, FILE *f) |
370 | int lineinput(char *string, int slen, FILE *f) |
… | |
… | |
438 | strcpy(lines[lin].line, "~"); |
507 | strcpy(lines[lin].line, "~"); |
439 | lines[lin].color = GetColor(def_color); |
508 | lines[lin].color = GetColor(def_color); |
440 | } |
509 | } |
441 | |
510 | |
442 | if (!opt_noinitial) |
511 | if (!opt_noinitial) |
|
|
512 | { |
443 | while (lineinput(buf, buflen, loglist->fp) != 0) { |
513 | while (lineinput(buf, buflen, loglist->fp) != 0) { |
444 | SCROLL_UP(lines, listlen); |
514 | SCROLL_UP(lines, listlen); |
445 | /* print the next line */ |
515 | /* print the next line */ |
446 | strcpy(lines[listlen - 1].line, buf); |
516 | strcpy(lines[listlen - 1].line, buf); |
447 | } |
517 | } |
|
|
518 | |
|
|
519 | redraw (); |
|
|
520 | } |
448 | |
521 | |
449 | for (;;) { |
522 | for (;;) { |
450 | int need_update = 0; |
523 | int need_update = 0; |
451 | struct logfile_entry *current; |
524 | struct logfile_entry *current; |
452 | static struct logfile_entry *lastprinted = NULL; |
525 | static struct logfile_entry *lastprinted = NULL; |
… | |
… | |
550 | int i; |
623 | int i; |
551 | int opt_daemonize = 0; |
624 | int opt_daemonize = 0; |
552 | #if HAS_REGEX |
625 | #if HAS_REGEX |
553 | char *transform = NULL; |
626 | char *transform = NULL; |
554 | #endif |
627 | #endif |
|
|
628 | |
|
|
629 | setlocale (LC_CTYPE, ""); /* try to initialize the locale. */ |
555 | |
630 | |
556 | /* window needs to be initialized before colorlookups can be done */ |
631 | /* window needs to be initialized before colorlookups can be done */ |
557 | /* just a dummy to get the color lookups right */ |
632 | /* just a dummy to get the color lookups right */ |
558 | geom_mask = NoValue; |
633 | geom_mask = NoValue; |
559 | InitWindow(); |
634 | InitWindow(); |
… | |
… | |
768 | if (setsid() == -1) |
843 | if (setsid() == -1) |
769 | return -1; |
844 | return -1; |
770 | |
845 | |
771 | return 0; |
846 | return 0; |
772 | } |
847 | } |
773 | |
|
|