1 #define _LARGEFILE64_SOURCE /* required for GLIBC to enable stat64 and friends */
2 #include <ctype.h>
3 #include <sys/types.h>
4 #include <regex.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <pwd.h>
8 #include <errno.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11
12 #include "mt.h"
13 #include "error.h"
14 #include "my_pty.h"
15 #include "utils.h"
16 #include "term.h"
17 #include "help.h"
18 #include "mem.h"
19 #include "ui.h"
20 #include "misc.h"
21 #include "globals.h"
22 #include "clipboard.h"
23
24 int scrollback_search_to_new_window(buffer *pbuf, char *org_title, char *find_str, mybool_t case_insensitive);
25
find_string(buffer * pbuf,char * find,int offset,char direction,mybool_t case_insensitive)26 int find_string(buffer *pbuf, char *find, int offset, char direction, mybool_t case_insensitive)
27 {
28 int loop, index = -1, rc;
29 regex_t regex;
30
31 /* compile the searchstring (which can be a regular expression) */
32 if ((rc = regcomp(®ex, find, REG_EXTENDED | (case_insensitive == MY_TRUE?REG_ICASE:0))))
33 {
34 regexp_error_popup(rc, ®ex);
35
36 return -1; /* failed -> not found */
37 }
38
39 if (direction == 1)
40 {
41 for(loop=offset; loop<pbuf -> curpos; loop++)
42 {
43 if ((pbuf -> be)[loop].Bline == NULL)
44 continue;
45
46 if (regexec(®ex, (pbuf -> be)[loop].Bline, 0, NULL, 0) == 0)
47 {
48 index = loop;
49 break;
50 }
51 }
52 }
53 else if (direction == (char)-1)
54 {
55 for(loop=offset; loop>=0; loop--)
56 {
57 if ((pbuf -> be)[loop].Bline == NULL)
58 continue;
59
60 if (regexec(®ex, (pbuf -> be)[loop].Bline, 0, NULL, 0) == 0)
61 {
62 index = loop;
63 break;
64 }
65 }
66 }
67
68 regfree(®ex);
69
70 return index;
71 }
72
scrollback_find_popup(char ** find_str,mybool_t * pcase_insensitive)73 void scrollback_find_popup(char **find_str, mybool_t *pcase_insensitive)
74 {
75 char *dummy;
76 NEWWIN *mywin = create_popup(5, 40);
77
78 win_header(mywin, "Find");
79
80 dummy = edit_string(mywin, 3, 2, 40, 80, 0, reuse_searchstring?*find_str:NULL, HELP_SCROLLBACK_EDIT_SEARCH_STRING, -1, &search_h, pcase_insensitive);
81 myfree(*find_str);
82 *find_str = dummy;
83
84 delete_popup(mywin);
85 }
86
scrollback_savefile(buffer * pbuf)87 void scrollback_savefile(buffer *pbuf)
88 {
89 char *file = NULL;
90 NEWWIN *mywin = create_popup(8, 40);
91
92 win_header(mywin, "Save buffer to file");
93
94 mvwprintw(mywin -> win, 4, 2, "Select file");
95 file = edit_string(mywin, 5, 2, 40, find_path_max(), 0, NULL, HELP_SCROLLBACK_SAVEFILE_ENTER_FILENAME, -1, &cmdfile_h, NULL);
96 if (file)
97 {
98 FILE *fh = fopen(file, "w");
99 if (fh)
100 {
101 int loop;
102
103 for(loop=0; loop<pbuf -> curpos; loop++)
104 {
105 if ((pbuf -> be)[loop].Bline)
106 {
107 char display = 1;
108 char *error;
109 int dummy = -1;
110 regmatch_t *pmatch = NULL;
111
112 /* check filter */
113 if (!IS_MARKERLINE((pbuf -> be)[loop].pi))
114 {
115 (void)check_filter((pbuf -> be)[loop].pi, (pbuf -> be)[loop].Bline, &pmatch, &error, &dummy, 0, &display);
116 if (error)
117 {
118 fprintf(fh, "%s\n", error);
119 myfree(error);
120 }
121 }
122 if (display)
123 {
124 fprintf(fh, "%s\n", USE_IF_SET((pbuf -> be)[loop].Bline, ""));
125 }
126
127 if (pmatch) myfree(pmatch);
128 }
129 }
130
131 fclose(fh);
132 }
133 else
134 {
135 error_popup("Save scrollback buffer", -1, "Cannot write to file, reason: %s", strerror(errno));
136 }
137 }
138
139 delete_popup(mywin);
140 }
141
get_lines_needed(char * string,int terminal_width)142 int get_lines_needed(char *string, int terminal_width)
143 {
144 if (string)
145 return (strlen(string) + terminal_width - 1) / terminal_width;
146 else
147 return 1;
148 }
149
scrollback_displayline(int window_nr,NEWWIN * win,buffer * pbuf,int buffer_offset,int terminal_offset,int offset_in_line,mybool_t force_to_winwidth,char show_winnr)150 void scrollback_displayline(int window_nr, NEWWIN *win, buffer *pbuf, int buffer_offset, int terminal_offset, int offset_in_line, mybool_t force_to_winwidth, char show_winnr)
151 {
152 char *cur_line = (pbuf -> be)[buffer_offset].Bline;
153
154 wmove(win -> win, terminal_offset, 0);
155
156 if (cur_line)
157 {
158 proginfo *cur_line_meta = (pbuf -> be)[buffer_offset].pi;
159 double ts = (pbuf -> be)[buffer_offset].ts;
160 char old_color_settings = 0;
161
162 if (scrollback_no_colors && cur_line_meta != NULL)
163 {
164 old_color_settings = cur_line_meta -> cdef.colorize;
165 cur_line_meta -> cdef.colorize = 0;
166 }
167 if (IS_MARKERLINE(cur_line_meta))
168 {
169 color_print(window_nr, win, cur_line_meta, cur_line, NULL, -1, MY_FALSE, 0, 0, ts, show_winnr);
170 }
171 else /* just a buffered line */
172 {
173 char *error = NULL;
174 regmatch_t *pmatch = NULL;
175 int matching_regex = -1;
176 char display;
177 (void)check_filter(cur_line_meta, cur_line, &pmatch, &error, &matching_regex, 0, &display);
178 if (error)
179 {
180 color_print(window_nr, win, cur_line_meta, error, NULL, -1, MY_FALSE, 0, 0, ts, show_winnr);
181 myfree(error);
182 }
183 if (display)
184 {
185 if (offset_in_line)
186 {
187 int line_len = strlen(cur_line);
188 int new_size = 0;
189
190 if (offset_in_line < line_len)
191 new_size = min(win -> width, line_len - offset_in_line);
192
193 color_print(window_nr, win, cur_line_meta, cur_line, pmatch, matching_regex, force_to_winwidth, offset_in_line, offset_in_line + new_size, ts, show_winnr);
194 }
195 else
196 {
197 color_print(window_nr, win, cur_line_meta, cur_line, pmatch, matching_regex, force_to_winwidth, 0, 0, ts, show_winnr);
198 }
199 }
200
201 myfree(pmatch);
202 }
203 if (scrollback_no_colors && cur_line_meta != NULL)
204 {
205 cur_line_meta -> cdef.colorize = old_color_settings;
206 }
207 }
208 else /* an empty line */
209 {
210 /* do nothing */
211 }
212 }
213
214
compute_text_dimensions(int * nlines,int * ncols,char fullscreen)215 void compute_text_dimensions(int *nlines, int *ncols, char fullscreen)
216 {
217 if (fullscreen)
218 {
219 *nlines = max_y;
220 *ncols = max_x;
221 }
222 else
223 {
224 *nlines = max_y - 6;
225 *ncols = max_x - 6;
226 }
227 }
228
create_scrollback_windows(NEWWIN ** mywin1,NEWWIN ** mywin2,int nlines,int ncols,char fullscreen)229 void create_scrollback_windows(NEWWIN **mywin1, NEWWIN **mywin2, int nlines, int ncols, char fullscreen)
230 {
231 /* Delete existing windows, if any. */
232 if (*mywin1)
233 {
234 delete_popup(*mywin1);
235 }
236
237 if (*mywin2)
238 {
239 delete_popup(*mywin2);
240 }
241
242 /* Re-create windows, according to fullscreen flag */
243 if (fullscreen)
244 {
245 *mywin1 = NULL;
246 *mywin2 = create_popup(max_y, max_x);
247 scrollok((*mywin2) -> win, FALSE); /* supposed to always return OK, according to the manpage */
248
249 }
250 else
251 {
252 *mywin1 = create_popup(max_y - 4, max_x - 4);
253 *mywin2 = create_popup(nlines, ncols);
254 scrollok((*mywin2) -> win, FALSE); /* supposed to always return OK, according to the manpage */
255 }
256 }
257
scrollback_do(int window_nr,buffer * pbuf,int * winnrs,char * header)258 int scrollback_do(int window_nr, buffer *pbuf, int *winnrs, char *header)
259 {
260 int rc = 0;
261 char *find = NULL;
262 char fullscreen = scrollback_fullscreen_default;
263 NEWWIN *mywin1 = NULL, *mywin2 = NULL;
264
265 int nlines, ncols;
266 compute_text_dimensions(&nlines, &ncols, fullscreen);
267
268 int offset = max(0, pbuf -> curpos - nlines); /* FIXME: aantal regels laten afhangen van lengte */
269 char redraw = 2;
270 int line_offset = 0;
271 char show_winnr = default_sb_showwinnr;
272 mybool_t case_insensitive = re_case_insensitive;
273 buffer cur_lb;
274 int loop = 0;
275
276 memset(&cur_lb, 0x00, sizeof(cur_lb));
277
278 for(loop=0; loop<pbuf -> curpos; loop++)
279 {
280 if ((pbuf -> be)[loop].Bline == NULL)
281 continue;
282
283 cur_lb.be = myrealloc(cur_lb.be, (cur_lb.curpos + 1) * sizeof(buffered_entry));
284 cur_lb.be[cur_lb.curpos].pi = (pbuf -> be)[loop].pi;
285 if ((pbuf -> be)[loop].pi != NULL && (!IS_MARKERLINE((pbuf -> be)[loop].pi)) && (pbuf -> be)[loop].pi -> cdef.term_emul != TERM_IGNORE)
286 {
287 color_offset_in_line *cmatches;
288 int n_cmatches;
289 cur_lb.be[cur_lb.curpos].Bline = emulate_terminal((pbuf -> be)[loop].Bline, &cmatches, &n_cmatches);
290 myfree(cmatches);
291 }
292 else
293 cur_lb.be[cur_lb.curpos].Bline = strdup((pbuf -> be)[loop].Bline);
294 cur_lb.be[cur_lb.curpos].ts = (pbuf -> be)[loop].ts;
295 cur_lb.curpos++;
296 }
297
298 LOG("---\n");
299 if (global_highlight_str)
300 {
301 find = mystrdup(global_highlight_str);
302 }
303
304 create_scrollback_windows(&mywin1, &mywin2, nlines, ncols, fullscreen);
305
306 for(;;)
307 {
308 int c, uc;
309
310 if (redraw == 2)
311 {
312 int index = 0;
313 int lines_used = 0;
314
315 if (mywin1)
316 {
317 ui_inverse_on(mywin1);
318 mvwprintw(mywin1 -> win, nlines + 1, 1, "%s - %d buffered lines", shorten_filename(header, max(24, ncols - 24)), cur_lb.curpos);
319 ui_inverse_off(mywin1);
320
321 if (!no_linewrap) ui_inverse_on(mywin1);
322 mvwprintw(mywin1 -> win, nlines + 1, ncols - 8, "LINEWRAP");
323 if (!no_linewrap) ui_inverse_off(mywin1);
324 }
325
326 werase(mywin2 -> win);
327
328 if (!no_linewrap && line_offset > 0)
329 {
330 int temp_line_offset = line_offset;
331 int n_chars_to_display_left = strlen((cur_lb.be)[offset].Bline) - temp_line_offset;
332
333 while(lines_used < nlines && n_chars_to_display_left > 0)
334 {
335 scrollback_displayline(winnrs?winnrs[offset]:window_nr, mywin2, &cur_lb, offset, lines_used, temp_line_offset, 1, show_winnr);
336
337 temp_line_offset += ncols;
338 n_chars_to_display_left -= ncols;
339
340 lines_used++;
341 }
342
343 index++;
344 }
345
346 for(;(offset + index) < cur_lb.curpos && lines_used < nlines;)
347 {
348 int lines_needed = get_lines_needed((cur_lb.be)[offset + index].Bline, ncols);
349
350 if (no_linewrap || lines_needed == 1)
351 {
352 scrollback_displayline(winnrs?winnrs[offset + index]:window_nr, mywin2, &cur_lb, offset + index, lines_used, no_linewrap?line_offset:0, no_linewrap, show_winnr);
353 lines_used++;
354 }
355 else
356 {
357 int cur_line_offset = 0;
358
359 while(lines_used < nlines && lines_needed > 0)
360 {
361 scrollback_displayline(winnrs?winnrs[offset + index]:window_nr, mywin2, &cur_lb, offset + index, lines_used, cur_line_offset, 1, show_winnr);
362 cur_line_offset += ncols;
363 lines_used++;
364 lines_needed--;
365 }
366 }
367
368 index++;
369 }
370
371 redraw = 1;
372 }
373
374 if (redraw == 1)
375 {
376 mydoupdate();
377
378 redraw = 0;
379 }
380
381 c = wait_for_keypress(HELP_SCROLLBACK_HELP, 0, NULL, 1);
382 uc = toupper(c);
383
384 if (c == 'q' || c == abort_key || c == KEY_CLOSE || c == KEY_EXIT)
385 {
386 break;
387 }
388 else if (c == 'Q' || c == -1) /* Q: close whole stack of scrollbackwindows, -1: something got closed */
389 {
390 rc = -1;
391 break;
392 }
393 else if (c == 20 && winnrs != NULL) /* ^t */
394 {
395 show_winnr = 1 - show_winnr;
396 redraw = 2;
397 }
398 else if (c == 'x')
399 {
400 send_to_clipboard(pbuf);
401 }
402 else if (c == 'Y')
403 {
404 no_linewrap = !no_linewrap;
405 redraw = 2;
406 line_offset = 0;
407 }
408 else if (c == KEY_F(9) || c == 23) /* ^w */
409 {
410 fullscreen = ! fullscreen;
411
412 compute_text_dimensions(&nlines, &ncols, fullscreen);
413
414 create_scrollback_windows(&mywin1, &mywin2, nlines, ncols, fullscreen);
415
416 redraw = 2;
417 }
418 else if (c == 't')
419 {
420 statistics_menu();
421 }
422 else if ((c == KEY_LEFT || c == KEY_BACKSPACE) && no_linewrap)
423 {
424 if (line_offset > 0)
425 line_offset--;
426
427 redraw = 2;
428 }
429 else if (c == KEY_SLEFT && no_linewrap)
430 {
431 if (line_offset >= (ncols / 2))
432 line_offset -= (ncols / 2);
433 else
434 line_offset = 0;
435
436 redraw = 2;
437 }
438 else if (c == KEY_SRIGHT && no_linewrap)
439 {
440 line_offset += (ncols / 2);
441
442 redraw = 2;
443 }
444 else if (c == KEY_BEG && no_linewrap)
445 {
446 if (line_offset)
447 {
448 line_offset = 0;
449 redraw = 2;
450 }
451 }
452 else if (c == KEY_BTAB)
453 {
454 if (line_offset >= 4)
455 line_offset -= 4;
456 else
457 line_offset = 0;
458
459 redraw = 2;
460 }
461 else if (c == KEY_RIGHT && no_linewrap)
462 {
463 line_offset++;
464 redraw = 2;
465 }
466 else if ((c == KEY_UP ||
467 c == 'y' ||
468 c == 25 || /* ^y */
469 c == 'k' ||
470 /* c == 11 || */ /* ^k */
471 c == 16) /* ^p */
472 && (offset > 0 || (!no_linewrap && line_offset > 0)))
473 {
474 if (no_linewrap)
475 {
476 offset--;
477 }
478 else if (line_offset > 0)
479 {
480 line_offset = max(0, line_offset - ncols);
481 }
482 else
483 {
484 offset--;
485
486 line_offset = (get_lines_needed((cur_lb.be)[offset].Bline, ncols) - 1) * ncols;
487 }
488
489 wmove(mywin2 -> win, 0, 0);
490 winsdelln(mywin2 -> win, 1);
491
492 scrollback_displayline(winnrs?winnrs[offset]:window_nr, mywin2, &cur_lb, offset, 0, line_offset, no_linewrap, show_winnr);
493
494 redraw = 1;
495 }
496 else if ((c == KEY_DOWN ||
497 c == 'e' ||
498 c == 5 || /* ^e */
499 c == 'j' ||
500 c == 14 || /* ^n */
501 c == 13 ||
502 c == KEY_ENTER)
503 && offset < (cur_lb.curpos - 1))
504 {
505 if (no_linewrap)
506 {
507 offset++;
508 }
509 else if (strlen((cur_lb.be)[offset].Bline) > (line_offset + ncols))
510 {
511 line_offset += ncols;
512 }
513 else if (offset < (cur_lb.curpos - 1))
514 {
515 if (strlen((cur_lb.be)[offset].Bline) > (line_offset + ncols))
516 line_offset += ncols;
517 else
518 {
519 line_offset = 0;
520 offset++;
521 }
522 }
523
524 redraw = 2;
525 }
526 else if ((c == KEY_NPAGE ||
527 c == 'f' ||
528 c == 6 || /* ^f */
529 c == ('V' - 65 + 1) || /* ^v */
530 c == ' ' ||
531 c == 'z' ||
532 c == 'u' ||
533 c == ('U' - 65 + 1)) /* ^u */
534 && offset < (cur_lb.curpos - 1))
535 {
536 if (no_linewrap)
537 {
538 offset += nlines;
539 if (offset >= cur_lb.curpos)
540 offset = cur_lb.curpos - 1;
541 }
542 else
543 {
544 int n_lines_to_move = nlines;
545
546 while(n_lines_to_move > 0 && offset < (cur_lb.curpos))
547 {
548 if (line_offset > 0)
549 {
550 if (line_offset + ncols >= strlen((cur_lb.be)[offset].Bline))
551 {
552 line_offset = 0;
553 offset++;
554 n_lines_to_move--;
555 }
556 else
557 {
558 line_offset += ncols;
559 n_lines_to_move--;
560 }
561 }
562 else
563 {
564 n_lines_to_move -= get_lines_needed((cur_lb.be)[offset].Bline, ncols);
565 offset++;
566 }
567 }
568
569 if (n_lines_to_move < 0)
570 line_offset = (-n_lines_to_move) * ncols;
571 }
572
573 redraw = 2;
574 }
575 else if ((c == KEY_PPAGE ||
576 c == 'b' ||
577 c == 2 || /* ^b */
578 c == 'w' ||
579 c == 'd' ||
580 c == 4) /* ^d */
581 && offset > 0)
582 {
583 if (no_linewrap)
584 {
585 offset -= nlines;
586 if (offset < 0)
587 offset = 0;
588 }
589 else
590 {
591 int n_lines_to_move = nlines;
592
593 if (line_offset)
594 n_lines_to_move -= line_offset / ncols;
595
596 while(n_lines_to_move > 0 && offset > 0)
597 {
598 offset--;
599
600 n_lines_to_move -= get_lines_needed((cur_lb.be)[offset].Bline, ncols);
601
602 if (n_lines_to_move < 0)
603 {
604 line_offset = (get_lines_needed((cur_lb.be)[offset].Bline, ncols) + n_lines_to_move) * ncols;
605 }
606 }
607 }
608
609 redraw = 2;
610 }
611 else if ((c == KEY_HOME ||
612 c == 'g' ||
613 c == '<' ||
614 c == KEY_SBEG)
615 && offset > 0)
616 {
617 line_offset = offset = 0;
618 redraw = 2;
619 }
620 else if ((c == KEY_END ||
621 c == 'G' ||
622 c == '>' ||
623 c == KEY_SEND)
624 && offset < (cur_lb. curpos - 1))
625 {
626 offset = cur_lb. curpos - 1;
627 redraw = 2;
628 }
629 else if (uc == 'R' || c == ('R' - 65 + 1) || c == ('L' - 65 + 1) || c == KEY_REFRESH)
630 {
631 redraw = 2;
632 }
633 else if (c == ('K' - 65 + 1) || c == KEY_MARK)
634 {
635 scrollback_find_popup(&find, &case_insensitive);
636
637 if (find)
638 {
639 int rc;
640
641 regfree(&global_highlight_re);
642 myfree(global_highlight_str);
643 global_highlight_str = NULL;
644
645 if ((rc = regcomp(&global_highlight_re, find, (case_insensitive == MY_TRUE?REG_ICASE:0) | REG_EXTENDED)))
646 {
647 regexp_error_popup(rc, &global_highlight_re);
648 myfree(find);
649 }
650 else
651 {
652 global_highlight_str = find;
653 }
654
655 redraw = 2; /* force redraw */
656 }
657
658 }
659 else if (c == 'f' || c == '/' || c == '?' || c == KEY_FIND || c == KEY_SFIND)
660 {
661 char direction = (c == '?' || c == KEY_SFIND) ? -1 : 1;
662
663 scrollback_find_popup(&find, &case_insensitive);
664
665 if (find)
666 {
667 if (scrollback_search_new_window)
668 {
669 if (scrollback_search_to_new_window(&cur_lb, header, find, case_insensitive) == -1)
670 {
671 /* cascaded close */
672 rc = -1;
673 break;
674 }
675 }
676 else
677 {
678 int new_f_index;
679
680 redraw = 2; /* force redraw */
681
682 regfree(&global_highlight_re);
683 myfree(global_highlight_str);
684 global_highlight_str = NULL;
685
686 new_f_index = find_string(&cur_lb, find, 0, direction, case_insensitive);
687 if (new_f_index == -1)
688 {
689 wrong_key();
690 }
691 else
692 {
693 offset = new_f_index;
694 line_offset = 0;
695 }
696 }
697 }
698 }
699 else if (uc == 'N' || c == KEY_NEXT || c == KEY_PREVIOUS || c == KEY_SNEXT)
700 {
701 if (find != NULL)
702 {
703 char direction = (c == 'n' || c == KEY_NEXT) ? 1 : -1;
704 int start_offset = offset + direction;
705 int new_f_index = find_string(&cur_lb, find, start_offset, direction, case_insensitive);
706 if (new_f_index == -1)
707 {
708 wrong_key();
709 }
710 else
711 {
712 redraw = 2; /* force redraw */
713 offset = new_f_index;
714 line_offset = 0;
715 }
716 }
717 else
718 {
719 wrong_key();
720 }
721 }
722 else if (c == 's' || c == KEY_SAVE)
723 {
724 scrollback_savefile(&cur_lb);
725 redraw = 2; /* force redraw */
726 }
727 else if (c == 'h')
728 {
729 show_help(HELP_SCROLLBACK_HELP);
730 }
731 else if (c == 'c')
732 {
733 toggle_colors();
734 redraw = 2; /* force redraw */
735 }
736 else if (c == 'i')
737 {
738 info();
739 }
740 else if (c == 'T')
741 {
742 statistics_menu();
743 }
744 else if (c == 20)
745 {
746 toggle_subwindow_nr();
747 redraw = 2; /* force redraw */
748 }
749 else
750 {
751 wrong_key();
752 }
753 }
754
755 delete_popup(mywin2);
756 if (mywin1)
757 delete_popup(mywin1);
758
759 myfree(find);
760
761 delete_be_in_buffer(&cur_lb);
762
763 return rc;
764 }
765
scrollback(void)766 void scrollback(void)
767 {
768 int window = 0;
769
770 if (nfd > 1)
771 {
772 window = select_window(HELP_SCROLLBACK_SELECT_WINDOW, NULL);
773 }
774
775 if (window != -1)
776 {
777 if (lb[window].bufferwhat == 0)
778 error_popup("Scrollback", HELP_SCROLLBACK_NO_MARK, "Cannot scrollback: buffering is disabled.");
779 }
780
781 if (window != -1 && lb[window].bufferwhat != 0)
782 {
783 int header_size = strlen(pi[window].filename) + 4;
784 char *header = (char *)mymalloc(header_size + 1);
785 snprintf(header, header_size, "%02d] %s", window, pi[window].filename);
786 scrollback_do(window, &lb[window], NULL, header);
787 myfree(header);
788 }
789 }
790
merged_scrollback_with_search(char * search_for,mybool_t case_insensitive)791 void merged_scrollback_with_search(char *search_for, mybool_t case_insensitive)
792 {
793 int lc_size = nfd * sizeof(int);
794 int *last_check = (int *)mymalloc(lc_size);
795 int *winnr = NULL;
796 buffer buf;
797 regex_t reg;
798 int rc;
799
800 memset(last_check, 0x00, lc_size);
801 memset(&buf, 0x00, sizeof(buf));
802
803 /* compile the search string which is supposed to be a valid regular
804 * expression
805 */
806 if (search_for)
807 {
808 if ((rc=regcomp(®, search_for, REG_EXTENDED | (case_insensitive == MY_TRUE?REG_ICASE:0))))
809 {
810 regexp_error_popup(rc, ®);
811 free(last_check);
812 return;
813 }
814 }
815
816 /* merge all windows into one */
817 for(;;)
818 {
819 int loop;
820 double chosen_ts = (double)(((long long int)1) << 62);
821 int chosen_win = -1;
822 int curline;
823 char *string;
824 int checked_all = 0;
825
826 for(loop=0; loop<nfd; loop++)
827 {
828 if (lb[loop].curpos == last_check[loop])
829 {
830 checked_all++;
831 continue;
832 }
833
834 if (search_for != NULL && lb[loop].be[last_check[loop]].Bline != NULL)
835 {
836 rc = regexec(®, lb[loop].be[last_check[loop]].Bline, 0, NULL, 0);
837
838 /* did not match? don't add and continue */
839 if (rc == REG_NOMATCH)
840 {
841 continue;
842 }
843
844 /* is it an error? then popup and abort */
845 if (rc != 0)
846 {
847 regexp_error_popup(rc, ®);
848 break;
849 }
850 }
851
852 if (lb[loop].be[last_check[loop]].ts <= chosen_ts)
853 {
854 chosen_ts = lb[loop].be[last_check[loop]].ts;
855 chosen_win = loop;
856 }
857 }
858
859 if (chosen_win == -1)
860 {
861 if (checked_all == nfd)
862 break;
863
864 for(loop=0; loop<nfd; loop++)
865 {
866 if (lb[loop].curpos > last_check[loop])
867 last_check[loop]++;
868 }
869
870 continue;
871 }
872
873 if (!IS_MARKERLINE(lb[chosen_win].be[last_check[chosen_win]].pi))
874 {
875 /*** ADD LINE TO BUFFER ***/
876 buf.be = (buffered_entry *)myrealloc(buf.be, sizeof(buffered_entry) * (buf.curpos + 1));
877 winnr = (int *)myrealloc(winnr, sizeof(int) * (buf.curpos + 1));
878 curline = buf.curpos++;
879 /* add the logline itself */
880 string = lb[chosen_win].be[last_check[chosen_win]].Bline;
881 if (string)
882 buf.be[curline].Bline = mystrdup(string);
883 else
884 buf.be[curline].Bline = NULL;
885 /* remember pointer to subwindow (required for setting colors etc.) */
886 buf.be[curline].pi = lb[chosen_win].be[last_check[chosen_win]].pi;
887 buf.be[curline].ts = lb[chosen_win].be[last_check[chosen_win]].ts;
888 /* remember window nr. */
889 winnr[curline] = chosen_win;
890 }
891
892 last_check[chosen_win]++;
893 }
894
895 if (buf.curpos == 0)
896 error_popup("Search in all windows", -1, "Nothing found.");
897 else
898 {
899 char *header;
900
901 if (search_for)
902 {
903 char *help = "Searched for: ";
904 int len = strlen(help) + strlen(search_for) + 1;
905 header = mymalloc(len);
906 snprintf(header, len, "%s%s", help, search_for);
907 }
908 else
909 {
910 char *help = "Merge view";
911 header = mymalloc(strlen(help) + 1);
912 sprintf(header, "%s", help);
913 }
914
915 scrollback_do(-1, &buf, winnr, header);
916
917 myfree(header);
918 }
919
920 delete_be_in_buffer(&buf);
921
922 myfree(winnr);
923
924 myfree(last_check);
925 }
926
scrollback_search_to_new_window(buffer * pbuf,char * org_title,char * find_str,mybool_t case_insensitive)927 int scrollback_search_to_new_window(buffer *pbuf, char *org_title, char *find_str, mybool_t case_insensitive)
928 {
929 int loop, rc;
930 regex_t regex;
931 buffer cur_lb;
932 char *new_header;
933
934 /* compile the searchstring (which can be a regular expression) */
935 if ((rc = regcomp(®ex, find_str, REG_EXTENDED | (case_insensitive == MY_TRUE?REG_ICASE:0))))
936 {
937 regexp_error_popup(rc, ®ex);
938 return 0;
939 }
940
941 memset(&cur_lb, 0x00, sizeof(buffer));
942
943 for(loop=0; loop<pbuf -> curpos; loop++)
944 {
945 if ((pbuf -> be)[loop].Bline == NULL)
946 continue;
947
948 if (regexec(®ex, (pbuf -> be)[loop].Bline, 0, NULL, 0) == 0)
949 {
950 cur_lb.be = myrealloc(cur_lb.be, (cur_lb.curpos + 1) * sizeof(buffered_entry));
951 cur_lb.be[cur_lb.curpos].Bline = (pbuf -> be)[loop].Bline;
952 cur_lb.be[cur_lb.curpos].pi = (pbuf -> be)[loop].pi;
953 cur_lb.be[cur_lb.curpos].ts = (pbuf -> be)[loop].ts;
954 cur_lb.curpos++;
955 }
956 }
957
958 new_header = (char *)mymalloc(strlen(org_title) + 1 + strlen(find_str) + 1);
959 sprintf(new_header, "%s %s", org_title, find_str);
960
961 rc = scrollback_do(-1, &cur_lb, NULL, new_header);
962
963 myfree(new_header);
964
965 myfree(cur_lb.be);
966
967 regfree(®ex);
968
969 return rc;
970 }
971