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.24 by chris_moore, Sun Mar 28 03:28:54 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;
449 logfile->partial = 1; 467 logfile->partial = ch == EOF;
468
469 if (logfile->partial && opt_whole)
470 return 0;
450 471
451#if HAS_REGEX 472#if HAS_REGEX
452 transform_line (string); 473 transform_line (logfile->buf);
453#endif 474#endif
454 logfile->lastpartial = partial;
455 return len; 475 return 1;
456} 476}
457 477
458/* input: reads file->fname 478/* input: reads file->fname
459 * output: fills file->fp, file->inode 479 * output: fills file->fp, file->inode
460 * returns file->fp 480 * returns file->fp
524 { /* file missing? */ 544 { /* file missing? */
525 sleep (1); 545 sleep (1);
526 if (e->fp) 546 if (e->fp)
527 fclose (e->fp); 547 fclose (e->fp);
528 if (openlog (e) == NULL) 548 if (openlog (e) == NULL)
529 break; 549 continue;
530 } 550 }
531 551
552 /* HACK this - stats can be uninitialised here (if the file
553 * didn't exist when stat() was called, but was recreated during
554 * the sleep(1)) */
532 if (stats.st_ino != e->inode) 555 if (stats.st_ino != e->inode)
533 { /* file renamed? */ 556 { /* file renamed? */
534 if (e->fp) 557 if (e->fp)
535 fclose (e->fp); 558 fclose (e->fp);
536 if (openlog (e) == NULL) 559 if (openlog (e) == NULL)
537 break; 560 continue;
538 } 561 }
539 562
540 if (stats.st_size < e->last_size) 563 if (stats.st_size < e->last_size)
541 { /* file truncated? */ 564 { /* file truncated? */
542 fseek (e->fp, 0, SEEK_SET); 565 fseek (e->fp, 0, SEEK_SET);
543 e->last_size = stats.st_size; 566 e->last_size = stats.st_size;
544 } 567 }
545 } 568 }
546} 569}
547 570
548#define SCROLL_UP(lines, listlen) \ 571/*
549{ \ 572 * insert a single physical line (that must be short enough to fit)
550 int cur_line; \ 573 * at position "idx" by pushing up lines above it. the caller
551 struct logfile_entry *current; \ 574 * MUST then fill in lines[idx] with valid data.
575 */
576static void
577insert_line (int idx)
578{
579 int cur_line;
580 struct logfile_entry *current;
581
582 free (lines[0].line);
583
552 for (cur_line = 0; cur_line < (listlen - 1); cur_line++) { \ 584 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; \ 585 lines[cur_line] = lines[cur_line + 1];
555 } \ 586
556 for (current = loglist; current; current = current->next) \ 587 for (current = loglist; current; current = current->next)
557 if (current->partial && current->index) \ 588 if (current->index <= idx)
558 current->index--; \ 589 current->index--;
559} 590}
560 591
561void 592/*
593 * remove a single physical line at position "idx" by moving the lines above it
594 * down and inserting a "~" line at the top.
595 */
596static void
597delete_line (int idx)
598{
599 int cur_line;
600 struct logfile_entry *current;
601
602 for (cur_line = idx; cur_line > 0; cur_line--)
603 lines[cur_line] = lines[cur_line - 1];
604
605 lines[0].line = strdup ("~");
606
607 for (current = loglist; current; current = current->next)
608 if (current->index >= 0 && current->index <= idx)
609 current->index++;
610}
611
612/*
613 * takes a logical log file line and splits it into multiple physical
614 * screen lines by splitting it whenever a part becomes too long.
615 * lal lines will be inserted at position "idx".
616 */
617static void
618split_line (int idx, const char *str, unsigned long color)
619{
620 int l = strlen (str);
621 const char *p = str;
622
623 do
624 {
625 const char *beg = p;
626 int w = 0, wrapped = 0;
627 const char *break_p = NULL;
628
629 while (*p)
630 {
631 /* find the length in bytes of the next multibyte character */
632 int len = mblen (p, l);
633 if (len <= 0)
634 len = 1; /* ignore (don't skip) illegal character sequences */
635
636 /* find the width in pixels of the next character */
637 int cw = XmbTextEscapement (fontset, p, len);
638 if (cw + w >= width)
639 {
640 wrapped = 1;
641 break;
642 }
643
644 if (opt_wordwrap && len == 1 && p[0] == ' ')
645 break_p = p;
646
647 w += cw;
648 p += len;
649 l -= len;
650 }
651
652 /* if we're wrapping at spaces, and the line is long enough to
653 * wrap, and we've seen a space already, and the space wasn't
654 * the first character on the line, then wrap at the space */
655 if (opt_wordwrap && wrapped && break_p && break_p != beg)
656 {
657 l += p - break_p;
658 p = break_p;
659 }
660
661 {
662 char *s = xmalloc (p - beg + 1);
663 memcpy (s, beg, p - beg);
664 s[p - beg] = 0;
665 insert_line (idx);
666 lines[idx].line = s;
667 lines[idx].len = p - beg;
668 lines[idx].color = color;
669 }
670
671 /* if we wrapped at a space, don't display the space */
672 if (opt_wordwrap && wrapped && break_p && break_p != beg)
673 {
674 l--;
675 p++;
676 }
677 }
678 while (l);
679}
680
681/*
682 * append something to an existing physical line. this is done
683 * by deleting the file on-screen, concatenating the new data to it
684 * and splitting it again.
685 */
686static void
687append_line (int idx, const char *str)
688{
689 unsigned long color = lines[idx].color;
690 char *old = lines[idx].line;
691 char *new = concat_line (old, str);
692
693 free (old);
694
695 delete_line (idx);
696 split_line (idx, new, color);
697}
698
699static void
562main_loop (void) 700main_loop (void)
563{ 701{
564 struct linematrix *lines = xmalloc (sizeof (struct linematrix) * listlen); 702 lines = xmalloc (sizeof (struct linematrix) * listlen);
565 int lin, miny, maxy; 703 int lin;
566 time_t lastreload; 704 time_t lastreload;
567 Region region = XCreateRegion (); 705 Region region = XCreateRegion ();
568 XEvent xev; 706 XEvent xev;
569 struct logfile_entry *lastprinted = NULL; 707 struct logfile_entry *lastprinted = NULL;
570 struct logfile_entry *current; 708 struct logfile_entry *current;
709 int need_update = 1;
571 710
572 maxy = 0;
573 miny = win_y + height;
574 lastreload = time (NULL); 711 lastreload = time (NULL);
575 712
576 /* Initialize linematrix */ 713 /* Initialize linematrix */
577 for (lin = 0; lin < listlen; lin++) 714 for (lin = 0; lin < listlen; lin++)
578 { 715 {
579 lines[lin].line = xmalloc (width + 2); 716 lines[lin].line = strdup ("~");
580 strcpy (lines[lin].line, "~"); 717 lines[lin].len = 1;
581 lines[lin].color = GetColor (def_color); 718 lines[lin].color = GetColor (def_color);
582 } 719 }
583 720
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 (;;) 721 for (;;)
591 { 722 {
592 int need_update = 0;
593
594 /* read logs */ 723 /* read logs */
595 for (current = loglist; current; current = current->next) 724 for (current = loglist; current; current = current->next)
596 { 725 {
597 if (!current->fp) 726 if (!current->fp)
598 continue; /* skip missing files */ 727 continue; /* skip missing files */
599 728
600 clearerr (current->fp); 729 clearerr (current->fp);
601 730
602 while (lineinput (current) != 0) 731 while (lineinput (current))
603 { 732 {
733 need_update = 1;
604 /* if we're trying to update old partial lines in 734 /* if we're trying to update old partial lines in
605 * place, and the last time this file was updated the 735 * place, and the last time this file was updated the
606 * output was partial, and that partial line is not 736 * output was partial, and that partial line is not
607 * too close to the top of the screen, then update 737 * too close to the top of the screen, then update
608 * that partial line */ 738 * that partial line */
609 if (opt_update && current->lastpartial && current->index >= 3) 739 if (opt_update && current->lastpartial && current->index >= 0)
610 { 740 {
611 int old_len = strlen (lines[current->index].line); 741 int idx = current->index;
612 int new_len = strlen (current->buf); 742 append_line (idx, current->buf);
613 int space_on_old_line = width / font_width - old_len; //D 743 current->index = idx;
614 744 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; 745 continue;
634 }
635 } 746 }
636 747
637 /* print filename if any, and if last line was from 748 /* print filename if any, and if last line was from
638 * different file */ 749 * different file */
639 if (!opt_nofilename &&
640 lastprinted != current && current->desc[0]) 750 if (!opt_nofilename && lastprinted != current && current->desc[0])
641 { 751 {
642 SCROLL_UP (lines, listlen); 752 char buf[1024]; /* HACK */
643 sprintf (lines[listlen - 1].line, "[%s]", current->desc); 753 snprintf (buf, sizeof (buf), "[%s]", current->desc);
644 lines[listlen - 1].color = current->color; 754 split_line (listlen - 1, buf, current->color);
645 } 755 }
646 756
647 /* if this is the same file we showed last, and the 757 /* if this is the same file we showed last, and the
648 * last time we showed it, it wasn't finished, then 758 * last time we showed it, it wasn't finished, then
649 * append to the last line shown */ 759 * append to the last line shown */
650 if (lastprinted == current && current->lastpartial) 760 if (lastprinted == current && current->lastpartial)
651 { 761 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) 762 else if (current->lastpartial)
669 { 763 {
670 int old_len = strlen (continuation); 764 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, 765 append_line (listlen - 1, current->buf);
675 width - old_len); 766 }
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 767 else
686 { 768 split_line (listlen - 1, current->buf, current->color);
687 SCROLL_UP (lines, listlen);
688 strcpy (lines[listlen - 1].line, current->buf);
689 }
690 769
691 /* we've shown the line now. clear the buffer for the next line */ 770 free (current->buf), current->buf = 0;
692 strcpy (current->buf, "");
693 current->index = listlen - 1; 771 current->index = listlen - 1;
694 lines[listlen - 1].color = current->color;
695
696 lastprinted = current; 772 lastprinted = current;
697 need_update = 1;
698 } 773 }
699 } 774 }
700 775
701 if (need_update) 776 if (need_update)
777 {
702 redraw (); 778 redraw ();
779 need_update = 0;
780 }
703 else 781 else
704 { 782 {
705 XFlush (disp); 783 XFlush (disp);
706 784
707 if (!XPending (disp)) 785 if (!XPending (disp))
733 811
734 r.x = xev.xexpose.x; 812 r.x = xev.xexpose.x;
735 r.y = xev.xexpose.y; 813 r.y = xev.xexpose.y;
736 r.width = xev.xexpose.width; 814 r.width = xev.xexpose.width;
737 r.height = xev.xexpose.height; 815 r.height = xev.xexpose.height;
816
738 XUnionRectWithRegion (&r, region, region); 817 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 } 818 }
744 break; 819 break;
745 default: 820 default:
746#ifdef DEBUGMODE 821#ifdef DEBUGMODE
747 fprintf (stderr, "PANIC! Unknown event %d\n", xev.type); 822 fprintf (stderr, "PANIC! Unknown event %d\n", xev.type);
760 lastreload = time (NULL); 835 lastreload = time (NULL);
761 } 836 }
762 837
763 if (!XEmptyRegion (region)) 838 if (!XEmptyRegion (region))
764 { 839 {
840 XRectangle r;
841
765 XSetRegion (disp, WinGC, region); 842 XSetRegion (disp, WinGC, region);
843 XClipBox (region, &r);
766 844
767 refresh (lines, miny, maxy); 845 refresh (r.y, r.y + r.height, 0);
846
768 XDestroyRegion (region); 847 XDestroyRegion (region);
769 region = XCreateRegion (); 848 region = XCreateRegion ();
770 maxy = 0;
771 miny = win_y + height;
772 } 849 }
773 } 850 }
774} 851}
775 852
776 853
825 reload = atoi (argv[++i]); 902 reload = atoi (argv[++i]);
826 command = argv[++i]; 903 command = argv[++i];
827 } 904 }
828 else if (!strcmp (arg, "-shade")) 905 else if (!strcmp (arg, "-shade"))
829 opt_shade = 1; 906 opt_shade = 1;
907 else if (!strcmp (arg, "-outline"))
908 opt_outline = 1;
909 else if (!strcmp (arg, "-noflicker"))
910 opt_noflicker = 1;
830 else if (!strcmp (arg, "-frame")) 911 else if (!strcmp (arg, "-frame"))
831 opt_frame = 1; 912 opt_frame = 1;
832 else if (!strcmp (arg, "-no-filename")) 913 else if (!strcmp (arg, "-no-filename"))
833 opt_nofilename = 1; 914 opt_nofilename = 1;
834 else if (!strcmp (arg, "-reverse")) 915 else if (!strcmp (arg, "-reverse"))
837 opt_whole = 1; 918 opt_whole = 1;
838 else if (!strcmp (arg, "-partial")) 919 else if (!strcmp (arg, "-partial"))
839 opt_partial = 1; 920 opt_partial = 1;
840 else if (!strcmp (arg, "-update")) 921 else if (!strcmp (arg, "-update"))
841 opt_update = opt_partial = 1; 922 opt_update = opt_partial = 1;
923 else if (!strcmp (arg, "-wordwrap"))
924 opt_wordwrap = 1;
842 else if (!strcmp (arg, "-color")) 925 else if (!strcmp (arg, "-color"))
843 def_color = argv[++i]; 926 def_color = argv[++i];
844 else if (!strcmp (arg, "-noinitial")) 927 else if (!strcmp (arg, "-noinitial"))
845 opt_noinitial = 1; 928 opt_noinitial = 1;
846 else if (!strcmp (arg, "-id")) 929 else if (!strcmp (arg, "-id"))
880 desc = p + 1; 963 desc = p + 1;
881 } 964 }
882 } 965 }
883 966
884 e = xmalloc (sizeof (struct logfile_entry)); 967 e = xmalloc (sizeof (struct logfile_entry));
968 e->partial = 0;
969 e->buf = 0;
970 e->index = -1;
971
885 if (arg[0] == '-' && arg[1] == '\0') 972 if (arg[0] == '-' && arg[1] == '\0')
886 { 973 {
887 if ((e->fp = fdopen (0, "r")) == NULL) 974 if ((e->fp = fdopen (0, "r")) == NULL)
888 perror ("fdopen"), exit (1); 975 perror ("fdopen"), exit (1);
889 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0) 976 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0)
907 memcpy (e->desc, desc, l); 994 memcpy (e->desc, desc, l);
908 *(e->desc + l) = '\0'; 995 *(e->desc + l) = '\0';
909 } 996 }
910 997
911 e->color = GetColor (fcolor); 998 e->color = GetColor (fcolor);
912 e->buf = xmalloc (width + 2);
913 e->partial = 0; 999 e->partial = 0;
914 e->buf[0] = '\0';
915 e->next = NULL; 1000 e->next = NULL;
916 1001
917 if (!loglist) 1002 if (!loglist)
918 loglist = e; 1003 loglist = e;
919 if (loglist_tail) 1004 if (loglist_tail)
1011 while ((p = malloc (size)) == NULL) 1096 while ((p = malloc (size)) == NULL)
1012 { 1097 {
1013 fprintf (stderr, "Memory exausted."); 1098 fprintf (stderr, "Memory exausted.");
1014 sleep (10); 1099 sleep (10);
1015 } 1100 }
1101
1016 return p; 1102 return p;
1017} 1103}
1018 1104
1019void 1105void
1020display_help (char *myname) 1106display_help (char *myname)
1030 " -reverse print new lines at the top\n" 1116 " -reverse print new lines at the top\n"
1031 " -whole wait for \\n before showing a line\n" 1117 " -whole wait for \\n before showing a line\n"
1032 " -partial show lines even if they don't end with a \\n\n" 1118 " -partial show lines even if they don't end with a \\n\n"
1033 " -update allow updates to old partial lines\n" 1119 " -update allow updates to old partial lines\n"
1034 " -cont string to prefix continued partial lines with\n" 1120 " -cont string to prefix continued partial lines with\n"
1121 " -wordwrap wrap long lines at spaces to avoid breaking words\n"
1035 " defaults to \"[+]\"\n" 1122 " defaults to \"[+]\"\n"
1036 " -shade add shading to font\n" 1123 " -shade add shading to font\n"
1037 " -noinitial don't display the last file lines on\n" 1124 " -noinitial don't display the last file lines on\n"
1038 " startup\n" 1125 " startup\n"
1039 " -i | -interval seconds interval between checks (fractional\n" 1126 " -i | -interval seconds interval between checks (fractional\n"
1040 " values o.k.). Default 3 seconds\n" 1127 " values o.k.). Default 2.4 seconds\n"
1041 " -V display version information and exit\n" 1128 " -V display version information and exit\n"
1042 "\n"); 1129 "\n");
1043 printf ("Example:\n%s -g 80x25+100+50 -font fixed /var/log/messages,green " 1130 printf ("Example:\n%s -g 80x25+100+50 -font fixed /var/log/messages,green "
1044 "/var/log/secure,red,'ALERT'\n", myname); 1131 "/var/log/secure,red,'ALERT'\n", myname);
1045 exit (0); 1132 exit (0);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines