… | |
… | |
401 | if (offset < miny || offset > maxy) |
401 | if (offset < miny || offset > maxy) |
402 | continue; |
402 | continue; |
403 | |
403 | |
404 | /* if this line is a different than it was, then it |
404 | /* if this line is a different than it was, then it |
405 | * needs displaying */ |
405 | * needs displaying */ |
406 | if (refresh_all |
406 | if (!opt_noflicker |
|
|
407 | || refresh_all |
407 | || display_line->len != line->len |
408 | || display_line->len != line->len |
408 | || memcmp (display_line->line, line->line, line->len)) |
409 | || memcmp (display_line->line, line->line, line->len)) |
409 | { |
410 | { |
|
|
411 | /* don't bother updating the record of what has been |
|
|
412 | * displayed if -noflicker isn't in effect, since we redraw |
|
|
413 | * the whole display every time anyway */ |
|
|
414 | if (opt_noflicker) |
|
|
415 | { |
410 | /* update the record of what has been displayed; |
416 | /* update the record of what has been displayed; |
411 | * first make sure the buffer is big enough */ |
417 | * first make sure the buffer is big enough */ |
412 | if (display_line->buffer_size <= line->len) |
418 | if (display_line->buffer_size <= line->len) |
413 | { |
419 | { |
414 | display_line->buffer_size = line->len + 1; |
420 | display_line->buffer_size = line->len + 1; |
415 | display_line->line = xrealloc (display_line->line, display_line->buffer_size); |
421 | display_line->line = xrealloc (display_line->line, display_line->buffer_size); |
416 | } |
422 | } |
417 | |
423 | |
418 | display_line->len = line->len; |
424 | display_line->len = line->len; |
419 | memcpy (display_line->line, line->line, line->len); |
425 | memcpy (display_line->line, line->line, line->len); |
420 | |
426 | |
421 | if (clear) |
427 | if (clear) |
422 | XClearArea (disp, root, win_x, win_y + offset - font_ascent, |
428 | XClearArea (disp, root, win_x, win_y + offset - font_ascent, |
423 | width + effect_x_space, font_height + effect_y_space, False); |
429 | width + effect_x_space, font_height + effect_y_space, False); |
|
|
430 | } |
424 | |
431 | |
425 | if (opt_outline) |
432 | if (opt_outline) |
426 | { |
433 | { |
427 | int x, y; |
434 | int x, y; |
428 | XSetForeground (disp, WinGC, black_color); |
435 | XSetForeground (disp, WinGC, black_color); |
… | |
… | |
523 | |
530 | |
524 | return r; |
531 | return r; |
525 | } |
532 | } |
526 | |
533 | |
527 | /* |
534 | /* |
528 | * This routine should read a single line, no matter how long. |
535 | * HACK-1: This routine should read a single line, no matter how long. |
529 | */ |
536 | */ |
530 | int |
537 | int |
531 | lineinput (struct logfile_entry *logfile) |
538 | lineinput (struct logfile_entry *logfile) |
532 | { |
539 | { |
533 | char buff[1024], *p = buff; |
540 | char buff[1024], *p = buff; |
534 | int ch; |
541 | int ch; |
535 | /* HACK this - to add on the length of any partial line which we will be appending to */ |
542 | /* HACK-2: add on the length of any partial line which we will be appending to */ |
536 | int ofs = logfile->buf ? strlen (logfile->buf) : 0; |
543 | int ofs = logfile->buf ? strlen (logfile->buf) : 0; |
537 | |
544 | |
538 | do |
545 | do |
539 | { |
546 | { |
540 | ch = fgetc (logfile->fp); |
547 | ch = fgetc (logfile->fp); |
… | |
… | |
653 | sleep (1); |
660 | sleep (1); |
654 | if (e->fp) |
661 | if (e->fp) |
655 | fclose (e->fp); |
662 | fclose (e->fp); |
656 | if (openlog (e) == NULL) |
663 | if (openlog (e) == NULL) |
657 | continue; |
664 | continue; |
|
|
665 | if (fstat (fileno (e->fp), &stats) < 0) |
|
|
666 | continue; |
658 | } |
667 | } |
659 | |
668 | |
660 | /* HACK this - stats can be uninitialised here (if the file |
|
|
661 | * didn't exist when stat() was called, but was recreated during |
|
|
662 | * the sleep(1)) */ |
|
|
663 | if (stats.st_ino != e->inode) |
669 | if (stats.st_ino != e->inode) |
664 | { /* file renamed? */ |
670 | { /* file renamed? */ |
665 | if (e->fp) |
671 | if (e->fp) |
666 | fclose (e->fp); |
672 | fclose (e->fp); |
667 | if (openlog (e) == NULL) |
673 | if (openlog (e) == NULL) |
… | |
… | |
724 | */ |
730 | */ |
725 | static void |
731 | static void |
726 | split_line (int idx, const char *str, unsigned long color) |
732 | split_line (int idx, const char *str, unsigned long color) |
727 | { |
733 | { |
728 | int l = strlen (str); |
734 | int l = strlen (str); |
|
|
735 | int last_wrapped = 0; |
729 | const char *p = str; |
736 | const char *p = str; |
|
|
737 | static int continuation_width = -1; |
|
|
738 | static int continuation_length; |
|
|
739 | |
|
|
740 | /* only calculate the continuation's width once */ |
|
|
741 | if (continuation_width == -1) |
|
|
742 | { |
|
|
743 | continuation_length = strlen(continuation); |
|
|
744 | continuation_width = XmbTextEscapement (fontset, continuation, continuation_length); |
|
|
745 | } |
730 | |
746 | |
731 | do |
747 | do |
732 | { |
748 | { |
733 | const char *beg = p; |
749 | const char *beg = p; |
|
|
750 | int w = last_wrapped ? continuation_width : 0; |
734 | int w = 0, wrapped = 0; |
751 | int wrapped = 0; |
735 | const char *break_p = NULL; |
752 | const char *break_p = NULL; |
736 | |
753 | |
737 | while (*p) |
754 | while (*p) |
738 | { |
755 | { |
739 | /* find the length in bytes of the next multibyte character */ |
756 | /* find the length in bytes of the next multibyte character */ |
… | |
… | |
743 | |
760 | |
744 | /* find the width in pixels of the next character */ |
761 | /* find the width in pixels of the next character */ |
745 | int cw = XmbTextEscapement (fontset, p, len); |
762 | int cw = XmbTextEscapement (fontset, p, len); |
746 | if (cw + w > width - effect_x_space) |
763 | if (cw + w > width - effect_x_space) |
747 | { |
764 | { |
|
|
765 | if (p == beg) |
|
|
766 | { |
|
|
767 | fprintf(stderr, "we can't even fit a single character onto the line\n"); |
|
|
768 | if (len == 1) fprintf(stderr, "(the character we couldn't fit was '%c')\n", *p); |
|
|
769 | exit(1); |
|
|
770 | } |
|
|
771 | |
748 | wrapped = 1; |
772 | wrapped = 1; |
749 | break; |
773 | break; |
750 | } |
774 | } |
751 | |
775 | |
752 | if (opt_wordwrap && len == 1 && p[0] == ' ') |
776 | if (opt_wordwrap && len == 1 && p[0] == ' ') |
… | |
… | |
765 | l += p - break_p; |
789 | l += p - break_p; |
766 | p = break_p; |
790 | p = break_p; |
767 | } |
791 | } |
768 | |
792 | |
769 | { |
793 | { |
|
|
794 | /* HACK-4 - consider inserting the 'continuation string' |
|
|
795 | * before the rest of the wrapped line */ |
|
|
796 | int len = p - beg + (last_wrapped ? continuation_length : 0); |
770 | char *s = xmalloc (p - beg + 1); |
797 | char *s = xmalloc (len + 1); |
|
|
798 | if (last_wrapped) |
|
|
799 | { |
|
|
800 | memcpy (s, continuation, continuation_length); |
|
|
801 | memcpy (s + continuation_length, beg, p - beg); |
|
|
802 | } |
|
|
803 | else |
771 | memcpy (s, beg, p - beg); |
804 | memcpy (s, beg, len); |
|
|
805 | |
772 | s[p - beg] = 0; |
806 | s[len] = 0; |
773 | insert_line (idx); |
807 | insert_line (idx); |
774 | lines[idx].line = s; |
808 | lines[idx].line = s; |
775 | lines[idx].len = p - beg; |
809 | lines[idx].len = len; |
776 | lines[idx].color = color; |
810 | lines[idx].color = color; |
777 | } |
811 | } |
778 | |
812 | |
779 | /* if we wrapped at a space, don't display the space */ |
813 | /* if we wrapped at a space, don't display the space */ |
780 | if (opt_wordwrap && wrapped && break_p && break_p != beg) |
814 | if (opt_wordwrap && wrapped && break_p && break_p != beg) |
781 | { |
815 | { |
782 | l--; |
816 | l--; |
783 | p++; |
817 | p++; |
784 | } |
818 | } |
|
|
819 | |
|
|
820 | last_wrapped = wrapped; |
785 | } |
821 | } |
786 | while (l); |
822 | while (l); |
787 | } |
823 | } |
788 | |
824 | |
789 | /* |
825 | /* |
… | |
… | |
859 | |
895 | |
860 | /* print filename if any, and if last line was from |
896 | /* print filename if any, and if last line was from |
861 | * different file */ |
897 | * different file */ |
862 | if (!opt_nofilename && lastprinted != current && current->desc[0]) |
898 | if (!opt_nofilename && lastprinted != current && current->desc[0]) |
863 | { |
899 | { |
864 | char buf[1024]; /* HACK */ |
900 | char buf[1024]; /* HACK-5 */ |
865 | snprintf (buf, sizeof (buf), "[%s]", current->desc); |
901 | snprintf (buf, sizeof (buf), "[%s]", current->desc); |
866 | split_line (listlen - 1, buf, current->color); |
902 | split_line (listlen - 1, buf, current->color); |
867 | } |
903 | } |
868 | |
904 | |
869 | /* if this is the same file we showed last, and the |
905 | /* if we're dealing with partial lines, and the last |
870 | * last time we showed it, it wasn't finished, then |
906 | * time we showed the line it wasn't finished ... */ |
871 | * append to the last line shown */ |
|
|
872 | if (lastprinted == current && current->lastpartial) |
|
|
873 | append_line (listlen - 1, current->buf); |
|
|
874 | else if (current->lastpartial) |
907 | if (!opt_whole && current->lastpartial) |
875 | { |
908 | { |
|
|
909 | /* if this is the same file we showed last then |
|
|
910 | append to the last line shown */ |
|
|
911 | if (lastprinted == current) |
|
|
912 | append_line (listlen - 1, current->buf); |
|
|
913 | else |
|
|
914 | { |
|
|
915 | /* but if a different file has been shown in the |
|
|
916 | * mean time, make a new line, starting with the |
|
|
917 | * continuation string */ |
876 | split_line (listlen - 1, continuation, current->color); |
918 | split_line (listlen - 1, continuation, current->color); |
877 | append_line (listlen - 1, current->buf); |
919 | append_line (listlen - 1, current->buf); |
|
|
920 | } |
878 | } |
921 | } |
879 | else |
922 | else |
|
|
923 | /* otherwise just make a plain and simple new line */ |
880 | split_line (listlen - 1, current->buf, current->color); |
924 | split_line (listlen - 1, current->buf, current->color); |
881 | |
925 | |
882 | free (current->buf), current->buf = 0; |
926 | free (current->buf), current->buf = 0; |
883 | current->index = listlen - 1; |
927 | current->index = listlen - 1; |
884 | lastprinted = current; |
928 | lastprinted = current; |
… | |
… | |
1101 | |
1145 | |
1102 | e->fname = xstrdup (fname); |
1146 | e->fname = xstrdup (fname); |
1103 | if (openlog (e) == NULL) |
1147 | if (openlog (e) == NULL) |
1104 | perror (fname), exit (1); |
1148 | perror (fname), exit (1); |
1105 | |
1149 | |
1106 | l = strlen (desc); |
1150 | e->desc = xstrdup (desc); |
1107 | /* HACK on this - width is in pixels now */ |
|
|
1108 | if (l > width - 2) /* must account for [ ] */ |
|
|
1109 | l = width - 2; |
|
|
1110 | e->desc = xmalloc (l + 1); |
|
|
1111 | memcpy (e->desc, desc, l); |
|
|
1112 | *(e->desc + l) = '\0'; |
|
|
1113 | } |
1151 | } |
1114 | |
1152 | |
1115 | e->color = GetColor (fcolor); |
1153 | e->color = GetColor (fcolor); |
1116 | e->partial = 0; |
1154 | e->partial = 0; |
1117 | e->next = NULL; |
1155 | e->next = NULL; |
… | |
… | |
1135 | { |
1173 | { |
1136 | fprintf (stderr, "Specify at most one of -partial and -whole\n"); |
1174 | fprintf (stderr, "Specify at most one of -partial and -whole\n"); |
1137 | exit (1); |
1175 | exit (1); |
1138 | } |
1176 | } |
1139 | |
1177 | |
1140 | /* HACK this - do we want to allow both -shade and -outline? */ |
1178 | /* HACK-7: do we want to allow both -shade and -outline? */ |
1141 | if (opt_shade && opt_outline) |
1179 | if (opt_shade && opt_outline) |
1142 | { |
1180 | { |
1143 | fprintf (stderr, "Specify at most one of -shade and -outline\n"); |
1181 | fprintf (stderr, "Specify at most one of -shade and -outline\n"); |
1144 | exit (1); |
1182 | exit (1); |
1145 | } |
1183 | } |
1146 | |
1184 | |
1147 | if (opt_partial) |
1185 | if (opt_partial) |
1148 | /* if we specifically requested to see partial lines then don't insist on whole lines */ |
1186 | /* if we specifically requested to see partial lines then don't insist on whole lines */ |
1149 | opt_whole = 0; |
1187 | opt_whole = 0; |
1150 | else if (file_count > 1) |
1188 | else if (file_count > 1) |
1151 | /* otherwise, if we've viewing multiple files, default to showing whole lines */ |
1189 | /* otherwise, if we're viewing multiple files, default to showing whole lines */ |
1152 | opt_whole = 1; |
1190 | opt_whole = 1; |
1153 | |
1191 | |
1154 | #if HAS_REGEX |
1192 | #if HAS_REGEX |
1155 | if (transform) |
1193 | if (transform) |
1156 | { |
1194 | { |