… | |
… | |
75 | struct displaymatrix |
75 | struct displaymatrix |
76 | { |
76 | { |
77 | char *line; |
77 | char *line; |
78 | int len; |
78 | int len; |
79 | int buffer_size; |
79 | int buffer_size; |
|
|
80 | unsigned long color; |
80 | }; |
81 | }; |
81 | |
82 | |
82 | /* global variables */ |
83 | /* global variables */ |
83 | struct linematrix *lines; |
84 | struct linematrix *lines; |
84 | struct displaymatrix *display; |
85 | struct displaymatrix *display; |
… | |
… | |
404 | /* if this line is a different than it was, then it |
405 | /* if this line is a different than it was, then it |
405 | * needs displaying */ |
406 | * needs displaying */ |
406 | if (!opt_noflicker |
407 | if (!opt_noflicker |
407 | || refresh_all |
408 | || refresh_all |
408 | || display_line->len != line->len |
409 | || display_line->len != line->len |
|
|
410 | || display_line->color != line->color |
409 | || memcmp (display_line->line, line->line, line->len)) |
411 | || memcmp (display_line->line, line->line, line->len)) |
410 | { |
412 | { |
411 | /* don't bother updating the record of what has been |
413 | /* don't bother updating the record of what has been |
412 | * displayed if -noflicker isn't in effect, since we redraw |
414 | * displayed if -noflicker isn't in effect, since we redraw |
413 | * the whole display every time anyway */ |
415 | * the whole display every time anyway */ |
… | |
… | |
415 | { |
417 | { |
416 | /* update the record of what has been displayed; |
418 | /* update the record of what has been displayed; |
417 | * first make sure the buffer is big enough */ |
419 | * first make sure the buffer is big enough */ |
418 | if (display_line->buffer_size <= line->len) |
420 | if (display_line->buffer_size <= line->len) |
419 | { |
421 | { |
420 | display_line->buffer_size = line->len + 1; |
422 | display_line->buffer_size = line->len; |
421 | display_line->line = xrealloc (display_line->line, display_line->buffer_size); |
423 | display_line->line = xrealloc (display_line->line, display_line->buffer_size); |
422 | } |
424 | } |
423 | |
425 | |
424 | display_line->len = line->len; |
426 | display_line->len = line->len; |
|
|
427 | display_line->color = line->color; |
425 | memcpy (display_line->line, line->line, line->len); |
428 | memcpy (display_line->line, line->line, line->len); |
426 | |
429 | |
427 | if (clear) |
430 | if (clear) |
428 | XClearArea (disp, root, win_x, win_y + offset - font_ascent, |
431 | XClearArea (disp, root, win_x, win_y + offset - font_ascent, |
429 | width + effect_x_space, font_height + effect_y_space, False); |
432 | width + effect_x_space, font_height + effect_y_space, False); |
… | |
… | |
432 | if (opt_outline) |
435 | if (opt_outline) |
433 | { |
436 | { |
434 | int x, y; |
437 | int x, y; |
435 | XSetForeground (disp, WinGC, black_color); |
438 | XSetForeground (disp, WinGC, black_color); |
436 | |
439 | |
437 | for (x = -1; x < 2; x += 2) |
440 | for (x = -1; x <= 1; x += 2) |
438 | for (y = -1; y < 2; y += 2) |
441 | for (y = -1; y <= 1; y += 2) |
439 | XmbDrawString (disp, root, fontset, WinGC, |
442 | XmbDrawString (disp, root, fontset, WinGC, |
440 | win_x + effect_x_offset + x, |
443 | win_x + effect_x_offset + x, |
441 | win_y + y + offset, |
444 | win_y + y + offset, |
442 | line->line, line->len); |
445 | line->line, line->len); |
443 | } |
446 | } |
… | |
… | |
488 | if (i == 0) |
491 | if (i == 0) |
489 | { /* matched */ |
492 | { /* matched */ |
490 | int match_start = matched[0].rm_so; |
493 | int match_start = matched[0].rm_so; |
491 | int match_end = matched[0].rm_eo; |
494 | int match_end = matched[0].rm_eo; |
492 | int old_len = match_end - match_start; |
495 | int old_len = match_end - match_start; |
493 | int new_len = strlen(transform_to); |
496 | int new_len = strlen (transform_to); |
494 | int old_whole_len = strlen(s); |
497 | int old_whole_len = strlen (s); |
|
|
498 | |
495 | printf("regexp was matched by '%s' - replace with '%s'\n", s, transform_to); |
499 | printf ("regexp was matched by '%s' - replace with '%s'\n", s, transform_to); |
496 | printf("match is from %d to %d\n", |
500 | printf ("match is from %d to %d\n", match_start, match_end); |
497 | match_start, match_end); |
|
|
498 | if (new_len > old_len) { |
501 | if (new_len > old_len) |
499 | s = xrealloc(s, old_whole_len + new_len - old_len); |
502 | s = xrealloc(s, old_whole_len + new_len - old_len); |
500 | } |
503 | |
501 | if (new_len != old_len) { |
504 | if (new_len != old_len) |
|
|
505 | { |
502 | memcpy(s + match_end + new_len - old_len, |
506 | memcpy(s + match_end + new_len - old_len, |
503 | s + match_end, |
507 | s + match_end, |
504 | old_whole_len - match_end); |
508 | old_whole_len - match_end); |
505 | s[old_whole_len + new_len - old_len] = '\0'; |
509 | s[old_whole_len + new_len - old_len] = '\0'; |
506 | } |
510 | } |
|
|
511 | |
507 | memcpy(s + match_start, |
512 | memcpy (s + match_start, |
508 | transform_to, |
513 | transform_to, |
509 | new_len); |
514 | new_len); |
510 | printf("transformed to '%s'\n", s); |
515 | printf ("transformed to '%s'\n", s); |
511 | } |
516 | } |
512 | else |
517 | else |
513 | { |
518 | { |
514 | printf("regexp was not matched by '%s'\n", s); |
519 | printf ("regexp was not matched by '%s'\n", s); |
515 | } |
520 | } |
516 | } |
521 | } |
517 | } |
522 | } |
518 | #endif |
523 | #endif |
519 | |
524 | |
… | |
… | |
530 | |
535 | |
531 | return r; |
536 | return r; |
532 | } |
537 | } |
533 | |
538 | |
534 | /* |
539 | /* |
535 | * This routine should read a single line, no matter how long. |
540 | * This routine can read a line of any length if it is called enough times. |
536 | */ |
541 | */ |
537 | int |
542 | int |
538 | lineinput (struct logfile_entry *logfile) |
543 | lineinput (struct logfile_entry *logfile) |
539 | { |
544 | { |
540 | char buff[1024], *p = buff; |
545 | char buff[1024], *p = buff; |
541 | int ch; |
546 | int ch; |
542 | /* HACK this - to add on the length of any partial line which we will be appending to */ |
547 | /* HACK-2: add on the length of any partial line which we will be appending to */ |
543 | int ofs = logfile->buf ? strlen (logfile->buf) : 0; |
548 | int ofs = logfile->buf ? strlen (logfile->buf) : 0; |
544 | |
549 | |
545 | do |
550 | do |
546 | { |
551 | { |
547 | ch = fgetc (logfile->fp); |
552 | ch = fgetc (logfile->fp); |
… | |
… | |
660 | sleep (1); |
665 | sleep (1); |
661 | if (e->fp) |
666 | if (e->fp) |
662 | fclose (e->fp); |
667 | fclose (e->fp); |
663 | if (openlog (e) == NULL) |
668 | if (openlog (e) == NULL) |
664 | continue; |
669 | continue; |
|
|
670 | if (fstat (fileno (e->fp), &stats) < 0) |
|
|
671 | continue; |
665 | } |
672 | } |
666 | |
673 | |
667 | /* HACK this - stats can be uninitialised here (if the file |
|
|
668 | * didn't exist when stat() was called, but was recreated during |
|
|
669 | * the sleep(1)) */ |
|
|
670 | if (stats.st_ino != e->inode) |
674 | if (stats.st_ino != e->inode) |
671 | { /* file renamed? */ |
675 | { /* file renamed? */ |
672 | if (e->fp) |
676 | if (e->fp) |
673 | fclose (e->fp); |
677 | fclose (e->fp); |
674 | if (openlog (e) == NULL) |
678 | if (openlog (e) == NULL) |
|
|
679 | continue; |
|
|
680 | if (fstat (fileno (e->fp), &stats) < 0) |
675 | continue; |
681 | continue; |
676 | } |
682 | } |
677 | |
683 | |
678 | if (stats.st_size < e->last_size) |
684 | if (stats.st_size < e->last_size) |
679 | { /* file truncated? */ |
685 | { /* file truncated? */ |
… | |
… | |
731 | */ |
737 | */ |
732 | static void |
738 | static void |
733 | split_line (int idx, const char *str, unsigned long color) |
739 | split_line (int idx, const char *str, unsigned long color) |
734 | { |
740 | { |
735 | int l = strlen (str); |
741 | int l = strlen (str); |
|
|
742 | int last_wrapped = 0; |
736 | const char *p = str; |
743 | const char *p = str; |
|
|
744 | static int continuation_width = -1; |
|
|
745 | static int continuation_length; |
|
|
746 | |
|
|
747 | /* only calculate the continuation's width once */ |
|
|
748 | if (continuation_width == -1) |
|
|
749 | { |
|
|
750 | continuation_length = strlen (continuation); |
|
|
751 | continuation_width = XmbTextEscapement (fontset, continuation, continuation_length); |
|
|
752 | } |
737 | |
753 | |
738 | do |
754 | do |
739 | { |
755 | { |
740 | const char *beg = p; |
756 | const char *beg = p; |
|
|
757 | int w = last_wrapped ? continuation_width : 0; |
741 | int w = 0, wrapped = 0; |
758 | int wrapped = 0; |
742 | const char *break_p = NULL; |
759 | const char *break_p = NULL; |
743 | |
760 | |
744 | while (*p) |
761 | while (*p) |
745 | { |
762 | { |
746 | /* find the length in bytes of the next multibyte character */ |
763 | /* find the length in bytes of the next multibyte character */ |
… | |
… | |
750 | |
767 | |
751 | /* find the width in pixels of the next character */ |
768 | /* find the width in pixels of the next character */ |
752 | int cw = XmbTextEscapement (fontset, p, len); |
769 | int cw = XmbTextEscapement (fontset, p, len); |
753 | if (cw + w > width - effect_x_space) |
770 | if (cw + w > width - effect_x_space) |
754 | { |
771 | { |
|
|
772 | if (p == beg) |
|
|
773 | { |
|
|
774 | fprintf (stderr, "we can't even fit a single character onto the line\n"); |
|
|
775 | if (len == 1) fprintf (stderr, "(the character we couldn't fit was '%c')\n", *p); |
|
|
776 | exit (1); |
|
|
777 | } |
|
|
778 | |
755 | wrapped = 1; |
779 | wrapped = 1; |
756 | break; |
780 | break; |
757 | } |
781 | } |
758 | |
782 | |
759 | if (opt_wordwrap && len == 1 && p[0] == ' ') |
783 | if (opt_wordwrap && len == 1 && p[0] == ' ') |
… | |
… | |
772 | l += p - break_p; |
796 | l += p - break_p; |
773 | p = break_p; |
797 | p = break_p; |
774 | } |
798 | } |
775 | |
799 | |
776 | { |
800 | { |
|
|
801 | /* HACK-4 - consider inserting the 'continuation string' |
|
|
802 | * before the rest of the wrapped line */ |
|
|
803 | int len = p - beg + (last_wrapped ? continuation_length : 0); |
777 | char *s = xmalloc (p - beg + 1); |
804 | char *s = xmalloc (len + 1); |
778 | memcpy (s, beg, p - beg); |
805 | if (last_wrapped) |
|
|
806 | { |
|
|
807 | memcpy (s, continuation, continuation_length); |
|
|
808 | memcpy (s + continuation_length, beg, p - beg); |
|
|
809 | } |
|
|
810 | else |
|
|
811 | memcpy (s, beg, len); |
|
|
812 | |
779 | s[p - beg] = 0; |
813 | s[len] = 0; |
780 | insert_line (idx); |
814 | insert_line (idx); |
781 | lines[idx].line = s; |
815 | lines[idx].line = s; |
782 | lines[idx].len = p - beg; |
816 | lines[idx].len = len; |
783 | lines[idx].color = color; |
817 | lines[idx].color = color; |
784 | } |
818 | } |
785 | |
819 | |
786 | /* if we wrapped at a space, don't display the space */ |
820 | /* if we wrapped at a space, don't display the space */ |
787 | if (opt_wordwrap && wrapped && break_p && break_p != beg) |
821 | if (opt_wordwrap && wrapped && break_p && break_p != beg) |
788 | { |
822 | { |
789 | l--; |
823 | l--; |
790 | p++; |
824 | p++; |
791 | } |
825 | } |
|
|
826 | |
|
|
827 | last_wrapped = wrapped; |
792 | } |
828 | } |
793 | while (l); |
829 | while (l); |
794 | } |
830 | } |
795 | |
831 | |
796 | /* |
832 | /* |
… | |
… | |
831 | { |
867 | { |
832 | lines[lin].line = xstrdup ("~"); |
868 | lines[lin].line = xstrdup ("~"); |
833 | lines[lin].len = 1; |
869 | lines[lin].len = 1; |
834 | display[lin].line = xstrdup(""); |
870 | display[lin].line = xstrdup(""); |
835 | display[lin].len = 0; |
871 | display[lin].len = 0; |
836 | display[lin].buffer_size = 1; |
872 | display[lin].buffer_size = 0; |
837 | lines[lin].color = GetColor (def_color); |
873 | lines[lin].color = GetColor (def_color); |
838 | } |
874 | } |
839 | |
875 | |
840 | for (;;) |
876 | for (;;) |
841 | { |
877 | { |
… | |
… | |
866 | |
902 | |
867 | /* print filename if any, and if last line was from |
903 | /* print filename if any, and if last line was from |
868 | * different file */ |
904 | * different file */ |
869 | if (!opt_nofilename && lastprinted != current && current->desc[0]) |
905 | if (!opt_nofilename && lastprinted != current && current->desc[0]) |
870 | { |
906 | { |
871 | char buf[1024]; /* HACK */ |
907 | char buf[1024]; /* HACK-5 */ |
872 | snprintf (buf, sizeof (buf), "[%s]", current->desc); |
908 | snprintf (buf, sizeof (buf), "[%s]", current->desc); |
873 | split_line (listlen - 1, buf, current->color); |
909 | split_line (listlen - 1, buf, current->color); |
874 | } |
910 | } |
875 | |
911 | |
876 | /* if we're dealing with partial lines, and the last |
912 | /* if we're dealing with partial lines, and the last |
… | |
… | |
1104 | { |
1140 | { |
1105 | if ((e->fp = fdopen (0, "r")) == NULL) |
1141 | if ((e->fp = fdopen (0, "r")) == NULL) |
1106 | perror ("fdopen"), exit (1); |
1142 | perror ("fdopen"), exit (1); |
1107 | if (fcntl (0, F_SETFL, O_NONBLOCK) < 0) |
1143 | if (fcntl (0, F_SETFL, O_NONBLOCK) < 0) |
1108 | perror ("fcntl"), exit (1); |
1144 | perror ("fcntl"), exit (1); |
|
|
1145 | |
1109 | e->fname = NULL; |
1146 | e->fname = NULL; |
1110 | e->inode = 0; |
1147 | e->inode = 0; |
1111 | e->desc = xstrdup ("stdin"); |
1148 | e->desc = xstrdup ("stdin"); |
1112 | } |
1149 | } |
1113 | else |
1150 | else |
1114 | { |
1151 | { |
1115 | int l; |
|
|
1116 | |
|
|
1117 | e->fname = xstrdup (fname); |
1152 | e->fname = xstrdup (fname); |
|
|
1153 | |
1118 | if (openlog (e) == NULL) |
1154 | if (openlog (e) == NULL) |
1119 | perror (fname), exit (1); |
1155 | perror (fname), exit (1); |
1120 | |
1156 | |
1121 | l = strlen (desc); |
1157 | e->desc = xstrdup (desc); |
1122 | /* HACK on this - width is in pixels now */ |
|
|
1123 | if (l > width - 2) /* must account for [ ] */ |
|
|
1124 | l = width - 2; |
|
|
1125 | e->desc = xmalloc (l + 1); |
|
|
1126 | memcpy (e->desc, desc, l); |
|
|
1127 | *(e->desc + l) = '\0'; |
|
|
1128 | } |
1158 | } |
1129 | |
1159 | |
1130 | e->color = GetColor (fcolor); |
1160 | e->color = GetColor (fcolor); |
1131 | e->partial = 0; |
1161 | e->partial = 0; |
1132 | e->next = NULL; |
1162 | e->next = NULL; |
1133 | |
1163 | |
1134 | if (!loglist) |
1164 | if (!loglist) |
1135 | loglist = e; |
1165 | loglist = e; |
1136 | if (loglist_tail) |
1166 | if (loglist_tail) |
1137 | loglist_tail->next = e; |
1167 | loglist_tail->next = e; |
|
|
1168 | |
1138 | loglist_tail = e; |
1169 | loglist_tail = e; |
1139 | } |
1170 | } |
1140 | } |
1171 | } |
1141 | |
1172 | |
1142 | if (!loglist) |
1173 | if (!loglist) |
… | |
… | |
1150 | { |
1181 | { |
1151 | fprintf (stderr, "Specify at most one of -partial and -whole\n"); |
1182 | fprintf (stderr, "Specify at most one of -partial and -whole\n"); |
1152 | exit (1); |
1183 | exit (1); |
1153 | } |
1184 | } |
1154 | |
1185 | |
1155 | /* HACK this - do we want to allow both -shade and -outline? */ |
1186 | /* HACK-7: do we want to allow both -shade and -outline? */ |
1156 | if (opt_shade && opt_outline) |
1187 | if (opt_shade && opt_outline) |
1157 | { |
1188 | { |
1158 | fprintf (stderr, "Specify at most one of -shade and -outline\n"); |
1189 | fprintf (stderr, "Specify at most one of -shade and -outline\n"); |
1159 | exit (1); |
1190 | exit (1); |
1160 | } |
1191 | } |