… | |
… | |
66 | int font_ascent; |
66 | int font_ascent; |
67 | FILE *fp; /* FILE struct associated with file */ |
67 | FILE *fp; /* FILE struct associated with file */ |
68 | ino_t inode; /* inode of the file opened */ |
68 | ino_t inode; /* inode of the file opened */ |
69 | off_t last_size; /* file size at the last check */ |
69 | off_t last_size; /* file size at the last check */ |
70 | unsigned long color; /* color to be used for printing */ |
70 | unsigned long color; /* color to be used for printing */ |
|
|
71 | const char *colorname; /* color name/string */ |
71 | int partial; /* true if the last line isn't complete */ |
72 | int partial; /* true if the last line isn't complete */ |
72 | int lastpartial; /* true if the previous output wasn't complete */ |
73 | int lastpartial; /* true if the previous output wasn't complete */ |
73 | struct line_node *last; /* last line we output */ |
74 | struct line_node *last; /* last line we output */ |
74 | int modified; /* true if line is modified & needs displaying */ |
75 | int modified; /* true if line is modified & needs displaying */ |
75 | }; |
76 | }; |
… | |
… | |
122 | struct timeval interval = { 2, 400000 }; |
123 | struct timeval interval = { 2, 400000 }; |
123 | |
124 | |
124 | /* command line options */ |
125 | /* command line options */ |
125 | int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename, |
126 | int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename, |
126 | opt_outline, opt_noflicker, opt_whole, opt_update, opt_wordwrap, |
127 | opt_outline, opt_noflicker, opt_whole, opt_update, opt_wordwrap, |
127 | opt_justify, geom_mask, reload = 0; |
128 | opt_justify, geom_mask, opt_minspace, reload; |
128 | const char *command = NULL, |
129 | const char *command = NULL, |
129 | *fontname = USE_FONT, *dispname = NULL, *def_color = DEF_COLOR, |
130 | *fontname = USE_FONT, *dispname = NULL, *def_color = DEF_COLOR, |
130 | *continuation = "|| ", *cont_color = DEF_CONT_COLOR; |
131 | *continuation = "|| ", *cont_color = DEF_CONT_COLOR; |
131 | |
132 | |
132 | struct logfile_entry *loglist = NULL, *loglist_tail = NULL; |
133 | struct logfile_entry *loglist = NULL, *loglist_tail = NULL; |
… | |
… | |
151 | /* prototypes */ |
152 | /* prototypes */ |
152 | void list_files (int); |
153 | void list_files (int); |
153 | void force_reopen (int); |
154 | void force_reopen (int); |
154 | void force_refresh (int); |
155 | void force_refresh (int); |
155 | void blank_window (int); |
156 | void blank_window (int); |
|
|
157 | #ifdef USE_TOON_GET_ROOT_WINDOW |
|
|
158 | Window ToonGetRootWindow(Display *, int, Window *); |
|
|
159 | #endif /* USE_TOON_GET_ROOT_WINDOW */ |
156 | |
160 | |
157 | void InitWindow (void); |
161 | void InitWindow (void); |
158 | unsigned long GetColor (const char *); |
162 | unsigned long GetColor (const char *); |
159 | void redraw (int); |
163 | void redraw (int); |
160 | void refresh (int, int, int, int); |
164 | void refresh (int, int, int, int); |
… | |
… | |
221 | fprintf (stderr, "can't allocate %s\n", ColorName); |
225 | fprintf (stderr, "can't allocate %s\n", ColorName); |
222 | |
226 | |
223 | return Color.pixel; |
227 | return Color.pixel; |
224 | } |
228 | } |
225 | |
229 | |
|
|
230 | #ifndef USE_TOON_GET_ROOT_WINDOW |
226 | static Window |
231 | static void |
227 | root_window (Display * display, int screen_number) |
232 | find_root_window (Display *display, int screen_number) |
228 | { |
233 | { |
|
|
234 | if (!root) |
|
|
235 | { |
229 | Atom SWM_VROOT = XInternAtom (display, "__SWM_VROOT", False); |
236 | Atom SWM_VROOT = XInternAtom (display, "__SWM_VROOT", False); |
|
|
237 | Atom NAUTILUS_DESKTOP_WINDOW_ID = XInternAtom (display, "NAUTILUS_DESKTOP_WINDOW_ID", False); |
230 | Window real_root_window = RootWindow (display, screen_number); |
238 | root = RootWindow (display, screen_number); |
231 | |
239 | |
232 | if (root) /* root window set via option */ |
|
|
233 | return root; |
|
|
234 | |
|
|
235 | if (SWM_VROOT != None) |
|
|
236 | { |
|
|
237 | Window unused, *windows; |
240 | Window unused, *windows = 0; |
238 | unsigned int count; |
241 | unsigned int count; |
239 | |
242 | |
|
|
243 | Atom type; |
|
|
244 | int format; |
|
|
245 | unsigned long nitems, bytes_after_return; |
|
|
246 | unsigned char *virtual_root_window; |
|
|
247 | |
|
|
248 | if (XGetWindowProperty (display, root, NAUTILUS_DESKTOP_WINDOW_ID, |
|
|
249 | 0, 1, False, XA_WINDOW, &type, &format, |
|
|
250 | &nitems, &bytes_after_return, |
|
|
251 | &virtual_root_window) == Success |
|
|
252 | && type == XA_WINDOW) |
|
|
253 | { |
|
|
254 | if (XQueryTree (display, *(Window *)virtual_root_window, &unused, &unused, &windows, &count)) |
|
|
255 | root = windows[count - 1]; |
|
|
256 | |
|
|
257 | XFree (virtual_root_window); |
|
|
258 | } |
240 | if (XQueryTree (display, real_root_window, &unused, &unused, &windows, &count)) |
259 | else if (XQueryTree (display, root, &unused, &unused, &windows, &count)) |
241 | { |
260 | { |
242 | int i; |
261 | int i; |
243 | |
262 | |
244 | for (i = 0; i < count; i++) |
263 | for (i = 0; i < count; i++) |
245 | { |
264 | { |
246 | Atom type; |
|
|
247 | int format; |
|
|
248 | unsigned long nitems, bytes_after_return; |
|
|
249 | unsigned char *virtual_root_window; |
|
|
250 | |
|
|
251 | if (XGetWindowProperty (display, windows[i], SWM_VROOT, |
265 | if (XGetWindowProperty (display, windows[i], SWM_VROOT, |
252 | 0, 1, False, XA_WINDOW, &type, &format, |
266 | 0, 1, False, XA_WINDOW, &type, &format, |
253 | &nitems, &bytes_after_return, |
267 | &nitems, &bytes_after_return, |
254 | &virtual_root_window) == Success) |
268 | &virtual_root_window) == Success |
|
|
269 | && type == XA_WINDOW) |
255 | { |
270 | { |
256 | if (type != None) |
|
|
257 | { |
|
|
258 | if (type == XA_WINDOW) |
|
|
259 | { |
|
|
260 | root = *(Window *)virtual_root_window; |
271 | root = *(Window *)virtual_root_window; |
261 | XFree (windows); |
|
|
262 | XFree (virtual_root_window); |
272 | XFree (virtual_root_window); |
263 | return root; |
|
|
264 | } |
|
|
265 | else |
|
|
266 | fprintf (stderr, "__SWM_VROOT property type mismatch"); |
|
|
267 | } |
273 | break; |
268 | } |
274 | } |
269 | else |
275 | } |
270 | fprintf (stderr, |
|
|
271 | "failed to get __SWM_VROOT property on window 0x%lx", |
|
|
272 | windows[i]); |
|
|
273 | } |
|
|
274 | |
276 | |
275 | if (count) |
|
|
276 | XFree (windows); |
277 | XFree (windows); |
277 | } |
278 | } |
278 | else |
279 | else |
279 | fprintf (stderr, "Can't query tree on root window 0x%lx", |
280 | fprintf (stderr, "Can't query tree on root window 0x%lx", root); |
280 | real_root_window); |
|
|
281 | } |
281 | } |
282 | else |
|
|
283 | /* This shouldn't happen. The Xlib documentation is wrong BTW. */ |
|
|
284 | fprintf (stderr, "Can't intern atom __SWM_VROOT"); |
|
|
285 | |
|
|
286 | return real_root_window; |
|
|
287 | } |
282 | } |
|
|
283 | #endif /* USE_TOON_GET_ROOT_WINDOW */ |
288 | |
284 | |
289 | void |
285 | void |
290 | InitWindow (void) |
286 | InitWindow (void) |
291 | { |
287 | { |
292 | XGCValues gcv; |
288 | XGCValues gcv; |
… | |
… | |
302 | |
298 | |
303 | screen = DefaultScreen (disp); |
299 | screen = DefaultScreen (disp); |
304 | ScreenHeight = DisplayHeight (disp, screen); |
300 | ScreenHeight = DisplayHeight (disp, screen); |
305 | ScreenWidth = DisplayWidth (disp, screen); |
301 | ScreenWidth = DisplayWidth (disp, screen); |
306 | |
302 | |
307 | root = root_window (disp, screen); |
303 | find_root_window (disp, screen); |
308 | |
304 | |
309 | gcm = GCBackground; |
305 | gcm = GCBackground; |
310 | gcv.graphics_exposures = True; |
306 | gcv.graphics_exposures = True; |
311 | WinGC = XCreateGC (disp, root, gcm, &gcv); |
307 | WinGC = XCreateGC (disp, root, gcm, &gcv); |
312 | XMapWindow (disp, root); |
308 | XMapWindow (disp, root); |
|
|
309 | |
313 | XSetForeground (disp, WinGC, GetColor (DEF_COLOR)); |
310 | XSetForeground (disp, WinGC, GetColor (DEF_COLOR)); |
314 | |
311 | |
315 | for (e = loglist; e; e = e->next) |
312 | for (e = loglist; e; e = e->next) |
316 | { |
313 | { |
317 | char **missing_charset_list; |
314 | char **missing_charset_list; |
… | |
… | |
340 | XFontSetExtents *xfe = XExtentsOfFontSet (e->fontset); |
337 | XFontSetExtents *xfe = XExtentsOfFontSet (e->fontset); |
341 | |
338 | |
342 | e->font_height = xfe->max_logical_extent.height; |
339 | e->font_height = xfe->max_logical_extent.height; |
343 | e->font_ascent = -xfe->max_logical_extent.y; |
340 | e->font_ascent = -xfe->max_logical_extent.y; |
344 | } |
341 | } |
|
|
342 | |
|
|
343 | if (e->font_height > height - effect_y_space) |
|
|
344 | { |
|
|
345 | fprintf(stderr, "\n the display isn't tall enough to display a single line in font '%s'\n", |
|
|
346 | e->fontname); |
|
|
347 | fprintf(stderr, "\n the geometry in use is %d pixels tall\n", height); |
|
|
348 | fprintf(stderr, "\n font '%s' is %d pixels tall\n", e->fontname, e->font_height); |
|
|
349 | if (effect_y_space) |
|
|
350 | fprintf(stderr, "\n the shade or outline options need an extra %d pixel%s of vertical space\n", |
|
|
351 | effect_y_space, effect_y_space == 1 ? "" : "s"); |
|
|
352 | fprintf(stderr, "\n"); |
|
|
353 | exit(1); |
|
|
354 | } |
345 | } |
355 | } |
346 | |
356 | |
347 | if (geom_mask & XNegative) |
357 | if (geom_mask & XNegative) |
348 | win_x = win_x + ScreenWidth - width; |
358 | win_x = win_x + ScreenWidth - width; |
349 | if (geom_mask & YNegative) |
359 | if (geom_mask & YNegative) |
350 | win_y = win_y + ScreenHeight - height; |
360 | win_y = win_y + ScreenHeight - height; |
351 | |
361 | |
352 | if (opt_outline) |
|
|
353 | { |
362 | { |
354 | /* adding outline increases the total width and height by 2 |
363 | struct logfile_entry *e; |
355 | pixels each, and offsets the text one pixel right and one |
364 | |
356 | pixel down */ |
365 | for (e = loglist; e; e = e->next) |
357 | effect_x_space = effect_y_space = 2; |
366 | e->color = GetColor (e->colorname); |
358 | effect_x_offset = effect_y_offset = 1; |
|
|
359 | } |
367 | } |
360 | else if (opt_shade) |
|
|
361 | { |
|
|
362 | /* adding a shadow increases the space used */ |
|
|
363 | effect_x_space = abs (SHADE_X); |
|
|
364 | effect_y_space = abs (SHADE_Y); |
|
|
365 | |
|
|
366 | /* if the shadow is to the right and below then we don't need |
|
|
367 | * to move the text to make space for it, but shadows to the left |
|
|
368 | * and above need accomodating */ |
|
|
369 | effect_x_offset = SHADE_X > 0 ? 0 : -SHADE_X; |
|
|
370 | effect_y_offset = SHADE_Y > 0 ? 0 : -SHADE_Y; |
|
|
371 | } |
|
|
372 | else |
|
|
373 | { |
|
|
374 | effect_x_space = effect_y_space = 0; |
|
|
375 | effect_x_offset = effect_y_offset = 0; |
|
|
376 | } |
|
|
377 | |
368 | |
378 | XSelectInput (disp, root, ExposureMask | FocusChangeMask); |
369 | XSelectInput (disp, root, ExposureMask | FocusChangeMask); |
379 | } |
370 | } |
380 | |
371 | |
381 | /* |
372 | /* |
… | |
… | |
569 | XClearArea (disp, root, win_x, win_y + offset - (opt_reverse ? 0 : space), |
560 | XClearArea (disp, root, win_x, win_y + offset - (opt_reverse ? 0 : space), |
570 | width + MARGIN_OF_ERROR, space, False); |
561 | width + MARGIN_OF_ERROR, space, False); |
571 | #endif |
562 | #endif |
572 | } |
563 | } |
573 | |
564 | |
|
|
565 | /* at least one of the lines must fit in the allocated area. we've |
|
|
566 | * already checked at initialisation time that all the fonts are small |
|
|
567 | * enough to fit at least one line in the display area, but assert it |
|
|
568 | * again here to be sure */ |
|
|
569 | assert(line != linelist); |
|
|
570 | |
574 | /* any lines that didn't just get looked at are never going to be, so break the chain */ |
571 | /* any lines that didn't just get looked at are never going to be, so break the chain */ |
575 | if (line) line->prev->next = 0; |
572 | if (line) line->prev->next = 0; |
576 | |
573 | |
577 | /* and throw them all away */ |
574 | /* and throw them all away */ |
578 | while (line) |
575 | while (line) |
… | |
… | |
1159 | continue; |
1156 | continue; |
1160 | } |
1157 | } |
1161 | |
1158 | |
1162 | /* print filename if any, and if last line was from |
1159 | /* print filename if any, and if last line was from |
1163 | * different file */ |
1160 | * different file */ |
1164 | if (!opt_nofilename && lastprinted != current && current->desc[0]) |
1161 | if (lastprinted != current) |
1165 | { |
1162 | { |
1166 | current->last = 0; |
1163 | current->last = 0; |
|
|
1164 | if (!opt_nofilename && current->desc[0]) |
|
|
1165 | { |
1167 | insert_new_line (xstrdup ("["), current); |
1166 | insert_new_line (xstrdup ("["), current); |
1168 | append_to_existing_line (xstrdup (current->desc), current); |
1167 | append_to_existing_line (xstrdup (current->desc), current); |
1169 | append_to_existing_line (xstrdup ("]"), current); |
1168 | append_to_existing_line (xstrdup ("]"), current); |
1170 | } |
1169 | } |
|
|
1170 | } |
1171 | |
1171 | |
1172 | /* if we're dealing with partial lines, and the last |
1172 | /* if we're dealing with partial lines, and the last |
1173 | * time we showed the line it wasn't finished ... */ |
1173 | * time we showed the line it wasn't finished ... */ |
1174 | if (!opt_whole && current->lastpartial) |
1174 | if (!opt_whole && current->lastpartial) |
1175 | { |
1175 | { |
… | |
… | |
1283 | char *transform = NULL; |
1283 | char *transform = NULL; |
1284 | #endif |
1284 | #endif |
1285 | |
1285 | |
1286 | setlocale (LC_CTYPE, ""); /* try to initialize the locale. */ |
1286 | setlocale (LC_CTYPE, ""); /* try to initialize the locale. */ |
1287 | |
1287 | |
1288 | /* window needs to be initialized before colorlookups can be done */ |
|
|
1289 | /* just a dummy to get the color lookups right */ |
|
|
1290 | geom_mask = NoValue; |
|
|
1291 | InitWindow (); |
|
|
1292 | |
|
|
1293 | for (i = 1; i < argc; i++) |
1288 | for (i = 1; i < argc; i++) |
1294 | { |
1289 | { |
1295 | const char *arg = argv[i]; |
1290 | const char *arg = argv[i]; |
1296 | |
1291 | |
1297 | if (arg[0] == '-' && arg[1] != '\0' && arg[1] != ',') |
1292 | if (arg[0] == '-' && arg[1] != '\0' && arg[1] != ',') |
… | |
… | |
1332 | } |
1327 | } |
1333 | else if (!strcmp (arg, "-shade")) |
1328 | else if (!strcmp (arg, "-shade")) |
1334 | opt_shade = 1; |
1329 | opt_shade = 1; |
1335 | else if (!strcmp (arg, "-outline")) |
1330 | else if (!strcmp (arg, "-outline")) |
1336 | opt_outline = 1; |
1331 | opt_outline = 1; |
|
|
1332 | else if (!strcmp (arg, "-minspace")) |
|
|
1333 | opt_minspace = 1; |
1337 | else if (!strcmp (arg, "-noflicker")) |
1334 | else if (!strcmp (arg, "-noflicker")) |
1338 | opt_noflicker = 1; |
1335 | opt_noflicker = 1; |
1339 | else if (!strcmp (arg, "-frame")) |
1336 | else if (!strcmp (arg, "-frame")) |
1340 | opt_frame = 1; |
1337 | opt_frame = 1; |
1341 | else if (!strcmp (arg, "-no-filename")) |
1338 | else if (!strcmp (arg, "-no-filename")) |
… | |
… | |
1425 | perror (fname), exit (1); |
1422 | perror (fname), exit (1); |
1426 | |
1423 | |
1427 | e->desc = xstrdup (desc); |
1424 | e->desc = xstrdup (desc); |
1428 | } |
1425 | } |
1429 | |
1426 | |
1430 | e->color = GetColor (fcolor); |
1427 | e->colorname = fcolor; |
1431 | e->partial = 0; |
1428 | e->partial = 0; |
1432 | e->fontname = fontname; |
1429 | e->fontname = fontname; |
1433 | e->last = NULL; |
1430 | e->last = NULL; |
1434 | e->next = NULL; |
1431 | e->next = NULL; |
1435 | |
1432 | |
… | |
… | |
1495 | } |
1492 | } |
1496 | else |
1493 | else |
1497 | printf ("compiled '%s' OK to %x\n", transform, (int)transformre); |
1494 | printf ("compiled '%s' OK to %x\n", transform, (int)transformre); |
1498 | } |
1495 | } |
1499 | #endif |
1496 | #endif |
|
|
1497 | |
|
|
1498 | if (opt_outline && !opt_minspace) |
|
|
1499 | { |
|
|
1500 | /* adding outline increases the total width and height by 2 |
|
|
1501 | pixels each, and offsets the text one pixel right and one |
|
|
1502 | pixel down */ |
|
|
1503 | effect_x_space = effect_y_space = 2; |
|
|
1504 | effect_x_offset = effect_y_offset = 1; |
|
|
1505 | } |
|
|
1506 | else if (opt_shade && !opt_minspace) |
|
|
1507 | { |
|
|
1508 | /* adding a shadow increases the space used */ |
|
|
1509 | effect_x_space = abs (SHADE_X); |
|
|
1510 | effect_y_space = abs (SHADE_Y); |
|
|
1511 | |
|
|
1512 | /* if the shadow is to the right and below then we don't need |
|
|
1513 | * to move the text to make space for it, but shadows to the left |
|
|
1514 | * and above need accomodating */ |
|
|
1515 | effect_x_offset = SHADE_X > 0 ? 0 : -SHADE_X; |
|
|
1516 | effect_y_offset = SHADE_Y > 0 ? 0 : -SHADE_Y; |
|
|
1517 | } |
|
|
1518 | else |
|
|
1519 | { |
|
|
1520 | effect_x_space = effect_y_space = 0; |
|
|
1521 | effect_x_offset = effect_y_offset = 0; |
|
|
1522 | } |
1500 | |
1523 | |
1501 | InitWindow (); |
1524 | InitWindow (); |
1502 | |
1525 | |
1503 | install_signal (SIGINT, blank_window); |
1526 | install_signal (SIGINT, blank_window); |
1504 | install_signal (SIGQUIT, blank_window); |
1527 | install_signal (SIGQUIT, blank_window); |
… | |
… | |
1587 | " -update allow updates to old partial lines\n" |
1610 | " -update allow updates to old partial lines\n" |
1588 | " -cont string to prefix continued partial lines with\n" |
1611 | " -cont string to prefix continued partial lines with\n" |
1589 | " defaults to \"|| \"\n" |
1612 | " defaults to \"|| \"\n" |
1590 | " -wordwrap wrap long lines at spaces to avoid breaking words\n" |
1613 | " -wordwrap wrap long lines at spaces to avoid breaking words\n" |
1591 | " -shade add shading to font\n" |
1614 | " -shade add shading to font\n" |
|
|
1615 | " -outline add black outline to font\n" |
|
|
1616 | " -minspace force minimum line spacing\n" |
1592 | " -noinitial don't display the last file lines on\n" |
1617 | " -noinitial don't display the last file lines on\n" |
1593 | " startup\n" |
1618 | " startup\n" |
1594 | " -i | -interval seconds interval between checks (fractional\n" |
1619 | " -i | -interval seconds interval between checks (fractional\n" |
1595 | " values o.k.). Default 2.4 seconds\n" |
1620 | " values o.k.). Default 2.4 seconds\n" |
1596 | " -V display version information and exit\n" |
1621 | " -V display version information and exit\n" |