ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/root-tail/root-tail.c
(Generate patch)

Comparing root-tail/root-tail.c (file contents):
Revision 1.11 by pcg, Fri Mar 26 13:14:54 2004 UTC vs.
Revision 1.25 by chris_moore, Sun Mar 28 03:53:48 2004 UTC

58}; 58};
59 59
60struct linematrix 60struct linematrix
61{ 61{
62 char *line; 62 char *line;
63 int len;
63 unsigned long color; 64 unsigned long color;
64}; 65};
65 66
66/* global variables */ 67/* global variables */
68struct linematrix *lines;
67int width = STD_WIDTH, height = STD_HEIGHT, listlen; 69int width = STD_WIDTH, height = STD_HEIGHT, listlen;
68int win_x = LOC_X, win_y = LOC_Y; 70int win_x = LOC_X, win_y = LOC_Y;
69int font_descent, font_height; 71int font_ascent, font_height;
70int do_reopen; 72int do_reopen;
71struct timeval interval = { 3, 0 }; 73struct timeval interval = { 2, 400000 };
72XFontSet fontset; 74XFontSet fontset;
73 75
74/* command line options */ 76/* command line options */
75int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename, 77int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename,
76 opt_whole, opt_update, geom_mask, reload = 0; 78 opt_outline, opt_noflicker, opt_whole, opt_update, opt_wordwrap,
79 geom_mask, reload = 0;
77const char *command = NULL, 80const char *command = NULL,
78 *fontname = USE_FONT, *dispname = NULL, *def_color = DEF_COLOR, 81 *fontname = USE_FONT, *dispname = NULL, *def_color = DEF_COLOR,
79 *continuation = "[+]"; 82 *continuation = "[+]";
80 83
81struct logfile_entry *loglist = NULL, *loglist_tail = NULL; 84struct logfile_entry *loglist = NULL, *loglist_tail = NULL;
102void blank_window (int); 105void blank_window (int);
103 106
104void InitWindow (void); 107void InitWindow (void);
105unsigned long GetColor (const char *); 108unsigned long GetColor (const char *);
106void redraw (void); 109void redraw (void);
107void refresh (struct linematrix *, int, int); 110void refresh (int, int, int);
108 111
109void transform_line (char *s); 112void transform_line (char *s);
110int lineinput (struct logfile_entry *); 113int lineinput (struct logfile_entry *);
111void reopen (void); 114void reopen (void);
112void check_open_files (void); 115void check_open_files (void);
113FILE *openlog (struct logfile_entry *); 116FILE *openlog (struct logfile_entry *);
114void main_loop (void); 117static void main_loop (void);
115 118
116void display_version (void); 119void display_version (void);
117void display_help (char *); 120void display_help (char *);
118void install_signal (int, void (*)(int)); 121void install_signal (int, void (*)(int));
119void *xstrdup (const char *); 122void *xstrdup (const char *);
138} 141}
139 142
140void 143void
141force_refresh (int dummy) 144force_refresh (int dummy)
142{ 145{
143 XClearArea (disp, root, win_x, win_y, width, height, False);
144 redraw (); 146 redraw ();
145} 147}
146 148
147void 149void
148blank_window (int dummy) 150blank_window (int dummy)
149{ 151{
150 XClearArea (disp, root, win_x, win_y, width, height, False); 152 XClearArea (disp, root, win_x - 2, win_y - 2, width + 5, height + 5, False);
151 XFlush (disp); 153 XFlush (disp);
152 exit (0); 154 exit (0);
153} 155}
154 156
155/* X related functions */ 157/* X related functions */
284 286
285 { 287 {
286 XFontSetExtents *xfe = XExtentsOfFontSet (fontset); 288 XFontSetExtents *xfe = XExtentsOfFontSet (fontset);
287 289
288 font_height = xfe->max_logical_extent.height; 290 font_height = xfe->max_logical_extent.height;
289 font_descent = xfe->max_logical_extent.y; 291 font_ascent = -xfe->max_logical_extent.y;
290 } 292 }
291 293
292 if (geom_mask & XNegative) 294 if (geom_mask & XNegative)
293 win_x = win_x + ScreenWidth - width; 295 win_x = win_x + ScreenWidth - width;
294 if (geom_mask & YNegative) 296 if (geom_mask & YNegative)
304 } 306 }
305 307
306 height = listlen * font_height; 308 height = listlen * font_height;
307 309
308 XSelectInput (disp, root, ExposureMask | FocusChangeMask); 310 XSelectInput (disp, root, ExposureMask | FocusChangeMask);
309}
310
311char *
312detabificate (char *s)
313{
314 char *out;
315 int i, j;
316
317 out = malloc (8 * strlen (s) + 1);
318
319 for (i = 0, j = 0; s[i]; i++)
320 {
321 if (s[i] == '\t')
322 do
323 out[j++] = ' ';
324 while (j % 8);
325 else
326 out[j++] = s[i];
327 }
328
329 out[j] = '\0';
330 return out;
331} 311}
332 312
333/* 313/*
334 * redraw does a complete redraw, rather than an update (i.e. the area 314 * redraw does a complete redraw, rather than an update (i.e. the area
335 * gets cleared first) 315 * gets cleared first)
336 * the rest is handled by regular refresh()'es 316 * the rest is handled by regular refresh()'es
337 */ 317 */
338void 318void
339redraw (void) 319redraw (void)
340{ 320{
341 XClearArea (disp, root, win_x, win_y, width, height, True); 321 XSetClipMask (disp, WinGC, None);
322 refresh (0, 32768, 1);
342} 323}
343 324
344/* Just redraw everything without clearing (i.e. after an EXPOSE event) */ 325/* Just redraw everything without clearing (i.e. after an EXPOSE event) */
345void 326void
346refresh (struct linematrix *lines, int miny, int maxy) 327refresh (int miny, int maxy, int clear)
347{ 328{
348 int lin; 329 int lin;
349 int offset = (listlen + 1) * font_height; 330 int offset = (listlen + 1) * font_height;
350 unsigned long black_color = GetColor ("black"); 331 unsigned long black_color = GetColor ("black");
351 332
352 miny -= win_y + font_height; 333 miny -= win_y + font_height;
353 maxy -= win_y - font_height; 334 maxy -= win_y - font_height;
354 335
336 if (clear && !opt_noflicker)
337 XClearArea (disp, root, win_x, win_y, width, height, False);
338
355 for (lin = listlen; lin--;) 339 for (lin = listlen; lin--;)
356 { 340 {
357 struct linematrix *line =
358 lines + (opt_reverse ? listlen - lin - 1 : lin); 341 struct linematrix *line = lines + (opt_reverse ? listlen - lin - 1 : lin);
359 342
360 offset -= font_height; 343 offset -= font_height;
361 344
362 if (offset < miny || offset > maxy) 345 if (offset < miny || offset > maxy)
363 continue; 346 continue;
364 347
348 if (clear && opt_noflicker)
349 XClearArea (disp, root, win_x, win_y + offset - font_ascent, width, font_height, False);
350
351 if (opt_outline)
352 {
353 XSetForeground (disp, WinGC, black_color);
354 XmbDrawString (disp, root, fontset, WinGC, win_x - 1,
355 win_y + offset + 1, line->line, line->len);
356 XmbDrawString (disp, root, fontset, WinGC, win_x + 1,
357 win_y + offset + 1, line->line, line->len);
358 XmbDrawString (disp, root, fontset, WinGC, win_x - 1,
359 win_y + offset - 1, line->line, line->len);
360 XmbDrawString (disp, root, fontset, WinGC, win_x + 1,
361 win_y + offset - 1, line->line, line->len);
362 }
365 if (opt_shade) 363 else if (opt_shade)
366 { 364 {
367 XSetForeground (disp, WinGC, black_color); 365 XSetForeground (disp, WinGC, black_color);
368 XmbDrawString (disp, root, fontset, WinGC, win_x + 2, 366 XmbDrawString (disp, root, fontset, WinGC, win_x + 2,
369 win_y + offset + 2, line->line, strlen (line->line)); 367 win_y + offset + 2, line->line, line->len);
370 } 368 }
371 369
372 XSetForeground (disp, WinGC, line->color); 370 XSetForeground (disp, WinGC, line->color);
373 XmbDrawString (disp, root, fontset, WinGC, win_x, win_y + offset, 371 XmbDrawString (disp, root, fontset, WinGC, win_x, win_y + offset,
374 line->line, strlen (line->line)); 372 line->line, line->len);
375 } 373 }
376 374
377 if (opt_frame) 375 if (opt_frame)
376 {
377 XSetForeground (disp, WinGC, GetColor (def_color));
378 XDrawRectangle (disp, root, WinGC, win_x, win_y, width, height); 378 XDrawRectangle (disp, root, WinGC, win_x - 2, win_y - 2, width + 4, height + 4);
379 }
379} 380}
380 381
381#if HAS_REGEX 382#if HAS_REGEX
382void 383void
383transform_line (char *s) 384transform_line (char *s)
403 } 404 }
404 } 405 }
405} 406}
406#endif 407#endif
407 408
409char *
410concat_line (const char *p1, const char *p2)
411{
412 int l1 = p1 ? strlen (p1) : 0;
413 int l2 = strlen (p2);
414 char *r = xmalloc (l1 + l2 + 1);
415
416 memcpy (r, p1, l1);
417 memcpy (r + l1, p2, l2);
418 r[l1 + l2] = 0;
419
420 return r;
421}
408 422
409/* 423/*
410 * This routine should read 'width' characters and not more. However, 424 * This routine should read a single line, no matter how long.
411 * we really want to read width + 1 characters if the last char is a '\n',
412 * which we should remove afterwards. So, read width+1 chars and ungetc
413 * the last character if it's not a newline. This means 'string' must be
414 * width + 2 wide!
415 */ 425 */
416int 426int
417lineinput (struct logfile_entry *logfile) 427lineinput (struct logfile_entry *logfile)
418{ 428{
419 char *string = logfile->buf; 429 char buff[1024], *p = buff;
420 int slen = width + 2; 430 int ch;
421 FILE *f = logfile->fp; 431 int ofs = logfile->buf ? strlen (logfile->buf) : 0;
422
423 int len = strlen (string);
424 int partial = logfile->partial;
425 432
426 do 433 do
427 { 434 {
428 if (fgets (string + len, slen - len, f) == NULL) /* EOF or Error */ 435 ch = fgetc (logfile->fp);
429 return 0;
430 436
431 len = strlen (string); 437 if (ch == '\n' || ch == EOF)
432 } 438 break;
433 while (len == 0); 439 else if (ch == '\r')
434 440 continue; /* skip */
435 logfile->partial = 0; 441 else if (ch == '\t')
436 442 {
437 if (string[len - 1] == '\n') 443 do
438 /* if the string ends in a newline, delete the newline */ 444 {
439 string[len - 1] = '\0'; /* erase newline */ 445 *p++ = ' ';
440 else if (len >= slen - 1) 446 ofs++;
447 }
448 while (ofs & 7);
449 }
450 else
451 {
452 *p++ = ch;
453 ofs++;
454 }
441 { 455 }
442 /* otherwise if we've read one too many characters, un-read the last one and delete it */ 456 while (p < buff + (sizeof buff) - 8 - 1);
443 ungetc (string[len - 1], f); 457
444 string[len - 1] = '\0'; 458 if (p == buff && ch == EOF)
445 }
446 else if (opt_whole)
447 return 0; 459 return 0;
448 else 460
461 *p = 0;
462
463 p = concat_line (logfile->buf, buff);
464 free (logfile->buf); logfile->buf = p;
465
466 logfile->lastpartial = logfile->partial;
467 /* there are 3 ways we could have exited the loop: reading '\n',
468 * reaching EOF, or filling the buffer; the 2nd and 3rd of these
469 * both result in a partial line */
449 logfile->partial = 1; 470 logfile->partial = ch != '\n';
471
472 if (logfile->partial && opt_whole)
473 return 0;
450 474
451#if HAS_REGEX 475#if HAS_REGEX
452 transform_line (string); 476 transform_line (logfile->buf);
453#endif 477#endif
454 logfile->lastpartial = partial;
455 return len; 478 return 1;
456} 479}
457 480
458/* input: reads file->fname 481/* input: reads file->fname
459 * output: fills file->fp, file->inode 482 * output: fills file->fp, file->inode
460 * returns file->fp 483 * returns file->fp
524 { /* file missing? */ 547 { /* file missing? */
525 sleep (1); 548 sleep (1);
526 if (e->fp) 549 if (e->fp)
527 fclose (e->fp); 550 fclose (e->fp);
528 if (openlog (e) == NULL) 551 if (openlog (e) == NULL)
529 break; 552 continue;
530 } 553 }
531 554
555 /* HACK this - stats can be uninitialised here (if the file
556 * didn't exist when stat() was called, but was recreated during
557 * the sleep(1)) */
532 if (stats.st_ino != e->inode) 558 if (stats.st_ino != e->inode)
533 { /* file renamed? */ 559 { /* file renamed? */
534 if (e->fp) 560 if (e->fp)
535 fclose (e->fp); 561 fclose (e->fp);
536 if (openlog (e) == NULL) 562 if (openlog (e) == NULL)
537 break; 563 continue;
538 } 564 }
539 565
540 if (stats.st_size < e->last_size) 566 if (stats.st_size < e->last_size)
541 { /* file truncated? */ 567 { /* file truncated? */
542 fseek (e->fp, 0, SEEK_SET); 568 fseek (e->fp, 0, SEEK_SET);
543 e->last_size = stats.st_size; 569 e->last_size = stats.st_size;
544 } 570 }
545 } 571 }
546} 572}
547 573
548#define SCROLL_UP(lines, listlen) \ 574/*
549{ \ 575 * insert a single physical line (that must be short enough to fit)
550 int cur_line; \ 576 * at position "idx" by pushing up lines above it. the caller
551 struct logfile_entry *current; \ 577 * MUST then fill in lines[idx] with valid data.
578 */
579static void
580insert_line (int idx)
581{
582 int cur_line;
583 struct logfile_entry *current;
584
585 free (lines[0].line);
586
552 for (cur_line = 0; cur_line < (listlen - 1); cur_line++) { \ 587 for (cur_line = 0; cur_line < idx; cur_line++)
553 strcpy(lines[cur_line].line, lines[cur_line + 1].line); \
554 lines[cur_line].color = lines[cur_line + 1].color; \ 588 lines[cur_line] = lines[cur_line + 1];
555 } \ 589
556 for (current = loglist; current; current = current->next) \ 590 for (current = loglist; current; current = current->next)
557 if (current->partial && current->index) \ 591 if (current->index <= idx)
558 current->index--; \ 592 current->index--;
559} 593}
560 594
561void 595/*
596 * remove a single physical line at position "idx" by moving the lines above it
597 * down and inserting a "~" line at the top.
598 */
599static void
600delete_line (int idx)
601{
602 int cur_line;
603 struct logfile_entry *current;
604
605 for (cur_line = idx; cur_line > 0; cur_line--)
606 lines[cur_line] = lines[cur_line - 1];
607
608 lines[0].line = strdup ("~");
609
610 for (current = loglist; current; current = current->next)
611 if (current->index >= 0 && current->index <= idx)
612 current->index++;
613}
614
615/*
616 * takes a logical log file line and splits it into multiple physical
617 * screen lines by splitting it whenever a part becomes too long.
618 * lal lines will be inserted at position "idx".
619 */
620static void
621split_line (int idx, const char *str, unsigned long color)
622{
623 int l = strlen (str);
624 const char *p = str;
625
626 do
627 {
628 const char *beg = p;
629 int w = 0, wrapped = 0;
630 const char *break_p = NULL;
631
632 while (*p)
633 {
634 /* find the length in bytes of the next multibyte character */
635 int len = mblen (p, l);
636 if (len <= 0)
637 len = 1; /* ignore (don't skip) illegal character sequences */
638
639 /* find the width in pixels of the next character */
640 int cw = XmbTextEscapement (fontset, p, len);
641 if (cw + w >= width)
642 {
643 wrapped = 1;
644 break;
645 }
646
647 if (opt_wordwrap && len == 1 && p[0] == ' ')
648 break_p = p;
649
650 w += cw;
651 p += len;
652 l -= len;
653 }
654
655 /* if we're wrapping at spaces, and the line is long enough to
656 * wrap, and we've seen a space already, and the space wasn't
657 * the first character on the line, then wrap at the space */
658 if (opt_wordwrap && wrapped && break_p && break_p != beg)
659 {
660 l += p - break_p;
661 p = break_p;
662 }
663
664 {
665 char *s = xmalloc (p - beg + 1);
666 memcpy (s, beg, p - beg);
667 s[p - beg] = 0;
668 insert_line (idx);
669 lines[idx].line = s;
670 lines[idx].len = p - beg;
671 lines[idx].color = color;
672 }
673
674 /* if we wrapped at a space, don't display the space */
675 if (opt_wordwrap && wrapped && break_p && break_p != beg)
676 {
677 l--;
678 p++;
679 }
680 }
681 while (l);
682}
683
684/*
685 * append something to an existing physical line. this is done
686 * by deleting the file on-screen, concatenating the new data to it
687 * and splitting it again.
688 */
689static void
690append_line (int idx, const char *str)
691{
692 unsigned long color = lines[idx].color;
693 char *old = lines[idx].line;
694 char *new = concat_line (old, str);
695
696 free (old);
697
698 delete_line (idx);
699 split_line (idx, new, color);
700}
701
702static void
562main_loop (void) 703main_loop (void)
563{ 704{
564 struct linematrix *lines = xmalloc (sizeof (struct linematrix) * listlen); 705 lines = xmalloc (sizeof (struct linematrix) * listlen);
565 int lin, miny, maxy; 706 int lin;
566 time_t lastreload; 707 time_t lastreload;
567 Region region = XCreateRegion (); 708 Region region = XCreateRegion ();
568 XEvent xev; 709 XEvent xev;
569 struct logfile_entry *lastprinted = NULL; 710 struct logfile_entry *lastprinted = NULL;
570 struct logfile_entry *current; 711 struct logfile_entry *current;
712 int need_update = 1;
571 713
572 maxy = 0;
573 miny = win_y + height;
574 lastreload = time (NULL); 714 lastreload = time (NULL);
575 715
576 /* Initialize linematrix */ 716 /* Initialize linematrix */
577 for (lin = 0; lin < listlen; lin++) 717 for (lin = 0; lin < listlen; lin++)
578 { 718 {
579 lines[lin].line = xmalloc (width + 2); 719 lines[lin].line = strdup ("~");
580 strcpy (lines[lin].line, "~"); 720 lines[lin].len = 1;
581 lines[lin].color = GetColor (def_color); 721 lines[lin].color = GetColor (def_color);
582 } 722 }
583 723
584 /* show the display full of empty lines ("~") in case the first
585 * time around the loop doesn't produce any output, as it won't if
586 * either (a) -noinitial is set or (b) all the files are currently
587 * empty */
588 redraw ();
589
590 for (;;) 724 for (;;)
591 { 725 {
592 int need_update = 0;
593
594 /* read logs */ 726 /* read logs */
595 for (current = loglist; current; current = current->next) 727 for (current = loglist; current; current = current->next)
596 { 728 {
597 if (!current->fp) 729 if (!current->fp)
598 continue; /* skip missing files */ 730 continue; /* skip missing files */
599 731
600 clearerr (current->fp); 732 clearerr (current->fp);
601 733
602 while (lineinput (current) != 0) 734 while (lineinput (current))
603 { 735 {
736 need_update = 1;
604 /* if we're trying to update old partial lines in 737 /* if we're trying to update old partial lines in
605 * place, and the last time this file was updated the 738 * place, and the last time this file was updated the
606 * output was partial, and that partial line is not 739 * output was partial, and that partial line is not
607 * too close to the top of the screen, then update 740 * too close to the top of the screen, then update
608 * that partial line */ 741 * that partial line */
609 if (opt_update && current->lastpartial && current->index >= 3) 742 if (opt_update && current->lastpartial && current->index >= 0)
610 { 743 {
611 int old_len = strlen (lines[current->index].line); 744 int idx = current->index;
612 int new_len = strlen (current->buf); 745 append_line (idx, current->buf);
613 int space_on_old_line = width / font_width - old_len; //D 746 current->index = idx;
614 747 free (current->buf), current->buf = 0;
615 strncat (lines[current->index].line, current->buf,
616 width - old_len);
617 /* if we can't fit the whole update into the old
618 * partial line then we're going to have to print
619 * the rest of it at the bottom on the screen */
620 if (new_len > space_on_old_line)
621 {
622 /* strcpy() doesn't like the strings to
623 * overlap in memory, but memmove() doesn't
624 * care */
625 memmove (current->buf,
626 current->buf + space_on_old_line,
627 new_len - space_on_old_line + 1);
628 }
629 else
630 {
631 need_update = 1;
632 strcpy (current->buf, "");
633 continue; 748 continue;
634 }
635 } 749 }
636 750
637 /* print filename if any, and if last line was from 751 /* print filename if any, and if last line was from
638 * different file */ 752 * different file */
639 if (!opt_nofilename &&
640 lastprinted != current && current->desc[0]) 753 if (!opt_nofilename && lastprinted != current && current->desc[0])
641 { 754 {
642 SCROLL_UP (lines, listlen); 755 char buf[1024]; /* HACK */
643 sprintf (lines[listlen - 1].line, "[%s]", current->desc); 756 snprintf (buf, sizeof (buf), "[%s]", current->desc);
644 lines[listlen - 1].color = current->color; 757 split_line (listlen - 1, buf, current->color);
645 } 758 }
646 759
647 /* if this is the same file we showed last, and the 760 /* if this is the same file we showed last, and the
648 * last time we showed it, it wasn't finished, then 761 * last time we showed it, it wasn't finished, then
649 * append to the last line shown */ 762 * append to the last line shown */
650 if (lastprinted == current && current->lastpartial) 763 if (lastprinted == current && current->lastpartial)
651 { 764 append_line (listlen - 1, current->buf);
652 int old_len = strlen (lines[listlen - 1].line);
653 int new_len = strlen (current->buf);
654 strncat (lines[listlen - 1].line, current->buf,
655 width - old_len);
656 /* if it doesn't all fit, then put the part that
657 * doesn't fit on a new line */
658 if (new_len > width - old_len)
659 {
660 SCROLL_UP (lines, listlen);
661 strcpy (lines[listlen - 1].line,
662 current->buf + width - old_len);
663 }
664 /* show the 'continuation' string because we've got a
665 * continued partial line, but we weren't able to
666 * append it to the old displayed partial line */
667 }
668 else if (current->lastpartial) 765 else if (current->lastpartial)
669 { 766 {
670 int old_len = strlen (continuation); 767 split_line (listlen - 1, continuation, current->color);
671 int new_len = strlen (current->buf);
672 SCROLL_UP (lines, listlen);
673 strcpy (lines[listlen - 1].line, continuation);
674 strncat (lines[listlen - 1].line, current->buf, 768 append_line (listlen - 1, current->buf);
675 width - old_len); 769 }
676 /* it might not fit, now that we've displayed the
677 * continuation string, so we may need to 'wrap' it */
678 if (new_len > width - old_len)
679 {
680 SCROLL_UP (lines, listlen);
681 strcpy (lines[listlen - 1].line,
682 current->buf + width - old_len);
683 }
684 }
685 else 770 else
686 { 771 split_line (listlen - 1, current->buf, current->color);
687 SCROLL_UP (lines, listlen);
688 strcpy (lines[listlen - 1].line, current->buf);
689 }
690 772
691 /* we've shown the line now. clear the buffer for the next line */ 773 free (current->buf), current->buf = 0;
692 strcpy (current->buf, "");
693 current->index = listlen - 1; 774 current->index = listlen - 1;
694 lines[listlen - 1].color = current->color;
695
696 lastprinted = current; 775 lastprinted = current;
697 need_update = 1;
698 } 776 }
699 } 777 }
700 778
701 if (need_update) 779 if (need_update)
780 {
702 redraw (); 781 redraw ();
782 need_update = 0;
783 }
703 else 784 else
704 { 785 {
705 XFlush (disp); 786 XFlush (disp);
706 787
707 if (!XPending (disp)) 788 if (!XPending (disp))
733 814
734 r.x = xev.xexpose.x; 815 r.x = xev.xexpose.x;
735 r.y = xev.xexpose.y; 816 r.y = xev.xexpose.y;
736 r.width = xev.xexpose.width; 817 r.width = xev.xexpose.width;
737 r.height = xev.xexpose.height; 818 r.height = xev.xexpose.height;
819
738 XUnionRectWithRegion (&r, region, region); 820 XUnionRectWithRegion (&r, region, region);
739 if (miny > r.y)
740 miny = r.y;
741 if (maxy < r.y + r.height)
742 maxy = r.y + r.height;
743 } 821 }
744 break; 822 break;
745 default: 823 default:
746#ifdef DEBUGMODE 824#ifdef DEBUGMODE
747 fprintf (stderr, "PANIC! Unknown event %d\n", xev.type); 825 fprintf (stderr, "PANIC! Unknown event %d\n", xev.type);
760 lastreload = time (NULL); 838 lastreload = time (NULL);
761 } 839 }
762 840
763 if (!XEmptyRegion (region)) 841 if (!XEmptyRegion (region))
764 { 842 {
843 XRectangle r;
844
765 XSetRegion (disp, WinGC, region); 845 XSetRegion (disp, WinGC, region);
846 XClipBox (region, &r);
766 847
767 refresh (lines, miny, maxy); 848 refresh (r.y, r.y + r.height, 0);
849
768 XDestroyRegion (region); 850 XDestroyRegion (region);
769 region = XCreateRegion (); 851 region = XCreateRegion ();
770 maxy = 0;
771 miny = win_y + height;
772 } 852 }
773 } 853 }
774} 854}
775 855
776 856
825 reload = atoi (argv[++i]); 905 reload = atoi (argv[++i]);
826 command = argv[++i]; 906 command = argv[++i];
827 } 907 }
828 else if (!strcmp (arg, "-shade")) 908 else if (!strcmp (arg, "-shade"))
829 opt_shade = 1; 909 opt_shade = 1;
910 else if (!strcmp (arg, "-outline"))
911 opt_outline = 1;
912 else if (!strcmp (arg, "-noflicker"))
913 opt_noflicker = 1;
830 else if (!strcmp (arg, "-frame")) 914 else if (!strcmp (arg, "-frame"))
831 opt_frame = 1; 915 opt_frame = 1;
832 else if (!strcmp (arg, "-no-filename")) 916 else if (!strcmp (arg, "-no-filename"))
833 opt_nofilename = 1; 917 opt_nofilename = 1;
834 else if (!strcmp (arg, "-reverse")) 918 else if (!strcmp (arg, "-reverse"))
837 opt_whole = 1; 921 opt_whole = 1;
838 else if (!strcmp (arg, "-partial")) 922 else if (!strcmp (arg, "-partial"))
839 opt_partial = 1; 923 opt_partial = 1;
840 else if (!strcmp (arg, "-update")) 924 else if (!strcmp (arg, "-update"))
841 opt_update = opt_partial = 1; 925 opt_update = opt_partial = 1;
926 else if (!strcmp (arg, "-wordwrap"))
927 opt_wordwrap = 1;
842 else if (!strcmp (arg, "-color")) 928 else if (!strcmp (arg, "-color"))
843 def_color = argv[++i]; 929 def_color = argv[++i];
844 else if (!strcmp (arg, "-noinitial")) 930 else if (!strcmp (arg, "-noinitial"))
845 opt_noinitial = 1; 931 opt_noinitial = 1;
846 else if (!strcmp (arg, "-id")) 932 else if (!strcmp (arg, "-id"))
880 desc = p + 1; 966 desc = p + 1;
881 } 967 }
882 } 968 }
883 969
884 e = xmalloc (sizeof (struct logfile_entry)); 970 e = xmalloc (sizeof (struct logfile_entry));
971 e->partial = 0;
972 e->buf = 0;
973 e->index = -1;
974
885 if (arg[0] == '-' && arg[1] == '\0') 975 if (arg[0] == '-' && arg[1] == '\0')
886 { 976 {
887 if ((e->fp = fdopen (0, "r")) == NULL) 977 if ((e->fp = fdopen (0, "r")) == NULL)
888 perror ("fdopen"), exit (1); 978 perror ("fdopen"), exit (1);
889 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0) 979 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0)
907 memcpy (e->desc, desc, l); 997 memcpy (e->desc, desc, l);
908 *(e->desc + l) = '\0'; 998 *(e->desc + l) = '\0';
909 } 999 }
910 1000
911 e->color = GetColor (fcolor); 1001 e->color = GetColor (fcolor);
912 e->buf = xmalloc (width + 2);
913 e->partial = 0; 1002 e->partial = 0;
914 e->buf[0] = '\0';
915 e->next = NULL; 1003 e->next = NULL;
916 1004
917 if (!loglist) 1005 if (!loglist)
918 loglist = e; 1006 loglist = e;
919 if (loglist_tail) 1007 if (loglist_tail)
1011 while ((p = malloc (size)) == NULL) 1099 while ((p = malloc (size)) == NULL)
1012 { 1100 {
1013 fprintf (stderr, "Memory exausted."); 1101 fprintf (stderr, "Memory exausted.");
1014 sleep (10); 1102 sleep (10);
1015 } 1103 }
1104
1016 return p; 1105 return p;
1017} 1106}
1018 1107
1019void 1108void
1020display_help (char *myname) 1109display_help (char *myname)
1030 " -reverse print new lines at the top\n" 1119 " -reverse print new lines at the top\n"
1031 " -whole wait for \\n before showing a line\n" 1120 " -whole wait for \\n before showing a line\n"
1032 " -partial show lines even if they don't end with a \\n\n" 1121 " -partial show lines even if they don't end with a \\n\n"
1033 " -update allow updates to old partial lines\n" 1122 " -update allow updates to old partial lines\n"
1034 " -cont string to prefix continued partial lines with\n" 1123 " -cont string to prefix continued partial lines with\n"
1124 " -wordwrap wrap long lines at spaces to avoid breaking words\n"
1035 " defaults to \"[+]\"\n" 1125 " defaults to \"[+]\"\n"
1036 " -shade add shading to font\n" 1126 " -shade add shading to font\n"
1037 " -noinitial don't display the last file lines on\n" 1127 " -noinitial don't display the last file lines on\n"
1038 " startup\n" 1128 " startup\n"
1039 " -i | -interval seconds interval between checks (fractional\n" 1129 " -i | -interval seconds interval between checks (fractional\n"
1040 " values o.k.). Default 3 seconds\n" 1130 " values o.k.). Default 2.4 seconds\n"
1041 " -V display version information and exit\n" 1131 " -V display version information and exit\n"
1042 "\n"); 1132 "\n");
1043 printf ("Example:\n%s -g 80x25+100+50 -font fixed /var/log/messages,green " 1133 printf ("Example:\n%s -g 80x25+100+50 -font fixed /var/log/messages,green "
1044 "/var/log/secure,red,'ALERT'\n", myname); 1134 "/var/log/secure,red,'ALERT'\n", myname);
1045 exit (0); 1135 exit (0);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines