1 /*
2 * window.c: Handles the Main Window stuff for irc. This includes proper
3 * scrolling, saving of screen memory, refreshing, clearing, etc.
4 *
5 * Written By Michael Sandrof
6 *
7 * Copyright(c) 1990
8 * Modified 1996 Colten Edwards
9 */
10
11
12 #include "irc.h"
13 static char cvsrevision[] = "$Id: window.c 440 2013-11-11 13:24:38Z keaston $";
14 CVS_REVISION(window_c)
15 #include "struct.h"
16
17 #include "screen.h"
18 #include "commands.h"
19 #include "exec.h"
20 #include "window.h"
21 #include "vars.h"
22 #include "server.h"
23 #include "list.h"
24 #include "ircterm.h"
25 #include "names.h"
26 #include "ircaux.h"
27 #include "input.h"
28 #include "status.h"
29 #include "output.h"
30 #include "log.h"
31 #include "hook.h"
32 #include "misc.h"
33 #include "cset.h"
34 #include "module.h"
35 #include "gui.h"
36 #define MAIN_SOURCE
37 #include "modval.h"
38
39 /* Resize relatively or absolutely? */
40 #define RESIZE_REL 1
41 #define RESIZE_ABS 2
42
43 Window *invisible_list = NULL; /* list of hidden windows */
44
45 const char *who_from = NULL;
46 unsigned long who_level = LOG_CRAP; /* Log level of message being displayed */
47
48 int in_window_command = 0; /* set to true if we are in window(). This
49 * is used if a put_it() is called within the
50 * window() command. We make sure all
51 * windows are fully updated before doing the
52 * put_it().
53 */
54 extern int dead;
55 static char *onoff[] = {"OFF", "ON"};
56
57 extern unsigned long current_window_level;
58
59 #ifdef WANT_DLL
60 WindowDll *dll_window = NULL;
61 #endif
62
63 /*
64 * window_display: this controls the display, 1 being ON, 0 being OFF. The
65 * DISPLAY var sets this.
66 */
67 unsigned int window_display = 1;
68
69 /*
70 * status_update_flag: if 1, the status is updated as normal. If 0, then all
71 * status updating is suppressed
72 */
73 int status_update_flag = 1;
74
75
76 static void remove_from_invisible_list (Window *window);
77 static void swap_window (Window *v_window, Window *window);
78 static Window *get_next_window (Window *);
79 static Window *get_previous_window (Window *);
80 static void revamp_window_levels (Window *window);
81 static void resize_window_display (Window *window);
82 static Window *window_next (Window *window, char **args, char *usage);
83 static Window *window_previous (Window *window, char **args, char *usage);
84
85
86 /*
87 * this is set to the window output should appear in.
88 */
89 Window *target_window = NULL;
90
91 Window *current_window = NULL;
92
93 void *default_output_function = BX_add_to_window;
94
95
96 #ifdef GUI
97 MenuStruct *findmenu(char *menuname);
98 #endif /* GUI */
99
100 /*
101 * new_window: This creates a new window on the screen. It does so by either
102 * splitting the current window, or if it can't do that, it splits the
103 * largest window. The new window is added to the window list and made the
104 * current window
105 */
BX_new_window(Screen * screen)106 Window *BX_new_window(Screen *screen)
107 {
108 Window *new;
109 Window *tmp = NULL;
110 unsigned int new_refnum = 1;
111
112 if (dumb_mode && current_window)
113 return NULL;
114
115 new = (Window *) new_malloc(sizeof(Window));
116
117 new->output_func = default_output_function;
118 new->update_status = NULL;
119
120 tmp = NULL;
121 while ((traverse_all_windows(&tmp)))
122 {
123 if (tmp->refnum == new_refnum)
124 {
125 new_refnum++;
126 tmp = NULL;
127 }
128 }
129 new->refnum = new_refnum;
130 new->name = NULL;
131
132 if (current_window)
133 new->server = current_window->server;
134 else
135 new->server = primary_server;
136
137
138 #if 0
139 if (!current_window)
140 new->window_level = LOG_ALL;
141 else
142 #endif
143 new->window_level = LOG_NONE;
144
145 new->lastlog_level = real_lastlog_level();
146 new->lastlog_max = get_int_var(LASTLOG_VAR);
147 new->status_split = 1;
148 new->scratch_line = -1;
149
150 #ifdef DEFAULT_DOUBLE_STATUS
151 new->double_status = DEFAULT_DOUBLE_STATUS;
152 #else
153 if (new->refnum == 1)
154 new->double_status = 1;
155 else
156 new->double_status = 0;
157 #endif
158
159 #ifdef DEFAULT_STATUS_LINES
160 new->status_lines = DEFAULT_STATUS_LINES;
161 #endif
162
163 new->display_size = 1;
164 new->old_size = 1;
165 new->visible = 1;
166 new->repaint_start = 0;
167 new->repaint_end = -1;
168
169 new->screen = screen;
170 new->next = new->prev = NULL;
171
172 new->notify_level = real_notify_level();
173
174 new->display_buffer_max = get_int_var(SCROLLBACK_VAR);
175 new->hold_mode = get_int_var(HOLD_MODE_VAR);
176
177 new->mangler = logfile_line_mangler;
178
179 create_wsets_for_window(new);
180 if (screen)
181 {
182 if (add_to_window_list(screen, new))
183 {
184 set_screens_current_window(screen, new);
185 term_flush();
186 do_hook(WINDOW_CREATE_LIST, "%d", new->refnum);
187
188 }
189 else
190 {
191 new_free(&new);
192 return NULL;
193 }
194 }
195 else
196 add_to_invisible_list(new);
197 build_status(new, NULL, 0);
198
199 make_window_current(new);
200 resize_window_display(new);
201 return (new);
202 }
203
204 /*
205 * delete_window: This deletes the given window. It frees all data and
206 * structures associated with the window, and it adjusts the other windows so
207 * they will display correctly on the screen.
208 */
BX_delete_window(Window * window)209 void BX_delete_window(Window *window)
210 {
211 char buffer[BIG_BUFFER_SIZE + 1];
212
213 if (window == NULL)
214 window = current_window;
215 if (window->screen && (window->screen->visible_windows == 1))
216 {
217 if (invisible_list)
218 {
219 window->deceased = 1;
220 swap_window(window, invisible_list);
221 window = invisible_list;
222 }
223 else if (!dead)
224 {
225 if (!get_int_var(WINDOW_QUIET_VAR))
226 say("You can't kill the last window!");
227 return;
228 }
229 else
230 {
231 window->deceased = 1;
232 set_screens_current_window(window->screen, NULL);
233 }
234 }
235 if (window->name)
236 strlcpy(buffer, window->name, sizeof buffer);
237 else
238 snprintf(buffer, sizeof buffer, "%u", window->refnum);
239
240 /*
241 * If this window is the "previous" window, then we make the current
242 * window the "previous" window. Um. right.
243 */
244 if (!dead && window->screen && window->screen->last_window_refnum == window->refnum)
245 window->screen->last_window_refnum = window->screen->current_window->refnum;
246
247 move_window_channels(window);
248
249 new_free(&window->query_nick);
250 new_free(&window->query_host);
251 new_free(&window->query_cmd);
252 new_free(&window->current_channel);
253 new_free(&window->bind_channel);
254 new_free(&window->waiting_channel);
255 new_free(&window->logfile);
256 new_free(&window->name);
257
258 /*
259 * Free off the display
260 */
261 {
262 Display *next;
263 while (window->top_of_scrollback)
264 {
265 next = window->top_of_scrollback->next;
266 new_free(&window->top_of_scrollback->line);
267 new_free((char **)&window->top_of_scrollback);
268 window->display_buffer_size--;
269 window->top_of_scrollback = next;
270 }
271 window->display_ip = NULL;
272 if (window->display_buffer_size != 0)
273 ircpanic("display_buffer size is %d. should be 0", window->display_buffer_size);
274 }
275
276 /*
277 * Free off the lastlog
278 */
279 while (window->lastlog_size)
280 remove_from_lastlog(window);
281
282 /*
283 * Free off the nick list
284 */
285 {
286 NickList *next;
287
288 while (window->nicks)
289 {
290 next = window->nicks->next;
291 new_free(&window->nicks->nick);
292 new_free(&window->nicks->host);
293 new_free((char **)&window->nicks);
294 window->nicks = next;
295 }
296 }
297
298 free_formats(window);
299
300 if (window->screen)
301 remove_window_from_screen(window);
302 else
303 remove_from_invisible_list(window);
304
305 /*
306 * If its the current window, choose another one.
307 */
308 if (window->screen && window->screen->current_window == window)
309 set_screens_current_window(window->screen, NULL);
310 if (window == current_window)
311 {
312 if (window == last_input_screen->current_window)
313 make_window_current(last_input_screen->window_list);
314 else
315 make_window_current(NULL);
316 }
317 if (target_window && (window == target_window))
318 target_window = NULL;
319 new_free((char **)&window);
320 window_check_servers(current_window->server);
321 do_hook(WINDOW_KILL_LIST, "%s", buffer);
322 set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
323 update_input(UPDATE_ALL);
324 }
325
326 /*
327 * new_traverse_all_windows: Based on the idea from phone that you should
328 * be able to do more than one iteration simultaneously.
329 *
330 * To initialize, *ptr should be NULL. The function will return 1 each time
331 * *ptr is set to the next valid window. When the function returns 0, then
332 * you have iterated all windows.
333 */
BX_traverse_all_windows(Window ** ptr)334 int BX_traverse_all_windows (Window **ptr)
335 {
336 /*
337 * If this is the first time through...
338 */
339 if (!*ptr)
340 {
341 Screen *screen = screen_list;
342 while (screen && (!screen->alive || !screen->window_list))
343 screen = screen->next;
344
345 if (!screen && !invisible_list)
346 return 0;
347 else if (!screen)
348 *ptr = invisible_list;
349 else
350 *ptr = screen->window_list;
351 }
352
353 /*
354 * As long as there is another window on this screen, keep going.
355 */
356 else if ((*ptr)->next)
357 {
358 *ptr = (*ptr)->next;
359 }
360
361 /*
362 * If there are no more windows on this screen, but we do belong to
363 * a screen (eg, we're not invisible), try the next screen
364 */
365 else if ((*ptr)->screen)
366 {
367 /*
368 * Skip any dead screens
369 */
370 Screen *ns = (*ptr)->screen->next;
371 while (ns && (!ns->alive || !ns->window_list))
372 ns = ns->next;
373
374 /*
375 * If there are no other screens, then if there is a list
376 * of hidden windows, try that. Otherwise we're done.
377 */
378 if (!ns && !invisible_list)
379 return 0;
380 else if (!ns)
381 *ptr = invisible_list;
382 else
383 *ptr = ns->window_list;
384 }
385
386 /*
387 * Otherwise there are no other windows, and we're not on a screen
388 * (eg, we're hidden), so we're all done here.
389 */
390 else
391 return 0;
392
393 /*
394 * If we get here, we're in business!
395 */
396 return 1;
397 }
398
remove_from_invisible_list(Window * window)399 static void remove_from_invisible_list(Window *window)
400 {
401
402 if (window->prev)
403 window->prev->next = window->next;
404 else
405 invisible_list = window->next;
406 if (window->next)
407 window->next->prev = window->prev;
408 }
409
BX_add_to_invisible_list(Window * window)410 void BX_add_to_invisible_list(Window *window)
411 {
412 if ((window->next = invisible_list) != NULL)
413 invisible_list->prev = window;
414 invisible_list = window;
415 window->prev = NULL;
416 window->visible = 0;
417 if (window->screen)
418 window->columns = window->screen->co;
419 else
420 window->columns = current_term->TI_cols;
421 window->screen = NULL;
422 }
423
424 /*
425 * add_to_window_list: This inserts the given window into the visible window
426 * list (and thus adds it to the displayed windows on the screen). The
427 * window is added by splitting the current window. If the current window is
428 * too small, the next largest window is used. The added window is returned
429 * as the function value or null is returned if the window couldn't be added
430 */
BX_add_to_window_list(Screen * screen,Window * new)431 Window *BX_add_to_window_list(Screen *screen, Window *new)
432 {
433 Window *biggest = NULL,
434 *tmp;
435
436 screen->visible_windows++;
437 new->screen = screen;
438 new->visible = 1;
439 new->miscflags &= ~WINDOW_NOTIFIED;
440 if (!screen->current_window)
441 {
442 screen->window_list_end = screen->window_list = new;
443 if (dumb_mode)
444 {
445 new->display_size = 24; /* what the hell */
446 set_screens_current_window(screen, new);
447 return (new);
448 }
449 recalculate_windows(screen);
450 }
451 else
452 {
453 /* split current window, or find a better window to split */
454 if ((screen->current_window->display_size < 4) ||
455 get_int_var(ALWAYS_SPLIT_BIGGEST_VAR))
456 {
457 int size = 0;
458
459 for (tmp = screen->window_list; tmp; tmp = tmp->next)
460 {
461 if (tmp->absolute_size)
462 continue;
463 if (tmp->display_size > size)
464 {
465 size = tmp->display_size;
466 biggest = tmp;
467 }
468 }
469 if (!biggest/* || size < 4 */)
470 {
471 if (!get_int_var(WINDOW_QUIET_VAR))
472 say("Not enough room for another window!");
473 screen->visible_windows--;
474 return (NULL);
475 }
476 }
477 else
478 biggest = screen->current_window;
479
480 if ((new->prev = biggest->prev) != NULL)
481 new->prev->next = new;
482 else
483 screen->window_list = new;
484
485 new->next = biggest;
486 biggest->prev = new;
487 biggest->display_size /= 2;
488 new->display_size = biggest->display_size;
489 recalculate_windows(screen);
490 }
491 return (new);
492 }
493
494 /*
495 * remove_from_window_list: this removes the given window from the list of
496 * visible windows. It closes up the hole created by the windows abnsense in
497 * a nice way
498 */
BX_remove_window_from_screen(Window * window)499 void BX_remove_window_from_screen(Window *window)
500 {
501 if (!window->visible || !window->screen)
502 ircpanic("This window is not on a screen");
503
504 /*
505 * We used to go to greath lengths to figure out how to fill
506 * in the space vacated by this window. Now we dont sweat that.
507 * we just blow away the window and then recalculate the entire
508 * screen.
509 */
510 if (window->prev)
511 window->prev->next = window->next;
512 else
513 window->screen->window_list = window->next;
514
515 if (window->next)
516 window->next->prev = window->prev;
517 else
518 window->screen->window_list_end = window->prev;
519
520 if (!--window->screen->visible_windows)
521 return;
522
523 if (window->screen->current_window == window)
524 set_screens_current_window(window->screen, NULL);
525
526 if (window->refnum == window->screen->last_window_refnum)
527 window->screen->last_window_refnum = window->screen->current_window->refnum;
528
529 if (window == window->screen->current_window)
530 make_window_current(last_input_screen->window_list);
531 else
532 make_window_current(NULL);
533
534 recalculate_windows(window->screen);
535 }
536
537 /*
538 * recalculate_window_positions: This runs through the window list and
539 * re-adjusts the top and bottom fields of the windows according to their
540 * current positions in the window list. This doesn't change any sizes of
541 * the windows
542 */
BX_recalculate_window_positions(Screen * screen)543 void BX_recalculate_window_positions(Screen *screen)
544 {
545 Window *tmp;
546 int top;
547
548 if (!screen)
549 return;
550 top = 0;
551 for (tmp = screen->window_list; tmp; tmp = tmp->next)
552 {
553 tmp->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
554 tmp->top = top;
555 tmp->bottom = top + tmp->display_size + tmp->status_lines;
556 top += tmp->display_size + tmp->status_lines + 1 + tmp->double_status;
557 }
558 }
559
560 /*
561 * swap_window: This swaps the given window with the current window. The
562 * window passed must be invisible. Swapping retains the positions of both
563 * windows in their respective window lists, and retains the dimensions of
564 * the windows as well
565 */
swap_window(Window * v_window,Window * window)566 static void swap_window(Window *v_window, Window *window)
567 {
568 if (!window)
569 {
570 if (!get_int_var(WINDOW_QUIET_VAR))
571 say("The window to be swapped in does not exist.");
572 return;
573 }
574
575 if (window->visible || !v_window->visible)
576 {
577 if (!get_int_var(WINDOW_QUIET_VAR))
578 say("You can only SWAP a hidden window with a visible window.");
579 return;
580 }
581
582 v_window->screen->last_window_refnum = v_window->refnum;
583 remove_from_invisible_list(window);
584
585 window->top = v_window->top;
586
587 window->display_size = v_window->display_size +
588 v_window->double_status -
589 window->double_status;
590
591 window->bottom = window->top + window->display_size + window->status_lines;
592
593 window->visible = 1;
594 window->screen = v_window->screen;
595
596 if (v_window->screen->current_window == v_window)
597 v_window->screen->current_window = window;
598
599 /*
600 * Put the window to be swapped into the screen list
601 */
602 if ((window->prev = v_window->prev))
603 window->prev->next = window;
604 else
605 window->screen->window_list = window;
606
607 if ((window->next = v_window->next))
608 window->next->prev = window;
609 else
610 window->screen->window_list_end = window;
611 add_to_invisible_list(v_window);
612
613 if (v_window == current_window)
614 make_window_current(window);
615
616 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
617 window->miscflags &= ~WINDOW_NOTIFIED;
618 update_input(UPDATE_ALL);
619 set_screens_current_window(window->screen, window);
620 recalculate_windows(window->screen);
621 reset_display_target();
622 do_hook(WINDOW_SWAP_LIST, "%d %d", v_window->refnum, window->refnum);
623 }
624
625 /*
626 * move_window: This moves a window offset positions in the window list. This
627 * means, of course, that the window will move on the screen as well
628 */
BX_move_window(Window * window,int offset)629 void BX_move_window(Window *window, int offset)
630 {
631 Window *tmp,
632 *last;
633 int win_pos,
634 pos;
635
636 if (offset == 0 || !window->screen)
637 return;
638 last = NULL;
639 for (win_pos = 0, tmp = window->screen->window_list; tmp;
640 tmp = tmp->next, win_pos++)
641 {
642 if (window == tmp)
643 break;
644 last = tmp;
645 }
646 if (!tmp)
647 return;
648 if (!last)
649 window->screen->window_list = tmp->next;
650 else
651 last->next = tmp->next;
652 if (tmp->next)
653 tmp->next->prev = last;
654 else
655 window->screen->window_list_end = last;
656
657 win_pos = (offset + win_pos) % window->screen->visible_windows;
658 if (win_pos < 0)
659 win_pos = window->screen->visible_windows + win_pos;
660
661 last = NULL;
662 for (pos = 0, tmp = window->screen->window_list;
663 pos != win_pos; tmp = tmp->next, pos++)
664 last = tmp;
665 if (!last)
666 window->screen->window_list = window;
667 else
668 last->next = window;
669
670 if (tmp)
671 tmp->prev = window;
672 else
673 window->screen->window_list_end = window;
674
675 window->prev = last;
676 window->next = tmp;
677 recalculate_window_positions(window->screen);
678 }
679
680 /*
681 * resize_window: if 'how' is RESIZE_REL, then this will increase or decrease
682 * the size of the given window by offset lines (positive offset increases,
683 * negative decreases). If 'how' is RESIZE_ABS, then this will set the
684 * absolute size of the given window.
685 * Obviously, with a fixed terminal size, this means that some other window
686 * is going to have to change size as well. Normally, this is the next
687 * window in the window list (the window below the one being changed) unless
688 * the window is the last in the window list, then the previous window is
689 * changed as well
690 */
BX_resize_window(int how,Window * window,int offset)691 void BX_resize_window(int how, Window *window, int offset)
692 {
693 Window *other;
694 int after,
695 window_size,
696 other_size;
697
698 if (!window)
699 window = current_window;
700
701 if (!window->visible)
702 {
703 if (!get_int_var(WINDOW_QUIET_VAR))
704 say("You cannot change the size of hidden windows!");
705 return;
706 }
707
708 if (how == RESIZE_ABS)
709 {
710 offset -= window->display_size;
711 how = RESIZE_REL;
712 }
713
714 after = 1;
715 other = window;
716
717 do
718 {
719 if (other->next)
720 other = other->next;
721 else
722 {
723 other = window->screen->window_list;
724 after = 0;
725 }
726
727 if (other == window)
728 {
729 say("Can't change the size of this window!");
730 return;
731 }
732
733 if (other->absolute_size)
734 continue;
735 }
736 while (/*other->absolute_size || */other->display_size < offset);
737
738 window_size = window->display_size + offset;
739 other_size = other->display_size - offset;
740
741 #if 0
742 if (how == RESIZE_REL)
743 {
744 window_size = window->display_size + offset;
745 other_size = other->display_size - offset;
746 }
747 else /* absolute size */
748 {
749 /*
750 * How much its growing/shrinking by. if
751 * offset > display_size, then window_size < 0.
752 * and other window is shrinking. If offset < display_size,
753 * the window_size > 0, and other_window is growing.
754 */
755 window_size = offset;
756 offset -= window->display_size;
757 other_size = other->display_size - offset;
758 }
759 #endif
760
761 if ((window_size < 0) || (other_size < 0))
762 {
763 if (!get_int_var(WINDOW_QUIET_VAR))
764 say("Not enough room to resize this window!");
765 return;
766 }
767
768 window->display_size = window_size;
769 other->display_size = other_size;
770 recalculate_windows(window->screen);
771 }
772
773 /*
774 * resize_display: After determining that the screen has changed sizes, this
775 * resizes all the internal stuff. If the screen grew, this will add extra
776 * empty display entries to the end of the display list. If the screen
777 * shrank, this will remove entries from the end of the display list. By
778 * doing this, we try to maintain as much of the display as possible.
779 *
780 * This has now been improved so that it returns enough information for
781 * redraw_resized to redisplay the contents of the window without having
782 * to redraw too much.
783 */
resize_window_display(Window * window)784 void resize_window_display(Window *window)
785 {
786 int cnt = 0, i;
787 Display *tmp;
788
789 if (dumb_mode)
790 return;
791 /*
792 * This is called in new_window to initialize the
793 * display the first time
794 */
795 if (!window->top_of_scrollback)
796 {
797 window->top_of_scrollback = new_display_line(NULL);
798 window->top_of_scrollback->line = NULL;
799 window->top_of_scrollback->next = NULL;
800 window->display_buffer_size = 1;
801 window->display_ip = window->top_of_scrollback;
802 window->top_of_display = window->top_of_scrollback;
803 window->ceiling_of_display = window->top_of_display;
804 window->old_size = 1;
805 }
806 else if (window->scrollback_point)
807 ;
808 else
809 {
810
811 /*
812 * Find out how much the window has changed by
813 */
814 cnt = window->display_size - window->old_size;
815 tmp = window->top_of_display;
816
817 /*
818 * If it got bigger, move the top_of_display back.
819 */
820 if (cnt > 0)
821 {
822 for (i = 0; i < cnt; i++)
823 {
824 if (!tmp || !tmp->prev || tmp == window->ceiling_of_display)
825 break;
826 tmp = tmp->prev;
827 }
828 }
829
830 /*
831 * If it got smaller, then move the top_of_display up
832 */
833 else if (cnt < 0)
834 {
835 /* Use any whitespace we may have lying around */
836 cnt += (window->old_size - window->distance_from_display);
837 for (i = 0; i > cnt; i--)
838 {
839 if (tmp == window->display_ip)
840 break;
841 tmp = tmp->next;
842 }
843 }
844 window->top_of_display = tmp;
845 recalculate_window_cursor(window);
846 }
847
848 /*
849 * Mark the window for redraw and store the new window size.
850 */
851 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
852 window->old_size = window->display_size;
853 return;
854 }
855
856 /*
857 * redraw_all_windows: This basically clears and redraws the entire display
858 * portion of the screen. All windows and status lines are draws. This does
859 * nothing for the input line of the screen. Only visible windows are drawn
860 */
BX_redraw_all_windows(void)861 void BX_redraw_all_windows(void)
862 {
863 Window *tmp = NULL;
864
865 if (dumb_mode)
866 return;
867 while (traverse_all_windows(&tmp))
868 tmp->update = REDRAW_STATUS | REDRAW_DISPLAY_FAST;
869 }
870
871 /*
872 * Rebalance_windows: this is called when you want all the windows to be
873 * rebalanced, except for those who have a set size.
874 */
BX_rebalance_windows(Screen * screen)875 void BX_rebalance_windows (Screen *screen)
876 {
877 Window *tmp;
878 int each, extra;
879 int window_resized = 0, window_count = 0;
880
881 if (dumb_mode)
882 return;
883
884 /*
885 * Two passes -- first figure out how much we need to balance,
886 * and how many windows there are to balance
887 */
888 for (tmp = screen->window_list; tmp; tmp = tmp->next)
889 {
890 if (tmp->absolute_size)
891 continue;
892 window_resized += tmp->display_size;
893 window_count++;
894 }
895
896 if (!window_count)
897 {
898 yell("All the windows on this screen are fixed");
899 return;
900 }
901
902 each = window_resized / window_count;
903 extra = window_resized % window_count;
904
905 /*
906 * And then go through and fix everybody
907 */
908 for (tmp = screen->window_list; tmp; tmp = tmp->next)
909 {
910 if (tmp->absolute_size)
911 ;
912 else
913 {
914 tmp->display_size = each;
915 if (extra)
916 tmp->display_size++, extra--;
917 }
918 }
919 recalculate_window_positions(screen);
920 }
921
922
923
924 /*
925 * recalculate_windows: this is called when the terminal size changes (as
926 * when an xterm window size is changed). It recalculates the sized and
927 * positions of all the windows. Currently, all windows are rebalanced and
928 * window size proportionality is lost
929 */
BX_recalculate_windows(Screen * screen)930 void BX_recalculate_windows (Screen *screen)
931 {
932 int old_li = 1;
933 int excess_li = 0;
934 Window *tmp;
935 int window_count = 0;
936 int window_resized = 0;
937 int offset;
938 int split = 0;
939
940 if (dumb_mode)
941 return;
942 #ifdef GUI
943 current_term->TI_lines = screen->li;
944 current_term->TI_cols = screen->co;
945 #endif
946
947 if (!screen) /* it's a hidden window. ignore this */
948 return;
949 /*
950 * If its a new window, just set it and be done with it.
951 */
952 if (screen && !screen->current_window)
953 {
954 screen->window_list->top = 0;
955 screen->window_list->display_size = current_term->TI_lines - 2 - screen->window_list->double_status;
956 screen->window_list->bottom = current_term->TI_lines - 2 - screen->window_list->double_status;
957 old_li = current_term->TI_lines;
958 return;
959 }
960
961 /*
962 * Expanding the screen takes two passes. In the first pass,
963 * We figure out how many windows will be resized. If none can
964 * be rebalanced, we add the whole shebang to the last one.
965 */
966 for (tmp = screen->window_list; tmp; tmp = tmp->next)
967 {
968 old_li += tmp->display_size + tmp->double_status + 1;
969 if (tmp->absolute_size && (window_count || tmp->next))
970 continue;
971 window_resized += tmp->display_size;
972 window_count++;
973 if (tmp->status_lines)
974 split += tmp->status_lines;
975 }
976
977 excess_li = current_term->TI_lines - old_li - split;
978
979 for (tmp = screen->window_list; tmp; tmp = tmp->next)
980 {
981 if (tmp->absolute_size && tmp->next)
982 ;
983 else
984 {
985 /*
986 * The number of lines this window gets is:
987 * The number of lines available for resizing times
988 * the percentage of the resizeable screen the window
989 * covers.
990 */
991 if (tmp->next && window_resized)
992 offset = (tmp->display_size * excess_li) / window_resized;
993 else
994 offset = excess_li;
995
996 tmp->display_size += offset;
997 if (tmp->display_size < 0)
998 tmp->display_size = 1;
999 excess_li -= offset;
1000 tmp->bottom = tmp->bottom - tmp->status_lines;
1001 }
1002 }
1003
1004 recalculate_window_positions(screen);
1005 }
1006
1007 /*
1008 * update_all_windows: This goes through each visible window and draws the
1009 * necessary portions according the the update field of the window.
1010 */
BX_update_all_windows()1011 void BX_update_all_windows()
1012 {
1013 Window *tmp = NULL;
1014 if (in_window_command)
1015 return;
1016
1017 while (traverse_all_windows(&tmp))
1018 {
1019 if (tmp->display_size != tmp->old_size)
1020 resize_window_display(tmp);
1021 if (tmp->visible && tmp->update)
1022 {
1023 int fast_window = tmp->update & REDRAW_DISPLAY_FAST;
1024 int full_window = tmp->update & REDRAW_DISPLAY_FULL;
1025 int r_status = tmp->update & REDRAW_STATUS;
1026 int u_status = tmp->update & UPDATE_STATUS;
1027
1028 if (full_window || fast_window)
1029 repaint_window(tmp, tmp->repaint_start, tmp->repaint_end);
1030
1031 if (tmp->update_status)
1032 (tmp->update_status)(tmp);
1033 else if (r_status)
1034 update_window_status(tmp, 1);
1035 else if (u_status)
1036 update_window_status(tmp, 0);
1037 }
1038 tmp->update = 0;
1039 tmp->repaint_start = 0;
1040 tmp->repaint_end = -1;
1041 }
1042 update_input(UPDATE_JUST_CURSOR);
1043 }
1044
1045 /*
1046 * goto_window: This will switch the current window to the window numbered
1047 * "which", where which is 0 through the number of visible windows on the
1048 * screen. The which has nothing to do with the windows refnum.
1049 */
BX_goto_window(Screen * s,int which)1050 void BX_goto_window(Screen *s, int which)
1051 {
1052 Window *tmp;
1053 int i;
1054
1055
1056 if (!s || which == 0)
1057 return;
1058
1059 if ((which < 0) || (which > s->visible_windows))
1060 {
1061 if (!get_int_var(WINDOW_QUIET_VAR))
1062 say("GOTO: Illegal value");
1063 return;
1064 }
1065 tmp = s->window_list;
1066 for (i = 1; i < which; i++)
1067 tmp = tmp->next;
1068
1069 set_screens_current_window(s, tmp);
1070 make_window_current(tmp);
1071 }
1072
1073 /*
1074 * hide_window: sets the given window to invisible and recalculates remaing
1075 * windows to fill the entire screen
1076 */
BX_hide_window(Window * window)1077 void BX_hide_window(Window *window)
1078 {
1079 if (!window->screen)
1080 {
1081 say("You can't hide an invisible window.");
1082 return;
1083 }
1084 if (window->screen->visible_windows == 1)
1085 {
1086 if (!get_int_var(WINDOW_QUIET_VAR))
1087 say("You can't hide the last window.");
1088 return;
1089 }
1090 if (window->screen)
1091 {
1092 remove_window_from_screen(window);
1093 add_to_invisible_list(window);
1094 }
1095 }
1096
1097 /*
1098 * swap_last_window: This swaps the current window with the last window
1099 * that was hidden.
1100 */
1101
BX_swap_last_window(char key,char * ptr)1102 void BX_swap_last_window(char key, char *ptr)
1103 {
1104 if (!invisible_list || !current_window->screen)
1105 return;
1106
1107 swap_window(current_window, invisible_list);
1108 reset_display_target();
1109 update_all_windows();
1110 cursor_to_input();
1111 }
1112
1113 /*
1114 * swap_next_window: This swaps the current window with the next hidden
1115 * window.
1116 */
1117
BX_swap_next_window(char key,char * ptr)1118 void BX_swap_next_window(char key, char *ptr)
1119 {
1120 window_next(current_window, NULL, NULL);
1121 update_all_windows();
1122 }
1123
1124 /*
1125 * swap_previous_window: This swaps the current window with the next
1126 * hidden window.
1127 */
1128
BX_swap_previous_window(char key,char * ptr)1129 void BX_swap_previous_window(char key, char *ptr)
1130 {
1131 window_previous(current_window, NULL, NULL);
1132 cursor_to_input();
1133 update_all_windows();
1134 }
1135
1136 /* show_window: This makes the given window visible. */
BX_show_window(Window * window)1137 void BX_show_window(Window *window)
1138 {
1139 if (!window->screen)
1140 {
1141 remove_from_invisible_list(window);
1142 if ((window == current_window) && !current_window->screen)
1143 window->screen = last_input_screen; /* What the hey */
1144 if (!add_to_window_list(current_window->screen, window))
1145 add_to_invisible_list(window);
1146 }
1147 make_window_current(window);
1148 if (!window->screen)
1149 {
1150 yell("ERROR ERROR ERROR. screen == NULL");
1151 return;
1152 }
1153 set_screens_current_window(window->screen, window);
1154 return;
1155 }
1156
1157 /*
1158 * XXXX i have no idea if this belongs here.
1159 */
BX_get_status_by_refnum(unsigned refnum,unsigned line)1160 char *BX_get_status_by_refnum(unsigned refnum, unsigned line)
1161 {
1162 Window *the_window;
1163
1164 if ((the_window = get_window_by_refnum(refnum)))
1165 {
1166 if (line > the_window->double_status)
1167 return empty_string;
1168
1169 return the_window->wset->status_line[line];
1170 }
1171 else
1172 return empty_string;
1173 }
1174
1175 /*
1176 * get_window_by_desc: Given either a refnum or a name, find that window
1177 */
BX_get_window_by_desc(const char * stuff)1178 Window *BX_get_window_by_desc (const char *stuff)
1179 {
1180 Window *w = NULL;
1181 do
1182 {
1183 if ((w = get_window_by_name(stuff)))
1184 break;
1185 if (is_number(stuff) && (w = get_window_by_refnum(my_atol(stuff))))
1186 break;
1187 if (*stuff == '#')
1188 {
1189 stuff++;
1190 continue;
1191 }
1192 } while (0);
1193 return w;
1194 }
1195
1196 /*
1197 * get_window_by_refnum: Given a reference number to a window, this returns a
1198 * pointer to that window if a window exists with that refnum, null is
1199 * returned otherwise. The "safe" way to reference a window is throught the
1200 * refnum, since a window might be delete behind your back and and Window
1201 * pointers might become invalid.
1202 */
BX_get_window_by_refnum(unsigned int refnum)1203 Window * BX_get_window_by_refnum(unsigned int refnum)
1204 {
1205 Window *tmp = NULL;
1206
1207 if (refnum < 0)
1208 return NULL;
1209 if (refnum == 0)
1210 return current_window;
1211 else while ((traverse_all_windows(&tmp)))
1212 {
1213 if (tmp->refnum == refnum)
1214 return (tmp);
1215 }
1216 return NULL;
1217 }
1218
1219 /*
1220 * get_window: this parses out any window (visible or not) and returns a
1221 * pointer to it
1222 */
BX_get_visible_by_refnum(char * args)1223 int BX_get_visible_by_refnum (char *args)
1224 {
1225 char *arg;
1226 Window *tmp;
1227
1228 if ((arg = next_arg(args, &args)) != NULL)
1229 {
1230 if (is_number(arg))
1231 {
1232 if ((tmp = get_window_by_refnum(my_atol(arg))) != NULL)
1233 return tmp->visible;
1234 }
1235 if ((tmp = get_window_by_name(arg)) != NULL)
1236 return tmp->visible;
1237
1238 return -1;
1239 }
1240 return -1;
1241 }
1242
1243 /*
1244 * get_window_by_name: returns a pointer to a window with a matching logical
1245 * name or null if no window matches
1246 */
BX_get_window_by_name(const char * name)1247 Window * BX_get_window_by_name(const char *name)
1248 {
1249 Window *tmp = NULL;
1250
1251 while ((traverse_all_windows(&tmp)))
1252 {
1253 if (tmp->name && (my_stricmp(tmp->name, name) == 0))
1254 return (tmp);
1255 }
1256 return (NULL);
1257 }
1258
1259
1260 /*
1261 * get_next_window: This returns a pointer to the next *visible* window in
1262 * the window list. It automatically wraps at the end of the list back to
1263 * the beginning of the list
1264 */
get_next_window(Window * w)1265 static Window * get_next_window (Window *w)
1266 {
1267 Window *last = w;
1268 Window *new = w;
1269
1270 if (!w || !w->screen)
1271 last = new = w = current_window;
1272
1273 do
1274 {
1275 if (new->next)
1276 new = new->next;
1277 else
1278 new = w->screen->window_list;
1279 }
1280 while (new && new->skip && new != last);
1281 return new;
1282 }
1283
1284 /*
1285 * get_previous_window: this returns the previous *visible* window in the
1286 * window list. This automatically wraps to the last window in the window
1287 * list
1288 */
get_previous_window(Window * w)1289 static Window * get_previous_window (Window *w)
1290 {
1291 Window *last = w;
1292 Window *new = w;
1293
1294 if (!w || !w->screen)
1295 last = new = w = current_window;
1296
1297 do
1298 {
1299 if (new->prev)
1300 new = new->prev;
1301 else
1302 new = w->screen->window_list_end;
1303 }
1304 while (new->skip && new != last);
1305
1306 return new;
1307 }
1308
1309 /*
1310 * next_window: This switches the current window to the next visible window
1311 */
BX_next_window(char key,char * ptr)1312 void BX_next_window(char key, char *ptr)
1313 {
1314 Window *w;
1315 if (!last_input_screen)
1316 return;
1317 if (last_input_screen->visible_windows == 1)
1318 return;
1319 w = get_next_window(last_input_screen->current_window);
1320 make_window_current(w);
1321 set_screens_current_window(last_input_screen, w);
1322 update_all_windows();
1323 set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
1324 }
1325
1326
1327 /*
1328 * previous_window: This switches the current window to the previous visible
1329 * window
1330 */
BX_previous_window(char key,char * ptr)1331 void BX_previous_window(char key, char *ptr)
1332 {
1333 Window *w;
1334
1335 if (!last_input_screen || last_input_screen->visible_windows == 1)
1336 return;
1337 w = get_previous_window(last_input_screen->current_window);
1338 make_window_current(w);
1339 set_screens_current_window(last_input_screen, w);
1340 update_all_windows();
1341 set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
1342 }
1343
1344
1345
1346 /*
1347 * update_window_status: This updates the status line for the given window.
1348 * If the refresh flag is true, the entire status line is redrawn. If not,
1349 * only some of the changed portions are redrawn
1350 */
BX_update_window_status(Window * window,int refresh)1351 void BX_update_window_status(Window *window, int refresh)
1352 {
1353 if (!window)
1354 window = current_window;
1355 if (!window || !window->visible || !status_update_flag || never_connected)
1356 return;
1357 if (refresh)
1358 {
1359 new_free(&(window->wset->status_line[0]));
1360 new_free(&(window->wset->status_line[1]));
1361 new_free(&(window->wset->status_line[2]));
1362 }
1363 make_status(window);
1364 }
1365
1366 /*
1367 * update_all_status: This updates all of the status lines for all of the
1368 * windows. By updating, it only draws from changed portions of the status
1369 * line to the right edge of the screen
1370 */
BX_update_all_status(Window * win,char * unused,int unused1)1371 void BX_update_all_status(Window *win, char *unused, int unused1)
1372 {
1373 Window *window = NULL;
1374 extern int foreground;
1375
1376 if (dumb_mode || !status_update_flag || never_connected || !foreground)
1377 return;
1378 while (traverse_all_windows(&window))
1379 {
1380 #if 0
1381 if (window->update & UPDATE_STATUS)
1382 continue;
1383 #endif
1384 if (!window->visible)
1385 break;
1386 make_status(window);
1387 }
1388 update_input(UPDATE_JUST_CURSOR);
1389 }
1390
BX_update_window_status_all(void)1391 void BX_update_window_status_all(void)
1392 {
1393 Window *win = NULL;
1394 while ((traverse_all_windows(&win)))
1395 {
1396 remove_wsets_for_window(win);
1397 win->wset = create_wsets_for_window(win);
1398 }
1399 update_all_status(win, NULL, 0);
1400 update_all_windows();
1401 }
1402
1403
1404 /*
1405 * status_update: sets the status_update_flag to whatever flag is. This also
1406 * calls update_all_status(), which will update the status line if the flag
1407 * was true, otherwise it's just ignored
1408 */
BX_status_update(int flag)1409 int BX_status_update(int flag)
1410 {
1411 int old_flag = status_update_flag;
1412 status_update_flag = flag;
1413 update_all_status(current_window, NULL, 0);
1414 cursor_to_input();
1415 return old_flag;
1416 }
1417
1418
1419 /*
1420 * set_prompt_by_refnum: changes the prompt for the given window. A window
1421 * prompt will be used as the target in place of the query user or current
1422 * channel if it is set
1423 */
BX_set_prompt_by_refnum(unsigned int refnum,char * prompt)1424 void BX_set_prompt_by_refnum(unsigned int refnum, char *prompt)
1425 {
1426 Window *tmp;
1427
1428 if (!(tmp = get_window_by_refnum(refnum)))
1429 tmp = current_window;
1430 malloc_strcpy(&(tmp->prompt), prompt);
1431 }
1432
1433 /* get_prompt_by_refnum: returns the prompt for the given window refnum */
BX_get_prompt_by_refnum(unsigned int refnum)1434 char *BX_get_prompt_by_refnum(unsigned int refnum)
1435 {
1436 Window *tmp;
1437
1438 if (!(tmp = get_window_by_refnum(refnum)))
1439 tmp = current_window;
1440 if (tmp->prompt)
1441 return (tmp->prompt);
1442 else
1443 return (empty_string);
1444 }
1445
1446 /*
1447 * get_target_by_refnum: returns the target for the window with the given
1448 * refnum (or for the current window). The target is either the query nick
1449 * or current channel for the window
1450 */
BX_get_target_by_refnum(unsigned int refnum)1451 char *BX_get_target_by_refnum(unsigned int refnum)
1452 {
1453 Window *tmp;
1454
1455 if (!(tmp = get_window_by_refnum(refnum)))
1456 if (!(tmp = last_input_screen->current_window))
1457 return NULL;
1458 if (tmp->query_nick)
1459 return tmp->query_nick;
1460 else if (tmp->current_channel)
1461 return tmp->current_channel;
1462
1463 return NULL;
1464 }
1465
BX_get_target_cmd_by_refnum(unsigned int refnum)1466 char *BX_get_target_cmd_by_refnum(unsigned int refnum)
1467 {
1468 Window *tmp;
1469 if (!(tmp = get_window_by_refnum(refnum)))
1470 if (!(tmp = last_input_screen->current_window))
1471 return NULL;
1472 return tmp->query_cmd ? tmp->query_cmd : NULL;
1473 }
1474
BX_get_window_target_by_desc(char * name)1475 Window *BX_get_window_target_by_desc(char *name)
1476 {
1477 Window *tmp = NULL;
1478 unsigned long level = 0;
1479 level = parse_lastlog_level(name, 0);
1480 while ((traverse_all_windows(&tmp)))
1481 {
1482 if (is_channel(name) && tmp->server != -1)
1483 {
1484 ChannelList *chan, *chan2;
1485 chan2 = get_server_channels(tmp->server);
1486 if ((chan = (ChannelList *)find_in_list((List **)&chan2, (char *)name, 0)))
1487 if (chan->window && (chan->window == tmp))
1488 return tmp;
1489 }
1490 else if (tmp->query_nick && !my_stricmp(tmp->query_nick, name))
1491 return tmp;
1492 else if (find_in_list((List **)&tmp->nicks, (char *)who_from, 0))
1493 return tmp;
1494 else if (level && tmp->window_level && (tmp->window_level & level))
1495 return tmp;
1496 }
1497 return NULL;
1498 }
1499
1500 #if 0
1501 /* set_query_nick: sets the query nick for the current channel to nick */
1502 void set_query_nick(char *nick, char *host, char *cmd)
1503 {
1504 NickList *tmp;
1505 char *old_nick;
1506 if (!nick && !host && cmd)
1507 {
1508 malloc_strcpy(¤t_window->query_cmd, cmd);
1509 return;
1510 }
1511 if ((old_nick = current_window->query_nick))
1512 {
1513 char *n;
1514 while ((n = next_in_comma_list(old_nick, &old_nick)))
1515 {
1516 if (!*n)
1517 break;
1518 if ((tmp = (NickList *) remove_from_list((List **) &(current_window->nicks), n)) != NULL)
1519 {
1520 new_free(&tmp->nick);
1521 new_free(&tmp->host);
1522 new_free((char **)&tmp);
1523 }
1524 }
1525 new_free(¤t_window->query_nick);
1526 new_free(¤t_window->query_host);
1527 new_free(¤t_window->query_cmd);
1528 }
1529 if (nick)
1530 {
1531 malloc_strcpy(¤t_window->query_nick, nick);
1532 malloc_strcpy(¤t_window->query_host, host);
1533 if (cmd)
1534 malloc_strcpy(¤t_window->query_cmd, cmd);
1535 current_window->update |= UPDATE_STATUS;
1536 while ((old_nick = next_in_comma_list(nick, &nick)))
1537 {
1538 if (!*old_nick)
1539 break;
1540 tmp = (NickList *) new_malloc(sizeof(NickList));
1541 malloc_strcpy(&tmp->nick, old_nick);
1542 malloc_strcpy(&tmp->host, host);
1543 add_to_list((List **) &(current_window->nicks), (List *) tmp);
1544 }
1545 }
1546 update_window_status(current_window, 0);
1547 }
1548 #endif
1549 /*
1550 * is_current_channel: Returns true is channel is a current channel for any
1551 * winDow. If the delete flag is not 0, then unset channel as the current
1552 * channel and attempt to replace it by a non-current channel or the
1553 * current_channel of window specified by value of delete
1554 */
BX_is_current_channel(char * channel,int server,int delete)1555 int BX_is_current_channel(char *channel, int server, int delete)
1556 {
1557
1558 Window *tmp = NULL;
1559 int found = 0;
1560
1561 while ((traverse_all_windows(&tmp)))
1562 {
1563 if (tmp->current_channel &&
1564 !my_stricmp(channel, tmp->current_channel) &&
1565 (tmp->server == from_server))
1566 {
1567 found = 1;
1568 if (delete)
1569 {
1570 new_free(&(tmp->current_channel));
1571 tmp->update |= UPDATE_STATUS;
1572 }
1573 }
1574 }
1575 return (found);
1576 }
1577
1578 /*
1579 * set_current_channel_by_refnum: This sets the current channel for the current
1580 * window. It returns the current channel as it's value. If channel is null,
1581 * the * current channel is not changed, but simply reported by the function
1582 * result. This treats as a special case setting the current channel to
1583 * channel "0". This frees the current_channel for the
1584 * output_screen->current_window, * setting it to null
1585 */
BX_set_current_channel_by_refnum(unsigned int refnum,char * channel)1586 const char *BX_set_current_channel_by_refnum(unsigned int refnum, char *channel)
1587 {
1588 Window *tmp;
1589 char *oldc;
1590 if ((tmp = get_window_by_refnum(refnum)) == NULL)
1591 tmp = current_window;
1592
1593 oldc = tmp->current_channel;
1594 if (!channel || (channel && !strcmp(channel, zero)))
1595 tmp->current_channel = NULL;
1596 else
1597 tmp->current_channel = m_strdup(channel);
1598
1599 new_free(&tmp->waiting_channel);
1600 tmp->update |= UPDATE_STATUS;
1601 set_channel_window(tmp, tmp->current_channel, tmp->server);
1602 do_hook(SWITCH_CHANNELS_LIST, "%d %s %s", refnum,
1603 oldc ? oldc : zero,
1604 tmp->current_channel ? tmp->current_channel : zero);
1605 #ifdef GUI
1606 if(tmp->current_channel)
1607 gui_update_nicklist(tmp->current_channel);
1608 #endif
1609 new_free(&oldc);
1610 return (channel);
1611 }
1612
1613 /* get_current_channel_by_refnum: returns the current channel for window refnum */
BX_get_current_channel_by_refnum(unsigned int refnum)1614 char * BX_get_current_channel_by_refnum(unsigned int refnum)
1615 {
1616 Window *tmp;
1617
1618 if ((tmp = get_window_by_refnum(refnum)) == NULL)
1619 tmp = current_window;
1620 return (tmp ? tmp->current_channel : NULL);
1621 }
1622
BX_get_refnum_by_window(const Window * w)1623 char *BX_get_refnum_by_window(const Window *w)
1624 {
1625 return w ? ltoa(w->refnum) : NULL;
1626 }
1627
1628
BX_is_bound_to_window(const Window * window,const char * channel)1629 int BX_is_bound_to_window (const Window *window, const char *channel)
1630 {
1631 if (window->bind_channel)
1632 {
1633 char *p, *q;
1634 q = p = LOCAL_COPY(window->bind_channel);
1635 while ((p = next_in_comma_list(q, &q)))
1636 {
1637 if (!p || !*p) break;
1638 if (!my_stricmp(p, channel))
1639 return 1;
1640 }
1641 }
1642 return 0;
1643 }
1644
BX_get_window_bound_channel(const char * channel)1645 Window *BX_get_window_bound_channel (const char *channel)
1646 {
1647 Window *tmp = NULL;
1648
1649 while ((traverse_all_windows(&tmp)))
1650 {
1651 if (tmp->bind_channel)
1652 {
1653 char *p, *q;
1654 if (!channel)
1655 return tmp;
1656 q = p = LOCAL_COPY(tmp->bind_channel);
1657 while ((p = next_in_comma_list(q, &q)))
1658 {
1659 if (!p || !*p) break;
1660 if (!my_stricmp(p, channel))
1661 return tmp;
1662 }
1663 }
1664 }
1665 return NULL;
1666 }
1667
BX_is_bound_anywhere(const char * channel)1668 int BX_is_bound_anywhere (const char *channel)
1669 {
1670 Window *tmp = NULL;
1671
1672 while ((traverse_all_windows(&tmp)))
1673 {
1674 if (tmp->bind_channel)
1675 {
1676 char *p, *q;
1677 q = p = LOCAL_COPY(tmp->bind_channel);
1678 while ((p = next_in_comma_list(q, &q)))
1679 {
1680 if (!p || !*p) break;
1681 if (!my_stricmp(p, channel))
1682 return 1;
1683 }
1684 }
1685 }
1686 return 0;
1687 }
1688
BX_is_bound(const char * channel,int server)1689 extern int BX_is_bound (const char *channel, int server)
1690 {
1691 Window *tmp = NULL;
1692
1693 while ((traverse_all_windows(&tmp)))
1694 {
1695 if (tmp->server == server && tmp->bind_channel)
1696 {
1697 char *p, *q;
1698 q = p = LOCAL_COPY(tmp->bind_channel);
1699 while ((p = next_in_comma_list(q, &q)))
1700 {
1701 if (!p || !*p) break;
1702 if (!my_stricmp(p, channel))
1703 return 1;
1704 }
1705 }
1706 }
1707 return 0;
1708 }
1709
BX_unbind_channel(const char * channel,int server)1710 void BX_unbind_channel (const char *channel, int server)
1711 {
1712 Window *tmp = NULL;
1713
1714 while ((traverse_all_windows(&tmp)))
1715 {
1716 if (tmp->server == server && tmp->bind_channel)
1717 {
1718 char *p, *q, *new_bind = NULL;
1719 if (!strchr(tmp->bind_channel, ','))
1720 {
1721 new_free(&tmp->bind_channel);
1722 tmp->bind_channel = NULL;
1723 return;
1724 }
1725 q = p = LOCAL_COPY(tmp->bind_channel);
1726 while ((p = next_in_comma_list(q, &q)))
1727 {
1728 if (!p || !*p)
1729 break;
1730 if (!my_stricmp(p, channel))
1731 continue;
1732 m_s3cat(&new_bind, comma, p);
1733 }
1734 malloc_strcpy(&tmp->bind_channel, new_bind);
1735 new_free(&new_bind);
1736 return;
1737 }
1738 }
1739 }
1740
BX_get_bound_channel(Window * window)1741 char *BX_get_bound_channel (Window *window)
1742 {
1743 return window ? window->bind_channel : NULL;
1744 }
1745
1746 /*
1747 * get_
1748 window_server: returns the server index for the window with the given
1749 * refnum
1750 */
BX_get_window_server(unsigned int refnum)1751 int BX_get_window_server(unsigned int refnum)
1752 {
1753 Window *tmp;
1754
1755 if ((tmp = get_window_by_refnum(refnum)) == NULL)
1756 tmp = current_window;
1757 return tmp ? tmp->server : -1;
1758 }
1759
1760 /*
1761 * set_window_server: This sets the server of the given window to server.
1762 * If refnum is -1 then we are setting the primary server and all windows
1763 * that are set to the current primary server are changed to server. The misc
1764 * flag is ignored in this case. If refnum is not -1, then that window is
1765 * set to the given server. If the misc flag is set as well, then all windows
1766 * with the same server as renum are set to the new server as well
1767 * if refnum == -2, then, we are setting the server group passed in the misc
1768 * variable to the server.
1769 */
BX_set_window_server(int refnum,int server,int misc)1770 void BX_set_window_server(int refnum, int server, int misc)
1771 {
1772 Window *tmp = NULL,
1773 *window;
1774 int old;
1775
1776 if (refnum == -1)
1777 {
1778 while ((traverse_all_windows(&tmp)))
1779 {
1780 if (tmp->server == primary_server)
1781 tmp->server = server;
1782 }
1783 window_check_servers(server);
1784 primary_server = server;
1785 }
1786 else
1787 {
1788 if ((window = get_window_by_refnum(refnum)) == NULL)
1789 window = current_window;
1790 old = window->server;
1791 if (misc || old == WINDOW_SERVER_CLOSED)
1792 {
1793 while ((traverse_all_windows(&tmp)))
1794 {
1795 if (tmp->server == old)
1796 tmp->server = server;
1797 }
1798 }
1799 else
1800 window->server = server;
1801 window_check_servers(window->server);
1802 }
1803 }
1804
1805 /*
1806 * window_check_servers: this checks the validity of the open servers vs the
1807 * current window list. Every open server must have at least one window
1808 * associated with it. If a window is associated with a server that's no
1809 * longer open, that window's server is set to the primary server. If an
1810 * open server has no assicatiate windows, that server is closed. If the
1811 * primary server is no more, a new primary server is picked from the open
1812 * servers
1813 */
1814
BX_window_check_servers(int unused)1815 void BX_window_check_servers(int unused)
1816 {
1817 Window *tmp;
1818 int cnt, max, i, not_connected, prime = -1;
1819
1820 connected_to_server = 0;
1821 max = server_list_size();
1822 for (i = 0; i < max; i++)
1823 {
1824 not_connected = !is_server_open(i);
1825 tmp = NULL;
1826 cnt = 0;
1827 while ((traverse_all_windows(&tmp)))
1828 {
1829 if (tmp->server == i)
1830 {
1831 if (not_connected)
1832 tmp->server = primary_server;
1833 else
1834 {
1835 prime = tmp->server;
1836 cnt++;
1837 }
1838 }
1839 }
1840 if (cnt == 0)
1841 {
1842 if(!not_connected)
1843 {
1844 if(!get_server_change_pending(i))
1845 close_server(i, "No windows for this server");
1846 else
1847 close_unattached_server(i);
1848 }
1849 }
1850 else
1851 connected_to_server++;
1852 }
1853
1854
1855 if (!is_server_open(primary_server))
1856 {
1857 tmp = NULL;
1858 while ((traverse_all_windows(&tmp)))
1859 if (tmp->server == primary_server)
1860 tmp->server = prime;
1861 primary_server = prime;
1862 }
1863 update_all_status(current_window, NULL, 0);
1864 cursor_to_input();
1865 }
1866
1867 /*
1868 * Changes any windows that are currently using "old_server" to instead
1869 * use "new_server".
1870 */
BX_change_window_server(int old_server,int new_server)1871 void BX_change_window_server (int old_server, int new_server)
1872 {
1873 Window *tmp = NULL;
1874
1875 while (traverse_all_windows(&tmp))
1876 {
1877 if (tmp->server == old_server)
1878 tmp->server = new_server;
1879 }
1880 window_check_servers(old_server);
1881 }
1882
1883 /*
1884 * set_level_by_refnum: This sets the window level given a refnum. It
1885 * revamps the windows levels as well using revamp_window_levels()
1886 */
BX_set_level_by_refnum(unsigned int refnum,unsigned long level)1887 void BX_set_level_by_refnum(unsigned int refnum, unsigned long level)
1888 {
1889 Window *tmp;
1890
1891 if ((tmp = get_window_by_refnum(refnum)) == NULL)
1892 tmp = current_window;
1893 tmp->window_level = level;
1894 revamp_window_levels(tmp);
1895 }
1896
1897 /*
1898 * revamp_window_levels: Given a level setting for the current window, this
1899 * makes sure that that level setting is unused by any other window. Thus
1900 * only one window in the system can be set to a given level. This only
1901 * revamps levels for windows with servers matching the given window
1902 * it also makes sure that only one window has the level `DCC', as this is
1903 * not dependant on a server.
1904 */
revamp_window_levels(Window * window)1905 void revamp_window_levels(Window *window)
1906 {
1907 Window *tmp = NULL;
1908 int got_dcc;
1909
1910 got_dcc = (LOG_DCC & window->window_level) ? 1 : 0;
1911 while ((traverse_all_windows(&tmp)))
1912 {
1913 if (tmp == window)
1914 continue;
1915 if (LOG_DCC & tmp->window_level)
1916 {
1917 if (0 != got_dcc)
1918 tmp->window_level &= ~LOG_DCC;
1919 got_dcc = 1;
1920 }
1921 if (window->server == tmp->server)
1922 tmp->window_level ^= (tmp->window_level & window->window_level);
1923 }
1924 }
1925
1926 /*
1927 * message_to: This allows you to specify a window (by refnum) as a
1928 * destination for messages. Used by EXEC routines quite nicely
1929 */
BX_message_to(unsigned long refnum)1930 void BX_message_to(unsigned long refnum)
1931 {
1932 target_window = (refnum) ? get_window_by_refnum(refnum) : NULL;
1933 }
1934
1935 #if 0
1936 /*
1937 * save_message_from: this is used to save (for later restoration) the
1938 * who_from variable. This comes in handy very often when a routine might
1939 * call another routine that might change who_from.
1940 */
1941 void save_message_from(char **saved_who_from, unsigned long *saved_who_level)
1942 {
1943 *saved_who_from = who_from;
1944 *saved_who_level = who_level;
1945 }
1946
1947 /* restore_message_from: restores a previously saved who_from variable */
1948 void restore_message_from (char *saved_who_from, unsigned long saved_who_level)
1949 {
1950 who_from = saved_who_from;
1951 who_level = saved_who_level;
1952 }
1953
1954 /*
1955 * message_from: With this you can the who_from variable and the who_level
1956 * variable, used by the display routines to decide which window messages
1957 * should go to.
1958 */
1959 void message_from(char *who, unsigned long level)
1960 {
1961 static unsigned long saved_lastlog_level = LOG_ALL;
1962
1963 if (level == LOG_CURRENT)
1964 set_lastlog_msg_level(saved_lastlog_level);
1965 else
1966 saved_lastlog_level = set_lastlog_msg_level(level);
1967 who_from = who;
1968 who_level = level;
1969 }
1970
1971 /*
1972 * message_from_level: Like set_lastlog_msg_level, except for message_from.
1973 * this is needed by XECHO, because we could want to output things in moRe
1974 * than one level.
1975 */
1976 int message_from_level(unsigned long level)
1977 {
1978 int temp;
1979
1980 temp = who_level;
1981 who_level = level;
1982 return temp;
1983 }
1984 #else
1985
1986 /*
1987 * save_message_from: this is used to save (for later restoration) the
1988 * who_from variable. This is needed when a function (do_hook) is about
1989 * to call another function (parse_line) it knows will change who_from.
1990 * The values are saved on the stack so it will be recursive-safe.
1991 *
1992 * NO CHEATING when you call this function to get the value of who_from! ;-)
1993 */
BX_save_display_target(const char ** saved_from,unsigned long * saved_level)1994 void BX_save_display_target (const char **saved_from, unsigned long *saved_level)
1995 {
1996 *saved_from = who_from;
1997 *saved_level = who_level;
1998 }
1999
2000 /* restore_message_from: restores a previously saved who_from variable */
BX_restore_display_target(const char * saved_from,unsigned long saved_level)2001 void BX_restore_display_target (const char *saved_from, unsigned long saved_level)
2002 {
2003 who_from = saved_from;
2004 who_level = saved_level;
2005 }
2006
2007 /*
2008 * is "word" in comma-separated "list" ?
2009 * --einride
2010 */
wordinlist(const char * word,const char * list)2011 int wordinlist(const char * word, const char * list)
2012 {
2013 char * nw;
2014 int wl;
2015 if (!word || !list || !word[0] || !list[0])
2016 return 0;
2017 wl = strlen(word);
2018 nw = (char *) list;
2019 while (nw) {
2020 if (!my_strnicmp(word, nw, wl) && (!nw[wl] || (nw[wl]==',')))
2021 return 1;
2022 nw = strchr(nw, ',');
2023 if (nw)
2024 nw++;
2025 }
2026 return 0;
2027 }
2028
2029 /*
2030 * message_from: With this you can set the who_from variable and the
2031 * who_level variable, used by the display routines to decide which
2032 * window messages should go to.
2033 */
2034 static unsigned long saved_lastlog_level = -1;
2035
BX_set_display_target(const char * who,unsigned long level)2036 void BX_set_display_target (const char *who, unsigned long level)
2037 {
2038 Window *tmp;
2039
2040 #ifdef NO_CHEATING
2041 if (who)
2042 malloc_strcpy(&who_from, who);
2043 else
2044 new_free(&who_from);
2045 #else
2046 who_from = who;
2047 #endif
2048 who_level = level;
2049 saved_lastlog_level = set_lastlog_msg_level(level);
2050
2051
2052 /*
2053 * Now we try to find the window that this output level would
2054 * be directed to. This was transplanted from add_to_screen.
2055 */
2056
2057 if (who_level == LOG_DEBUG && debugging_window)
2058 {
2059 target_window = debugging_window;
2060 return;
2061 }
2062 /*
2063 * LOG_CURRENT means everything goes to the current window.
2064 */
2065 if (who_level == LOG_CURRENT && current_window->server == from_server)
2066 {
2067 target_window = current_window;
2068 return;
2069 }
2070 /*
2071 * Next priority is to honor who_from (using /window bind,
2072 * /window channel, or /window add)
2073 */
2074 if (who_from)
2075 {
2076 tmp = NULL;
2077 while (traverse_all_windows(&tmp))
2078 {
2079 /*
2080 * Check for /WINDOW CHANNELs that apply.
2081 * (Any current channel will do)
2082 */
2083 if (tmp->server != from_server && level != LOG_DCC)
2084 continue;
2085 if ((tmp->window_level & LOG_DEBUG) == LOG_DEBUG)
2086 continue;
2087 if (tmp->current_channel &&
2088 wordinlist(who_from, tmp->current_channel))
2089 {
2090 if (tmp->server == from_server)
2091 {
2092 target_window = tmp;
2093 return;
2094 }
2095 }
2096 if (tmp->bind_channel &&
2097 wordinlist(who_from, tmp->bind_channel))
2098 {
2099 if (tmp->server == from_server)
2100 {
2101 target_window = tmp;
2102 return;
2103 }
2104 }
2105 /*
2106 * Check for /WINDOW QUERYs that apply.
2107 */
2108 if (tmp->query_nick)
2109 {
2110 if ((who_level == LOG_MSG || who_level == LOG_NOTICE
2111 || who_level == LOG_DCC || who_level == LOG_CTCP
2112 || who_level == LOG_ACTION)
2113 && wordinlist(who_from, tmp->query_nick)
2114 && from_server == tmp->server)
2115 {
2116 target_window = tmp;
2117 return;
2118 }
2119 if ((who_level == LOG_DCC || who_level == LOG_CTCP
2120 || who_level == LOG_ACTION)
2121 && (*tmp->query_nick == '=' || *tmp->query_nick == '-')
2122 && wordinlist(who_from, tmp->query_nick + 1))
2123 {
2124 target_window = tmp;
2125 return;
2126 }
2127 if ((who_level == LOG_DCC || who_level == LOG_CTCP
2128 || who_level == LOG_ACTION)
2129 && *tmp->query_nick == '='
2130 && wordinlist(who_from, tmp->query_nick))
2131 {
2132 target_window = tmp;
2133 return;
2134 }
2135 }
2136 }
2137
2138 /*
2139 * Check for /WINDOW NICKs that apply
2140 */
2141 tmp = NULL;
2142 while (traverse_all_windows(&tmp))
2143 {
2144 if (tmp->nicks && from_server == tmp->server)
2145 {
2146 if (find_in_list((List **)&(tmp->nicks),
2147 (char *)who_from, !USE_WILDCARDS))
2148 {
2149 target_window = tmp;
2150 return;
2151 }
2152 }
2153 }
2154
2155 /*
2156 * We'd better check to see if this should go to a
2157 * specific window (i dont agree with this, though)
2158 */
2159 if (is_channel((char *)who_from) && from_server > -1)
2160 {
2161 ChannelList *chan, *chan2;
2162 chan2 = get_server_channels(from_server);
2163 if ((chan = (ChannelList *)find_in_list((List **)&chan2,
2164 (char *)who_from, !USE_WILDCARDS)))
2165 {
2166 tmp = NULL;
2167 while ((traverse_all_windows(&tmp)))
2168 {
2169 if ((tmp->window_level & LOG_DEBUG) == LOG_DEBUG || !chan->window)
2170 continue;
2171 if (tmp->server != from_server)
2172 continue;
2173 if ((chan->refnum == tmp->refnum) && (tmp->server == chan->server))
2174 {
2175 target_window = tmp;
2176 return;
2177 }
2178 }
2179 }
2180 }
2181 }
2182
2183 /*
2184 * Check to see if this level should go to current window
2185 */
2186 if ((current_window_level & who_level) &&
2187 current_window->server == from_server)
2188 {
2189 target_window = current_window;
2190 return;
2191 }
2192 /*
2193 * Check to see if any window can claim this level
2194 */
2195 tmp = NULL;
2196 while (traverse_all_windows(&tmp))
2197 {
2198 if ((tmp->window_level & LOG_DEBUG) == LOG_DEBUG)
2199 continue;
2200 /*
2201 * Check for /WINDOW LEVELs that apply
2202 */
2203 if (((from_server == tmp->server) || (from_server <= -1)) &&
2204 (who_level & tmp->window_level))
2205 {
2206 target_window = tmp;
2207 return;
2208 }
2209 }
2210
2211 /*
2212 * If all else fails, if the current window is connected to the
2213 * given server, use the current window.
2214 */
2215 if (level == LOG_DCC || (from_server == current_window->server &&
2216 (current_window->window_level & LOG_DEBUG) != LOG_DEBUG))
2217 {
2218 target_window = current_window;
2219 return;
2220 }
2221
2222 /*
2223 * And if that fails, look for ANY window that is bound to the
2224 * given server (this never fails if we're connected.)
2225 */
2226 tmp = NULL;
2227 while (traverse_all_windows(&tmp))
2228 {
2229 if ((tmp->window_level & LOG_DEBUG) == LOG_DEBUG)
2230 continue;
2231 if (tmp->server == from_server)
2232 {
2233 target_window = tmp;
2234 return;
2235 }
2236 }
2237
2238 /*
2239 * No window found for a server is usually because we're
2240 * disconnected or not yet connected.
2241 */
2242 target_window = current_window;
2243 return;
2244 }
2245
BX_reset_display_target(void)2246 void BX_reset_display_target (void)
2247 {
2248 set_display_target(NULL, LOG_CRAP);
2249 }
2250
BX_set_display_target_by_desc(char * desc)2251 void BX_set_display_target_by_desc (char *desc)
2252 {
2253 if (!desc)
2254 target_window = current_window;
2255 else if (!strcmp(desc, "-1"))
2256 return;
2257 else if (!(target_window = get_window_by_desc(desc)))
2258 {
2259 say("Window [%s] does not exist", desc);
2260 target_window = current_window;
2261 }
2262 }
2263
set_display_target_by_winref(unsigned int refnum)2264 void set_display_target_by_winref (unsigned int refnum)
2265 {
2266 Window *w;
2267
2268 if (refnum == -1)
2269 return;
2270 if (!(w = get_window_by_refnum(refnum)))
2271 say("Window [%d] does not exist", refnum);
2272 else
2273 target_window = w;
2274 }
2275
2276 #endif
2277
2278
2279 /*
2280 * message_from_level: Like set_lastlog_msg_level, except for message_from.
2281 * this is needed by XECHO, because we could want to output things in more
2282 * than one level.
2283 */
message_from_level(unsigned long level)2284 unsigned long message_from_level (unsigned long level)
2285 {
2286 unsigned long temp;
2287 temp = who_level;
2288 who_level = level;
2289 return temp;
2290 }
2291
2292
2293
2294 /*
2295 * clear_window: This clears the display list for the given window, or
2296 * current window if null is given.
2297 */
BX_clear_window(Window * window)2298 void BX_clear_window(Window *window)
2299 {
2300 if (dumb_mode)
2301 return;
2302 if (window->scratch_line != -1)
2303 {
2304 Display *curr_line;
2305 /* Just walk every line and nuke whatever is in it */
2306 curr_line = window->top_of_display;
2307 while (curr_line && curr_line != window->display_ip)
2308 {
2309 malloc_strcpy(&curr_line->line, empty_string);
2310 curr_line = curr_line->next;
2311 }
2312 }
2313 else
2314 {
2315 window->top_of_display = window->display_ip;
2316 window->ceiling_of_display = window->top_of_display;
2317 window->cursor = 0;
2318 window->lines_scrolled_back = 0;
2319 window->scrollback_point = NULL;
2320 window->held_displayed = 0;
2321 if (window->miscflags & WINDOW_NOTIFIED)
2322 window->miscflags &= ~WINDOW_NOTIFIED;
2323 }
2324 repaint_window(window, 0, -1);
2325 update_window_status(window, 1);
2326 #ifdef GUI
2327 gui_activity(COLOR_INACTIVE);
2328 #endif
2329 }
2330
2331 /* clear_all_windows: This clears all *visible* windows */
BX_clear_all_windows(int unhold,int scrollback)2332 void BX_clear_all_windows(int unhold, int scrollback)
2333 {
2334 Window *tmp = NULL;
2335
2336 while (traverse_all_windows(&tmp))
2337 {
2338 if (unhold)
2339 set_hold_mode(tmp, OFF, 1);
2340 if (scrollback)
2341 clear_scrollback(tmp);
2342 clear_window(tmp);
2343 }
2344 }
2345
2346 /*
2347 * clear_window_by_refnum: just like clear_window(), but it uses a refnum. If
2348 * the refnum is invalid, the current window is cleared.
2349 */
BX_clear_window_by_refnum(unsigned int refnum)2350 void BX_clear_window_by_refnum(unsigned int refnum)
2351 {
2352 Window *tmp;
2353
2354 if ((tmp = get_window_by_refnum(refnum)) == NULL)
2355 tmp = current_window;
2356 clear_window(tmp);
2357 }
2358
unclear_window(Window * window)2359 static void unclear_window (Window *window)
2360 {
2361 int i;
2362
2363 if (dumb_mode)
2364 return;
2365 if (window->scratch_line != -1)
2366 return;
2367 window->top_of_display = window->display_ip;
2368 for (i = 0; i < window->display_size; i++)
2369 {
2370 window->top_of_display = window->top_of_display->prev;
2371 if (window->top_of_display == window->top_of_scrollback)
2372 break;
2373 }
2374 window->ceiling_of_display = window->top_of_display;
2375 repaint_window(window, 0, -1);
2376 update_window_status(window, 0);
2377 }
2378
unclear_all_windows(int unhold,int visible,int hidden)2379 void unclear_all_windows (int unhold, int visible, int hidden)
2380 {
2381 Window *tmp = NULL;
2382
2383 while (traverse_all_windows(&tmp))
2384 {
2385 if (visible && !hidden && !tmp->visible)
2386 continue;
2387 if (!visible && hidden && tmp->visible)
2388 continue;
2389
2390 if (unhold)
2391 set_hold_mode(tmp, OFF, 1);
2392 unclear_window(tmp);
2393 }
2394 }
2395
BX_unclear_window_by_refnum(unsigned refnum)2396 void BX_unclear_window_by_refnum (unsigned refnum)
2397 {
2398 Window *tmp;
2399
2400 if (!(tmp = get_window_by_refnum(refnum)))
2401 tmp = current_window;
2402 unclear_window(tmp);
2403 }
2404
2405 /*
2406 * set_scroll_lines: called by /SET SCROLL_LINES to check the scroll lines
2407 * value
2408 */
BX_set_scroll_lines(Window * win,char * unused,int size)2409 void BX_set_scroll_lines(Window *win, char *unused, int size)
2410 {
2411 if (size == 0)
2412 {
2413 return;
2414 }
2415 else if (size > current_window->display_size)
2416 {
2417 say("Maximum lines that may be scrolled is %d",
2418 current_window->display_size);
2419 set_int_var(SCROLL_LINES_VAR, current_window->display_size);
2420 }
2421 }
2422
2423 /*
2424 * set_continued_lines: checks the value of CONTINUED_LINE for validity,
2425 * altering it if its no good
2426 */
BX_set_continued_lines(Window * win,char * value,int unused)2427 void BX_set_continued_lines(Window *win, char *value, int unused)
2428 {
2429 if (value && ((int) strlen(stripansicodes(value)) > (current_term->TI_cols / 2)))
2430 value[current_term->TI_cols / 2] = '\0';
2431 }
2432
2433
2434
BX_free_formats(Window * window)2435 void BX_free_formats(Window *window)
2436 {
2437 remove_wsets_for_window(window);
2438 }
2439
2440 /* current_refnum: returns the reference number for the current window */
BX_current_refnum(void)2441 unsigned int BX_current_refnum (void)
2442 {
2443 return current_window->refnum;
2444 }
2445
BX_number_of_windows_on_screen(Window * w)2446 int BX_number_of_windows_on_screen (Window *w)
2447 {
2448 return w->screen->visible_windows;
2449 }
2450
2451 /*
2452 * set_lastlog_size: sets up a lastlog buffer of size given. If the lastlog
2453 * has gotten larger than it was before, all previous lastlog entry remain.
2454 * If it get smaller, some are deleted from the end.
2455 */
BX_set_scrollback_size(Window * w,char * unused,int size)2456 void BX_set_scrollback_size (Window *w, char *unused, int size)
2457 {
2458 Window *window = NULL;
2459
2460 while (traverse_all_windows(&window))
2461 {
2462 if (size < window->display_size * 2)
2463 window->display_buffer_max = window->display_size * 2;
2464 else
2465 window->display_buffer_max = size;
2466 }
2467 }
2468
2469 /*
2470 * is_window_name_unique: checks the given name vs the names of all the
2471 * windows and returns true if the given name is unique, false otherwise
2472 */
BX_is_window_name_unique(name)2473 int BX_is_window_name_unique(name)
2474 char *name;
2475 {
2476 Window *tmp = NULL;
2477
2478 if (name)
2479 {
2480 while ((traverse_all_windows(&tmp)))
2481 {
2482 if (tmp->name && !my_stricmp(tmp->name, name))
2483 return (0);
2484 }
2485 }
2486 return (1);
2487 }
2488
BX_get_nicklist_by_window(Window * win)2489 char *BX_get_nicklist_by_window (Window *win)
2490 {
2491 NickList *nick = win->nicks;
2492 char *stuff = NULL;
2493 for (; nick; nick = nick->next)
2494 m_s3cat(&stuff, space, nick->nick);
2495 if (!stuff)
2496 return m_strdup(empty_string);
2497 return stuff;
2498 }
2499
2500
2501 #define WIN_FORM "%-4s %*.*s %*.*s %*.*s %-9.9s %-10.10s %s%s"
list_a_window(Window * window,int len)2502 static void list_a_window(Window *window, int len)
2503 {
2504 int cnw = get_int_var(CHANNEL_NAME_WIDTH_VAR);
2505
2506 say(WIN_FORM, ltoa(window->refnum),
2507 12, 12, get_server_nickname(window->server),
2508 len, len, window->name ? window->name : "<None>",
2509 cnw, cnw, window->current_channel ? window->current_channel : "<None>",
2510 window->query_nick ? window->query_nick : "<None>",
2511 get_server_itsname(window->server) ? get_server_itsname(window->server) : "<None>",
2512 bits_to_lastlog_level(window->window_level),
2513 window->visible ? empty_string : " Hidden");
2514 }
2515
2516 /* below is stuff used for parsing of WINDOW command */
2517
2518 /*
2519 * get_window: this parses out any window (visible or not) and returns a
2520 * pointer to it
2521 */
get_window(char * name,char ** args)2522 static Window * get_window(char *name, char **args)
2523 {
2524 char *arg;
2525 Window *tmp;
2526
2527 if ((arg = next_arg(*args, args)) != NULL)
2528 {
2529 if (is_number(arg))
2530 {
2531 if ((tmp = get_window_by_refnum(my_atol(arg))) != NULL)
2532 return tmp;
2533 }
2534 if ((tmp = get_window_by_name(arg)) != NULL)
2535 return tmp;
2536 if (!get_int_var(WINDOW_QUIET_VAR))
2537 say("%s: No such window: %s", name, arg);
2538 }
2539 else
2540 say("%s: Please specify a window refnum or name", name);
2541 return NULL;
2542 }
2543
2544 /*
2545 * get_invisible_window: parses out an invisible window by reference number.
2546 * Returns the pointer to the window, or null. The args can also be "LAST"
2547 * indicating the top of the invisible window list (and thus the last window
2548 * made invisible)
2549 */
get_invisible_window(char * name,char ** args)2550 static Window *get_invisible_window(char *name, char **args)
2551 {
2552 char *arg;
2553 Window *tmp;
2554
2555 if ((arg = next_arg(*args, args)) != NULL)
2556 {
2557 if (my_strnicmp(arg, "LAST", strlen(arg)) == 0)
2558 {
2559 if (invisible_list == NULL)
2560 {
2561 if (!get_int_var(WINDOW_QUIET_VAR))
2562 say("%s: There are no hidden windows", name);
2563 }
2564 return invisible_list;
2565 }
2566 if ((tmp = get_window(name, &arg)) != NULL)
2567 {
2568 if (!tmp->visible)
2569 return (tmp);
2570 else if (!get_int_var(WINDOW_QUIET_VAR))
2571 {
2572 if (tmp->name)
2573 say("%s: Window %s is not hidden!",
2574 name, tmp->name);
2575 else
2576 say("%s: Window %d is not hidden!",
2577 name, tmp->refnum);
2578 }
2579 }
2580 }
2581 else
2582 say("%s: Please specify a window refnum or LAST", name);
2583 return NULL;
2584 }
2585
2586 /* get_number: parses out an integer number and returns it */
get_number(char * name,char ** args,char * msg)2587 static int get_number(char *name, char **args, char *msg)
2588 {
2589 char *arg;
2590
2591 if ((arg = next_arg(*args, args)) != NULL)
2592 return my_atol(arg);
2593 else if (!get_int_var(WINDOW_QUIET_VAR))
2594 {
2595 if (msg)
2596 say("%s: %s", name, msg);
2597 else
2598 say("%s: You must specify the number of lines", name);
2599 }
2600 return 0;
2601 }
2602
2603 /*
2604 * get_boolean: parses either ON, OFF, or TOGGLE and sets the var
2605 * accordingly. Returns 0 if all went well, -1 if a bogus or missing value
2606 * was specified
2607 */
get_boolean(char * name,char ** args,int * var)2608 static int get_boolean(char *name, char **args, int *var)
2609 {
2610 char *arg;
2611
2612 if (((arg = next_arg(*args, args)) == NULL) || do_boolean(arg, var))
2613 {
2614 if (!get_int_var(WINDOW_QUIET_VAR))
2615 say("Value for %s must be ON, OFF, or TOGGLE", name);
2616 return (-1);
2617 }
2618 else
2619 {
2620 say("Window %s is %s", name, onoff[*var]);
2621 return (0);
2622 }
2623 }
2624
2625
2626
2627
2628
2629
2630 /*
2631 * /WINDOW ADD nick<,nick>
2632 * Adds a list of one or more nicknames to the current list of usupred
2633 * targets for the current window. These are matched up with the nick
2634 * argument for message_from().
2635 */
window_add(Window * window,char ** args,char * usage)2636 static Window *window_add (Window *window, char **args, char *usage)
2637 {
2638 char *ptr;
2639 NickList *new;
2640 char *arg = next_arg(*args, args);
2641
2642 if (!arg)
2643 say("ADD: Add nicknames to be redirected to this window");
2644
2645 else while (arg)
2646 {
2647 if ((ptr = strchr(arg, ',')))
2648 *ptr++ = 0;
2649 if (!find_in_list((List **)&window->nicks, arg, !USE_WILDCARDS))
2650 {
2651 say("Added %s to window name list", arg);
2652 new = (NickList *)new_malloc(sizeof(NickList));
2653 new->nick = m_strdup(arg);
2654 add_to_list((List **)&(window->nicks), (List *)new);
2655 }
2656 else
2657 say("%s already on window name list", arg);
2658
2659 arg = ptr;
2660 }
2661
2662 return window;
2663 }
2664
2665 /*
2666 * /WINDOW BACK
2667 * Changes the current window pointer to the window that was most previously
2668 * the current window. If that window is now hidden, then it is swapped with
2669 * the current window.
2670 */
window_back(Window * window,char ** args,char * usage)2671 static Window *window_back (Window *window, char **args, char *usage)
2672 {
2673 Window *tmp;
2674
2675 tmp = get_window_by_refnum(last_input_screen->last_window_refnum);
2676 if (!tmp)
2677 tmp = last_input_screen->window_list;
2678
2679 make_window_current(tmp);
2680 if (tmp->visible)
2681 set_screens_current_window(last_input_screen, tmp);
2682 else
2683 {
2684 swap_window(window, tmp);
2685 reset_display_target();
2686 }
2687
2688 return window;
2689 }
2690
2691 /*
2692 * /WINDOW BALANCE
2693 * Causes all of the windows on the current screen to be adjusted so that
2694 * the largest window on the screen is no more than one line larger than
2695 * the smallest window on the screen.
2696 */
window_balance(Window * window,char ** args,char * usage)2697 static Window *window_balance (Window *window, char **args, char *usage)
2698 {
2699 if (window->screen)
2700 rebalance_windows(window->screen);
2701 else
2702 yell("cannot rebalance invisible windows!");
2703 return window;
2704 }
2705
2706 /*
2707 * /WINDOW BEEP_ALWAYS ON|OFF
2708 * Indicates that when this window is HIDDEN (sorry, thats not what it seems
2709 * like it should do, but that is what it does), beeps to this window should
2710 * not be suppressed like they normally are for hidden windows. The beep
2711 * occurs EVEN IF /set beep is OFF.
2712 */
window_beep_always(Window * window,char ** args,char * usage)2713 static Window *window_beep_always (Window *window, char **args, char *usage)
2714 {
2715 if (get_boolean("BEEP_ALWAYS", args, &window->beep_always))
2716 return NULL;
2717 return window;
2718 }
2719
2720 /*
2721 * /WINDOW BIND <#channel>
2722 * Indicates that the window should be "bound" to the specified channel.
2723 * "binding" a channel to a window means that the channel will always
2724 * belong to this window, no matter what. For example, if a channel is
2725 * bound to a window, you can do a /join #channel in any window, and it
2726 * will always "join" in this window. This is especially useful when
2727 * you are disconnected from a server, because when you reconnect, the client
2728 * often loses track of which channel went to which window. Binding your
2729 * channels gives the client a hint where channels belong.
2730 *
2731 * You can rebind a channel to a new window, even after it has already
2732 * been bound elsewhere.
2733 */
window_bind(Window * window,char ** args,char * usage)2734 static Window *window_bind (Window *window, char **args, char *usage)
2735 {
2736 char *arg;
2737 Window *w = NULL;
2738
2739 if ((arg = next_arg(*args, args)))
2740 {
2741 char *channel;
2742 channel = make_channel(arg);
2743 if (!channel || !is_channel(channel))
2744 {
2745 say("BIND: %s is not a valid channel name", channel ? channel :"");
2746 return window;
2747 }
2748 /*
2749 * If its already bound, no point in continuing.
2750 */
2751 if (window->bind_channel && is_bound_to_window(window, channel))
2752 {
2753 say("Window is already bound to channel %s", channel);
2754 return window;
2755 }
2756
2757 #if 0
2758 /*
2759 * You must either bind the current channel to a window, or
2760 * you must be binding to a window without a current channel
2761 */
2762 if (window->current_channel)
2763 {
2764 if (!my_stricmp(window->current_channel, channel))
2765 m_s3cat(&window->bind_channel, comma, channel);
2766 else
2767 say("You may only /WINDOW BIND the current channel for this window");
2768 return window;
2769 }
2770 #endif
2771
2772 /*
2773 * So we know this window doesnt have a current channel.
2774 * So we have to find the window where it IS the current
2775 * channel (if it is at all)
2776 */
2777 while (traverse_all_windows(&w))
2778 {
2779 /*
2780 * If we have found a window where this channel
2781 * is currently bound, then we unbind it from
2782 * that oTher window and bind it here.
2783 */
2784 if (w->bind_channel && w->server && is_bound_to_window(w, channel))
2785 {
2786 char *p, *q, *new_bind = NULL;
2787 m_s3cat(&window->bind_channel, comma, channel);
2788 q = p = LOCAL_COPY(w->bind_channel);
2789 while ((p = next_in_comma_list(q, &q)))
2790 {
2791 if (!p || !*p)
2792 break;
2793 if (!my_stricmp(p, channel))
2794 continue;
2795 m_s3cat(&new_bind, comma, p);
2796 }
2797 if (new_bind && *new_bind)
2798 malloc_strcpy(&w->bind_channel, new_bind);
2799 else
2800 new_free(&w->bind_channel);
2801 new_free(&new_bind);
2802 }
2803
2804 /*
2805 * If we have found a window where this channel
2806 * is the current channel, then we make it so that
2807 * it is the current channel here.
2808 */
2809 if (w->current_channel && w->server == window->server)
2810 {
2811 if (is_bound_to_window(w, channel))
2812 unset_window_current_channel(w);
2813 }
2814 }
2815
2816 /*
2817 * Now we mark this channel as being bound here.
2818 * and as being our current channel.
2819 */
2820 m_s3cat(&window->bind_channel, comma, channel);
2821 say("Window is bound to channel %s", channel);
2822
2823 if (im_on_channel(channel, window->server))
2824 {
2825 set_current_channel_by_refnum(window->refnum, channel);
2826 say("Current channel for window now %s", channel);
2827 }
2828 }
2829
2830 else if ((arg = get_bound_channel(window)))
2831 say("Window is bound to channel %s", arg);
2832 else
2833 say("Window is not bound to any channel");
2834
2835 return window;
2836 }
2837
2838 /*
2839 * /WINDOW CHANNEL <#channel>
2840 * Directs the client to make a specified channel the current channel for
2841 * the window -- it will JOIN the channel if you are not already on it.
2842 * If the channel you wish to activate is bound to a different window, you
2843 * will be notified. If you are already on the channel in another window,
2844 * then the channel's window will be switched. If you do not specify a
2845 * channel, or if you specify the channel "0", then the window will drop its
2846 * connection to whatever channel it is in.
2847 */
window_channel(Window * window,char ** args,char * usage)2848 Window *window_channel (Window *window, char **args, char *usage)
2849 {
2850 char *arg;
2851
2852 if ((arg = new_next_arg(*args, args)))
2853 {
2854 char *channel, *ch;
2855 while ((ch = next_in_comma_list(arg, &arg)))
2856 {
2857 if (!my_strnicmp(ch, "-i", 2))
2858 {
2859 if (invite_channel)
2860 ch = invite_channel;
2861 else
2862 {
2863 say("You have not been invited to a channel!");
2864 return window;
2865 }
2866 }
2867 if (!ch || !*ch)
2868 break;
2869 if (!(channel = make_channel(ch)))
2870 break;
2871 if (is_bound(channel, window->server))
2872 say("Channel %s is already bound elsewhere", channel);
2873 else if (is_current_channel(channel, window->server, 1) ||
2874 is_on_channel(channel, window->server, get_server_nickname(window->server)))
2875 {
2876 say("You are now talking to channel %s", channel);
2877 set_current_channel_by_refnum(window->refnum, channel);
2878 }
2879 else if (channel[1] == '0' && channel[2] == 0)
2880 set_current_channel_by_refnum(window->refnum, NULL);
2881 else
2882 {
2883 my_send_to_server(window->server, "JOIN %s", channel);
2884 malloc_strcpy(&window->waiting_channel, channel);
2885 }
2886 }
2887 }
2888 else
2889 set_current_channel_by_refnum(window->refnum, zero);
2890
2891 return window;
2892 }
2893
2894 /* For JOIN_NEW_WINDOW .... */
win_create(int var,int test)2895 void win_create(int var, int test)
2896 {
2897 if (get_int_var(var) && (test ||
2898 current_window->current_channel || current_window->query_nick))
2899 {
2900 char *args = NULL;
2901 switch (var)
2902 {
2903 case JOIN_NEW_WINDOW_VAR:
2904 args = LOCAL_COPY(SAFE(get_string_var(JOIN_NEW_WINDOW_TYPE_VAR)));
2905 break;
2906 case QUERY_NEW_WINDOW_VAR:
2907 args = LOCAL_COPY(SAFE(get_string_var(QUERY_NEW_WINDOW_TYPE_VAR)));
2908 break;
2909 default:
2910 return;
2911 break;
2912 }
2913 if (args && *args)
2914 windowcmd("WINDOW", args, empty_string, empty_string);
2915 }
2916 }
2917
2918 /*
2919 * /WINDOW CREATE
2920 * This directs the client to open up a new physical screen and create a
2921 * new window in it. This feature depends on the external "wserv" utility
2922 * and requires a multi-processing system, since it actually runs the new
2923 * screen in a seperate process. Please note that the external screen is
2924 * not actually controlled by the client, but rather by "wserv" which acts
2925 * as a pass-through filter on behalf of the client.
2926 *
2927 * Since the external screen is outside the client's process, it is not really
2928 * possible for the client to know when the external screen is resized, or
2929 * what that new size would be. For this reason, you should not resize any
2930 * screen when you have external screens open. If you do, the client will
2931 * surely become confused and the output will probably be garbled. You can
2932 * restore some sanity by making sure that ALL external screens have the same
2933 * geometry, and then redrawing each screen.
2934 */
window_create(Window * window,char ** args,char * usage)2935 static Window *window_create (Window *window, char **args, char *usage)
2936 {
2937 #ifdef WINDOW_CREATE
2938 Window *tmp;
2939 if ((tmp = (Window *)create_additional_screen()))
2940 {
2941 last_input_screen = tmp->screen;
2942 window = tmp;
2943 }
2944 else
2945 #endif
2946 say("Cannot create new screen!");
2947 return window;
2948 }
2949
2950 /*
2951 * /WINDOW DELETE
2952 * This directs the client to close the current external physical screen
2953 * and to re-parent any windows onto other screens. You are not allowed
2954 * to delete the "main" window because that window belongs to the process
2955 * group of the client itself.
2956 */
window_delete(Window * window,char ** args,char * usage)2957 static Window *window_delete (Window *window, char **args, char *usage)
2958 {
2959 #ifdef WINDOW_CREATE
2960 if(window->screen)
2961 kill_screen(window->screen);
2962 #endif
2963 return current_window;
2964 }
2965
2966 /*
2967 * /WINDOW DESCRIBE
2968 * Directs the client to tell you a bit about the current window.
2969 * This is the 'default' argument to the /window command.
2970 */
window_describe(Window * window,char ** args,char * usage)2971 static Window *window_describe (Window *window, char **args, char *usage)
2972 {
2973 if (window->name)
2974 say("Window %s (%u)", window->name, window->refnum);
2975 else
2976 say("Window %u", window->refnum);
2977
2978 say("\tServer: [%d] %s",
2979 window->server,
2980 window->server <= -1 ?
2981 get_server_name(window->server) : "<None>");
2982 say("\tScreen: %p", window->screen);
2983 say("\tGeometry Info: [%d %d %d %d %d %d]",
2984 window->top, window->bottom,
2985 window->held_displayed, window->display_size,
2986 window->cursor, window->distance_from_display);
2987
2988 #ifndef GUI
2989 say("\tCO, LI are [%d %d]", current_term->TI_cols, current_term->TI_lines);
2990 #else
2991 say("\tCO, LI are [%d %d]", output_screen->co, output_screen->li);
2992 #endif
2993 say("\tCurrent channel: %s",
2994 window->current_channel ?
2995 window->current_channel : "<None>");
2996
2997 if (window->waiting_channel)
2998 say("\tWaiting channel: %s",
2999 window->waiting_channel);
3000
3001 if (window->bind_channel)
3002 say("\tBound channel: %s",
3003 window->bind_channel);
3004 say("\tQuery User: %s %s",
3005 window->query_nick ?
3006 window->query_nick : "<None>",
3007 window->query_cmd ?
3008 window->query_cmd : empty_string);
3009 say("\tPrompt: %s",
3010 window->prompt ?
3011 window->prompt : "<None>");
3012 say("\tSecond status line is %s", onoff[window->double_status]);
3013 say("\tSplit line is %s triple is %s", onoff[window->status_split], onoff[window->status_lines]);
3014 say("\tLogging is %s", onoff[window->log]);
3015
3016 if (window->logfile)
3017 say("\tLogfile is %s", window->logfile);
3018 else
3019 say("\tNo logfile given");
3020
3021 say("\tNotification is %s",
3022 onoff[window->miscflags & WINDOW_NOTIFY]);
3023 say("\tHold mode is %s",
3024 onoff[window->hold_mode]);
3025 say("\tWindow level is %s",
3026 bits_to_lastlog_level(window->window_level));
3027 say("\tLastlog level is %s",
3028 bits_to_lastlog_level(window->lastlog_level));
3029 say("\tNotify level is %s",
3030 bits_to_lastlog_level(window->notify_level));
3031
3032 if (window->nicks)
3033 {
3034 NickList *tmp;
3035 say("\tName list:");
3036 for (tmp = window->nicks; tmp; tmp = tmp->next)
3037 say("\t %s", tmp->nick);
3038 }
3039
3040 return window;
3041 }
3042
3043 /*
3044 * /WINDOW DISCON
3045 * This disassociates a window with all servers.
3046 */
window_discon(Window * window,char ** args,char * usage)3047 static Window *window_discon (Window *window, char **args, char *usage)
3048 {
3049 if (window->server != -1)
3050 server_disconnect(window->server, NULL);
3051 window->server = -1;
3052 return window;
3053 }
3054
3055 /*
3056 * /WINDOW DOUBLE ON|OFF
3057 * This directs the client to enable or disable the supplimentary status bar.
3058 * When the "double status bar" is enabled, the status formats are taken from
3059 * /set STATUS_FORMAT1 or STATUS_FORMAT2. When it is disabled, the format is
3060 * taken from /set STATUS_FORMAT.
3061 */
window_double(Window * window,char ** args,char * usage)3062 static Window *window_double (Window *window, char **args, char *usage)
3063 {
3064 int current = window->double_status;
3065
3066 if (get_boolean("DOUBLE", args, &window->double_status))
3067 return NULL;
3068
3069 window->display_size += current - window->double_status;
3070 recalculate_window_positions(window->screen);
3071 redraw_all_windows();
3072 build_status(window, NULL, 0);
3073 return window;
3074 }
3075
3076 /*
3077 * alias wc {^window new double on split on hide_others}
3078 */
window_split(Window * window,char ** args,char * usage)3079 static Window *window_split (Window *window, char **args, char *usage)
3080 {
3081 int booya = window->status_lines;
3082 Window *tmp;
3083 if (get_boolean("SPLIT", args, &booya))
3084 return NULL;
3085 for (tmp = screen_list->window_list; tmp; tmp = tmp->next)
3086 {
3087 if (tmp->status_lines && booya)
3088 {
3089 if (!get_int_var(WINDOW_QUIET_VAR))
3090 yell("Already a split window");
3091 return window;
3092 }
3093 else if (tmp->status_lines && !booya)
3094 window = tmp;
3095 }
3096 window->status_lines = booya;
3097 recalculate_window_positions(window->screen);
3098 recalculate_windows(window->screen);
3099 update_all_windows();
3100 build_status (window, NULL, 0);
3101 return window;
3102 }
3103
window_triple(Window * window,char ** args,char * usage)3104 static Window *window_triple (Window *window, char **args, char *usage)
3105 {
3106 int booya = window->status_lines;
3107 if (get_boolean("TRIPLE", args, &booya))
3108 return NULL;
3109 if (!booya)
3110 {
3111 window->status_split = 1;
3112 window->status_lines = 0;
3113 }
3114 else
3115 {
3116 window->status_split = 0;
3117 window->status_lines = 1;
3118 }
3119 recalculate_windows(window->screen);
3120 update_all_windows();
3121 build_status (window, NULL, 0);
3122 return window;
3123 }
3124
3125 /*
3126 * WINDOW ECHO <text>
3127 *
3128 * Text must either be surrounded with double-quotes (")'s or it is assumed
3129 * to terminate at the end of the argument list. This sends the given text
3130 * to the current window.
3131 */
window_echo(Window * window,char ** args,char * usage)3132 static Window *window_echo (Window *window, char **args, char *usage)
3133 {
3134 const char *to_echo;
3135
3136 if (**args == '"')
3137 to_echo = new_next_arg(*args, args);
3138 else
3139 to_echo = *args, *args = NULL;
3140
3141 add_to_window(window, (const unsigned char *)to_echo);
3142 return window;
3143 }
3144
3145 /*
3146 * /WINDOW FIXED (ON|OFF)
3147 *
3148 * When this is ON, then this window will never be used as the implicit
3149 * partner for a window resize. That is to say, if you /window grow another
3150 * window, this window will not be considered for the corresponding shrink.
3151 * You may /window grow a fixed window, but if you do not have other nonfixed
3152 * windows, the grow will fail.
3153 */
window_fixed(Window * window,char ** args,char * usage)3154 static Window *window_fixed (Window *window, char **args, char *usage)
3155 {
3156 if (get_boolean("FIXED", args, &window->absolute_size))
3157 return NULL;
3158 return window;
3159 }
3160
3161 /*
3162 * /WINDOW GOTO refnum
3163 * This switches the current window selection to the window as specified
3164 * by the numbered refnum.
3165 */
window_goto(Window * window,char ** args,char * usage)3166 static Window *window_goto (Window *window, char **args, char *usage)
3167 {
3168 goto_window(window->screen, get_number("GOTO", args, NULL));
3169 from_server = get_window_server(0);
3170 return current_window;
3171 }
3172
3173 /*
3174 * /WINDOW GROW lines
3175 * This directs the client to expand the specified window by the specified
3176 * number of lines. The number of lines should be a positive integer, and
3177 * the window's growth must noT cause another window to be smaller than
3178 * the minimum of 3 lines.
3179 */
window_grow(Window * window,char ** args,char * usage)3180 static Window *window_grow (Window *window, char **args, char *usage)
3181 {
3182 resize_window(RESIZE_REL, window, get_number("GROW", args, NULL));
3183 return window;
3184 }
3185
3186 /*
3187 * /WINDOW HIDE
3188 * This directs the client to remove the specified window from the current
3189 * (visible) screen and place the window on the client's invisible list.
3190 * A hidden window has no "screen", and so can not be seen, and does not
3191 * have a size. It can be unhidden onto any screen.
3192 */
window_hide(Window * window,char ** args,char * usage)3193 static Window *window_hide (Window *window, char **args, char *usage)
3194 {
3195 hide_window(window);
3196 return current_window;
3197 }
3198
3199 /*
3200 * /WINDOW HIDE_OTHERS
3201 * This directs the client to place *all* windows on the current screen,
3202 * except for the current window, onto the invisible list.
3203 */
window_hide_others(Window * window,char ** args,char * usage)3204 static Window *window_hide_others (Window *window, char **args, char *usage)
3205 {
3206 Window *tmp, *next;
3207
3208 if (window->screen)
3209 tmp = window->screen->window_list;
3210 else
3211 tmp = invisible_list;
3212 while (tmp)
3213 {
3214 next = tmp->next;
3215 if (tmp != window)
3216 hide_window(tmp);
3217 tmp = next;
3218 }
3219 return window;
3220 }
3221
3222 /*
3223 * /WINDOW HOLD_MODE
3224 * This arranges for the window to "hold" any output bound for it once
3225 * a full page of output has been completed. Setting the global value of
3226 * HOLD_MODE is truly bogus and should be changed. XXXX
3227 */
window_hold_mode(Window * window,char ** args,char * usage)3228 static Window *window_hold_mode (Window *window, char **args, char *usage)
3229 {
3230 if (get_boolean("HOLD_MODE", args, &window->hold_mode))
3231 return NULL;
3232
3233 set_int_var(HOLD_MODE_VAR, window->hold_mode);
3234 return window;
3235 }
3236
3237 /*
3238 * /WINDOW KILL
3239 * This arranges for the current window to be destroyed. Once a window
3240 * is killed, it cannot be recovered. Because every server must have at
3241 * least one window "connected" to it, if you kill the last window for a
3242 * server, the client will drop your connection to that server automatically.
3243 */
window_kill(Window * window,char ** args,char * usage)3244 static Window *window_kill (Window *window, char **args, char *usage)
3245 {
3246 delete_window(window);
3247 redraw_all_windows();
3248 return current_window;
3249 }
3250
3251 /*
3252 * /WINDOW KILL_OTHERS
3253 * This arranges for all windows on the current screen, other than the
3254 * current window to be destroyed. Obviously, the current window will be
3255 * the only window left on the screen. Connections to servers other than
3256 * the server for the current window will be implicitly closed.
3257 */
window_kill_others(Window * window,char ** args,char * usage)3258 static Window *window_kill_others (Window *window, char **args, char *usage)
3259 {
3260 Window *tmp, *next;
3261
3262 if (window->screen)
3263 tmp = window->screen->window_list;
3264 else
3265 tmp = invisible_list;
3266 while (tmp)
3267 {
3268 next = tmp->next;
3269 if (tmp != window)
3270 delete_window(tmp);
3271 tmp = next;
3272 }
3273 return window;
3274 }
3275
3276 /*
3277 * /WINDOW KILLSWAP
3278 * This arranges for the current window to be replaced by the last window
3279 * to be hidden, and also destroys the current window.
3280 */
window_killswap(Window * window,char ** args,char * usage)3281 static Window *window_killswap (Window *window, char **args, char *usage)
3282 {
3283 if (invisible_list)
3284 {
3285 swap_window(window, invisible_list);
3286 delete_window(window);
3287 }
3288 else
3289 say("There are no hidden windows!");
3290
3291 return current_window;
3292 }
3293
3294 /*
3295 * /WINDOW LAST
3296 * This changes the current window focus to the window that was most recently
3297 * the current window *but only if that window is still visible*. If the
3298 * window is no longer visible (having been HIDDEN), then the next window
3299 * following the current window will be made the current window.
3300 */
window_last(Window * window,char ** args,char * usage)3301 static Window *window_last (Window *window, char **args, char *usage)
3302 {
3303 set_screens_current_window(window->screen, NULL);
3304 return current_window;
3305 }
3306
3307 /*
3308 * /WINDOW LASTLOG <size>
3309 * This changes the size of the window's lastlog buffer. The default value
3310 * foR a window's lastlog is the value of /set LASTLOG, but each window may
3311 * be independantly tweaked with this command.
3312 */
window_lastlog(Window * window,char ** args,char * usage)3313 static Window *window_lastlog (Window *window, char **args, char *usage)
3314 {
3315 char *arg = next_arg(*args, args);
3316
3317 if (arg)
3318 {
3319 int size = my_atol(arg);
3320 if (window->lastlog_size > size)
3321 {
3322 int i, diff;
3323 diff = window->lastlog_size - size;
3324 for (i = 0; i < diff; i++)
3325 remove_from_lastlog(window);
3326 }
3327 window->lastlog_max = size;
3328 }
3329 say("Lastlog size is %d", window->lastlog_max);
3330 return window;
3331 }
3332
3333 /*
3334 * /WINDOW LASTLOG_LEVEL <level-description>
3335 * This changes the types of lines that will be placed into this window's
3336 * lastlog. It is useful to note that the window's lastlog will contain
3337 * a subset (possibly a complete subset) of the lines that have appeared
3338 * in the window. This setting allows you to control which lines are
3339 * "thrown away" by the window.
3340 */
window_lastlog_level(Window * window,char ** args,char * usage)3341 static Window *window_lastlog_level (Window *window, char **args, char *usage)
3342 {
3343 char *arg = next_arg(*args, args);;
3344
3345 if (arg)
3346 window->lastlog_level = parse_lastlog_level(arg, 1);
3347 say("Lastlog level is %s", bits_to_lastlog_level(window->lastlog_level));
3348 return window;
3349 }
3350
3351 /*
3352 * /WINDOW LEVEL <level-description>
3353 * This changes the types of output that will appear in the specified window.
3354 * Note that for the given set of windows connected to a server, each level
3355 * may only appear once in that set. When you add a level to a given window,
3356 * then it will be removed from whatever window currently holds it. The
3357 * exception to this is the "DCC" level, which may only be set to one window
3358 * for the entire client.
3359 */
window_level(Window * window,char ** args,char * usage)3360 static Window *window_level (Window *window, char **args, char *usage)
3361 {
3362 char *arg;
3363 int add = 0;
3364 int newlevel = 0;
3365
3366 if ((arg = next_arg(*args, args)))
3367 {
3368 if (*arg == '+')
3369 add = 1, arg++;
3370 else if (*arg == '-')
3371 add = -1, arg++;
3372
3373 newlevel = parse_lastlog_level(arg, 1);
3374 if (add == 1)
3375 window->window_level |= newlevel;
3376 else if (add == 0)
3377 window->window_level = newlevel;
3378 else if (add == -1)
3379 window->window_level &= ~newlevel;
3380
3381 revamp_window_levels(window);
3382 }
3383 say("Window level is %s", bits_to_lastlog_level(window->window_level));
3384 return window;
3385 }
3386
3387 /*
3388 * /WINDOW LIST
3389 * This lists all of the windows known to the client, and a breif summary
3390 * of their current state.
3391 */
window_list(Window * window,char ** args,char * usage)3392 Window *window_list (Window *window, char **args, char *usage)
3393 {
3394 Window *tmp = NULL;
3395 int len = 6;
3396 int cnw = get_int_var(CHANNEL_NAME_WIDTH_VAR);
3397
3398 while ((traverse_all_windows(&tmp)))
3399 {
3400 if (tmp->name && (strlen(tmp->name) > len))
3401 len = strlen(tmp->name);
3402 }
3403
3404 say(WIN_FORM, "Ref",
3405 12, 12, "Nick",
3406 len, len, "Name",
3407 cnw, cnw, "Channel",
3408 "Query",
3409 "Server",
3410 "Level",
3411 empty_string);
3412
3413 tmp = NULL;
3414 while ((traverse_all_windows(&tmp)))
3415 list_a_window(tmp, len);
3416
3417 return window;
3418 }
3419
3420 /*
3421 * /WINDOW LOG ON|OFF
3422 * This sets the current state of the logfile for the given window. When the
3423 * logfile is on, then any lines that appear on the window are written to the
3424 * logfile 'as-is'. The name of the logfile can be controlled with
3425 * /WINDOW LOGFILE. The default logfile name is <windowname>.<target|refnum>
3426 */
window_log(Window * window,char ** args,char * usage)3427 static Window *window_log (Window *window, char **args, char *usage)
3428 {
3429 char logfile[MAXPATHLEN];
3430
3431 if (get_boolean("LOG", args, &window->log))
3432 return NULL;
3433
3434 if (window->logfile)
3435 {
3436 strlcpy(logfile, window->logfile, sizeof logfile);
3437 }
3438 else
3439 {
3440 char *logfile_base = get_string_var(LOGFILE_VAR);
3441
3442 if (!logfile_base)
3443 logfile_base = empty_string;
3444
3445 if (window->current_channel)
3446 snprintf(logfile, sizeof logfile, "%s.%s", logfile_base,
3447 window->current_channel);
3448 else if (window->query_nick)
3449 snprintf(logfile, sizeof logfile, "%s.%s", logfile_base,
3450 window->query_nick);
3451 else
3452 snprintf(logfile, sizeof logfile, "%s.Window_%u", logfile_base,
3453 window->refnum);
3454 }
3455 strip_chars(logfile, "|\\:", '-');
3456 do_log(window->log, logfile, &window->log_fp);
3457 if (!window->log_fp)
3458 window->log = 0;
3459
3460 return window;
3461 }
3462
3463 /*
3464 * /WINDOW LOGFILE <filename>
3465 * This sets the current value of the log filename for the given window.
3466 * When you activate the log (with /WINDOW LOG ON), then any output to the
3467 * window also be written to the filename specified.
3468 */
window_logfile(Window * window,char ** args,char * usage)3469 static Window *window_logfile (Window *window, char **args, char *usage)
3470 {
3471 char *arg = next_arg(*args, args);
3472
3473 if (arg)
3474 {
3475 malloc_strcpy(&window->logfile, arg);
3476 say("Window LOGFILE set to %s", arg);
3477 }
3478 else if (window->logfile)
3479 say("Window LOGFILE is %s", window->logfile);
3480 else
3481 say("Window LOGFILE is not set.");
3482
3483 return window;
3484 }
3485
window_move(Window * window,char ** args,char * usage)3486 static Window *window_move (Window *window, char **args, char *usage)
3487 {
3488 move_window(window, get_number("MOVE", args, NULL));
3489 return window;
3490 }
3491
window_name(Window * window,char ** args,char * usage)3492 static Window *window_name (Window *window, char **args, char *usage)
3493 {
3494 char *arg;
3495
3496 if ((arg = next_arg(*args, args)))
3497 {
3498 if (is_window_name_unique(arg))
3499 {
3500 malloc_strcpy(&window->name, arg);
3501 window->update |= UPDATE_STATUS;
3502 }
3503 else
3504 say("%s is not unique!", arg);
3505 }
3506 else
3507 say("You must specify a name for the window!");
3508
3509 return window;
3510 }
3511
window_new(Window * window,char ** args,char * usage)3512 static Window *window_new (Window *window, char **args, char *usage)
3513 {
3514 Window *tmp;
3515 if ((tmp = new_window(window->screen)))
3516 window = tmp;
3517
3518 return window;
3519 }
3520
window_new_hide(Window * window,char ** args,char * usage)3521 static Window *window_new_hide (Window *window, char **args, char *usage)
3522 {
3523 new_window(NULL);
3524 return window;
3525 }
3526
window_next(Window * window,char ** args,char * usage)3527 static Window *window_next (Window *window, char **args, char *usage)
3528 {
3529 Window *tmp;
3530 Window *next = NULL;
3531 Window *smallest = NULL;
3532
3533 if (!invisible_list)
3534 {
3535 say("There are no hidden windows");
3536 return NULL;
3537 }
3538
3539 smallest = window;
3540 for (tmp = invisible_list; tmp; tmp = tmp->next)
3541 {
3542 if (tmp->refnum < smallest->refnum)
3543 smallest = tmp;
3544 if ((tmp->refnum > window->refnum)
3545 && (!next || (tmp->refnum < next->refnum)))
3546 next = tmp;
3547 }
3548
3549 if (!next)
3550 next = smallest;
3551
3552 swap_window(window, next);
3553 reset_display_target();
3554 return current_window;
3555 }
3556
window_noserv(Window * window,char ** args,char * usage)3557 static Window *window_noserv (Window *window, char **args, char *usage)
3558 {
3559 window->server = -1;
3560 return window;
3561 }
3562
window_notify(Window * window,char ** args,char * usage)3563 static Window *window_notify (Window *window, char **args, char *usage)
3564 {
3565 window->miscflags ^= WINDOW_NOTIFY;
3566 say("Notification when hidden set to %s",
3567 window->miscflags & WINDOW_NOTIFY ? on : off);
3568 return window;
3569 }
3570
window_notify_level(Window * window,char ** args,char * usage)3571 static Window *window_notify_level (Window *window, char **args, char *usage)
3572 {
3573 char *arg;
3574
3575 if ((arg = next_arg(*args, args)))
3576 window->notify_level = parse_lastlog_level(arg, 1);
3577 say("Window notify level is %s", bits_to_lastlog_level(window->notify_level));
3578 return window;
3579 }
3580
window_number(Window * window,char ** args,char * usage)3581 static Window *window_number (Window *window, char **args, char *usage)
3582 {
3583 Window *tmp;
3584 char *arg;
3585 int i;
3586
3587 if ((arg = next_arg(*args, args)))
3588 {
3589 if ((i = my_atol(arg)) > 0)
3590 {
3591 if ((tmp = get_window_by_refnum(i)))
3592 tmp->refnum = window->refnum;
3593 window->refnum = i;
3594 }
3595 else
3596 say("Window number must be greater than 0");
3597 }
3598 else
3599 say("Window number missing");
3600
3601 return window;
3602 }
3603
3604 /*
3605 * /WINDOW POP
3606 * This changes the current window focus to the most recently /WINDOW PUSHed
3607 * window that still exists. If the window is hidden, then it will be made
3608 * visible. Any windows that are found along the way that have been since
3609 * KILLed will be ignored.
3610 */
window_pop(Window * window,char ** args,char * usage)3611 static Window *window_pop (Window *window, char **args, char *usage)
3612 {
3613 int refnum;
3614 WindowStack *tmp;
3615 Window *win = NULL;
3616
3617 while (window->screen->window_stack)
3618 {
3619 refnum = window->screen->window_stack->refnum;
3620 tmp = window->screen->window_stack->next;
3621 new_free(&window->screen->window_stack);
3622 window->screen->window_stack = tmp;
3623
3624 win = get_window_by_refnum(refnum);
3625 if (!win)
3626 continue;
3627
3628 if (win->visible)
3629 set_screens_current_window(win->screen, win);
3630 else
3631 show_window(win);
3632 }
3633
3634 if (!window->screen->window_stack && !win)
3635 say("The window stack is empty!");
3636
3637 return win;
3638 }
3639
window_previous(Window * window,char ** args,char * usage)3640 static Window *window_previous (Window *window, char **args, char *usage)
3641 {
3642 Window *tmp;
3643 Window *previous = NULL, *largest;
3644
3645 if (!invisible_list)
3646 {
3647 say("There are no hidden windows");
3648 return NULL;
3649 }
3650
3651 largest = window;
3652 for (tmp = invisible_list; tmp; tmp = tmp->next)
3653 {
3654 if (tmp->refnum > largest->refnum)
3655 largest = tmp;
3656 if ((tmp->refnum < window->refnum)
3657 && (!previous || tmp->refnum > previous->refnum))
3658 previous = tmp;
3659 }
3660
3661 if (!previous)
3662 previous = largest;
3663
3664 swap_window(window, previous);
3665 reset_display_target();
3666 return current_window;
3667 }
3668
window_prompt(Window * window,char ** args,char * usage)3669 static Window *window_prompt (Window *window, char **args, char *usage)
3670 {
3671 char *arg;
3672
3673 if ((arg = next_arg(*args, args)))
3674 {
3675 malloc_strcpy(&window->prompt, arg);
3676 window->update |= UPDATE_STATUS;
3677 }
3678 else
3679 say("You must specify a prompt for the window!");
3680
3681 return window;
3682 }
3683
window_push(Window * window,char ** args,char * usage)3684 static Window *window_push (Window *window, char **args, char *usage)
3685 {
3686 WindowStack *new;
3687
3688 new = (WindowStack *) new_malloc(sizeof(WindowStack));
3689 new->refnum = window->refnum;
3690 new->next = window->screen->window_stack;
3691 window->screen->window_stack = new;
3692 return window;
3693 }
3694
window_query(Window * window,char ** args,char * usage)3695 Window *window_query (Window *window, char **args, char *usage)
3696 {
3697 NickList *tmp;
3698 char *nick = NULL;
3699 char *host = NULL;
3700 char *cmd = NULL;
3701 char *ptr;
3702
3703 /*
3704 * Nuke the old query list
3705 */
3706 if (*args && !my_strnicmp(*args, "-cmd", 4))
3707 {
3708 cmd = next_arg(*args, args);
3709 cmd = next_arg(*args, args);
3710 }
3711 if ((nick = window->query_nick))
3712 {
3713 say("Ending conversation with %s", current_window->query_nick);
3714 window->update |= UPDATE_STATUS;
3715 while ((ptr = next_in_comma_list(nick, &nick)))
3716 {
3717 if (!ptr || !*ptr)
3718 break;
3719
3720 if ((tmp = (NickList *)remove_from_list(
3721 (List **)&window->nicks, ptr)))
3722 {
3723 new_free(&tmp->nick);
3724 new_free(&tmp->host);
3725 new_free((char **)&tmp);
3726 }
3727 }
3728 new_free(&window->query_nick);
3729 new_free(&window->query_host);
3730 new_free(&window->query_cmd);
3731 }
3732
3733 if (cmd)
3734 malloc_strcpy(&window->query_cmd, cmd);
3735
3736 if ((nick = next_arg(*args, args)))
3737 {
3738
3739 if (args && *args)
3740 host = *args;
3741 if (!strcmp(nick, "."))
3742 {
3743 if (!(nick = get_server_sent_nick(window->server)))
3744 say("You have not messaged anyone yet");
3745 }
3746 else if (!strcmp(nick, ","))
3747 {
3748 if (!(nick = get_server_recv_nick(window->server)))
3749 say("You have not recieved a message yet");
3750 }
3751 else if (!strcmp(nick, "*") &&
3752 !(nick = get_current_channel_by_refnum(0)))
3753 {
3754 say("You are not on a channel");
3755 }
3756 else if (*nick == '%')
3757 {
3758 if (!is_valid_process(nick))
3759 nick = NULL;
3760 }
3761
3762 if (!nick)
3763 return window;
3764
3765
3766
3767 /*
3768 * Create the new query list
3769 */
3770 say("Starting conversation with %s", nick);
3771 malloc_strcpy(&window->query_nick, nick);
3772 malloc_strcpy(&window->query_host, host);
3773
3774 window->update |= UPDATE_STATUS;
3775 ptr = nick;
3776 while ((ptr = next_in_comma_list(nick, &nick)))
3777 {
3778 if (!ptr || !*ptr)
3779 break;
3780 tmp = (NickList *) new_malloc(sizeof(NickList));
3781 tmp->nick = m_strdup(ptr);
3782 if (host)
3783 tmp->host = m_strdup(host);
3784 add_to_list((List **)&window->nicks,(List *)tmp);
3785 }
3786 }
3787 update_input(UPDATE_ALL);
3788 #ifdef GUI
3789 xterm_settitle();
3790 #endif
3791 return window;
3792 }
3793
window_refresh(Window * window,char ** args,char * usage)3794 static Window *window_refresh (Window *window, char **args, char *usage)
3795 {
3796 int oiwc = in_window_command;
3797 in_window_command = 0;
3798 update_all_windows();
3799 update_all_status(window, NULL, 0);
3800 in_window_command = oiwc;
3801 return window;
3802 }
3803
3804
window_refnum(Window * window,char ** args,char * usage)3805 static Window *window_refnum (Window *window, char **args, char *usage)
3806 {
3807 Window *tmp;
3808 if ((tmp = get_window("REFNUM", args)))
3809 {
3810 window = tmp;
3811 make_window_current(tmp);
3812 if (tmp->visible)
3813 {
3814 set_screens_current_window(tmp->screen, tmp);
3815 window = tmp;
3816 }
3817 }
3818 else
3819 {
3820 say("No such window!");
3821 window = NULL;
3822 }
3823 return window;
3824 }
3825
window_remove(Window * window,char ** args,char * usage)3826 static Window *window_remove (Window *window, char **args, char *usage)
3827 {
3828 char *arg;
3829
3830 if ((arg = next_arg(*args, args)))
3831 {
3832 char *ptr;
3833 NickList *new;
3834
3835 while (arg)
3836 {
3837 if ((ptr = strchr(arg, ',')) != NULL)
3838 *ptr++ = 0;
3839
3840 if ((new = (NickList *)remove_from_list((List **)&(window->nicks), arg)))
3841 {
3842 say("Removed %s from window name list", new->nick);
3843 new_free(&new->nick);
3844 new_free((char **)&new);
3845 }
3846 else
3847 say("%s is not on the list for this window!", arg);
3848
3849 arg = ptr;
3850 }
3851 }
3852 else
3853 say("REMOVE: Do something! Geez!");
3854
3855 return window;
3856 }
3857
BUILT_IN_WINDOW(window_server)3858 BUILT_IN_WINDOW(window_server)
3859 {
3860 char *arg;
3861 #ifdef HAVE_SSL
3862 int withSSL = 0;
3863 #endif
3864
3865 if ((arg = next_arg(*args, args)))
3866 {
3867 #ifdef HAVE_SSL
3868 if (!my_strnicmp(arg, "-SSL", strlen(arg)))
3869 {
3870 withSSL = 1;
3871
3872 arg = next_arg(*args, args);
3873 }
3874 if(arg)
3875 {
3876 #endif
3877 int i = find_server_refnum(arg, NULL);
3878
3879 #ifdef HAVE_SSL
3880 if(i != -1)
3881 {
3882 if(withSSL)
3883 set_server_ssl(i, 1);
3884 else
3885 set_server_ssl(i, 0);
3886 }
3887 #endif
3888 close_unattached_servers();
3889 set_server_old_server(i, -2);
3890 set_server_try_once(i, 1);
3891 set_server_change_refnum(i, window->refnum);
3892 if (!connect_to_server_by_refnum(i, -1))
3893 {
3894 #ifndef NON_BLOCKING_CONNECTS
3895 set_window_server(window->refnum, from_server, 0);
3896 set_level_by_refnum(window->refnum, new_server_lastlog_level);
3897 if (window->current_channel)
3898 new_free(&window->current_channel);
3899 #endif
3900 }
3901 window_check_servers(from_server);
3902 #ifdef HAVE_SSL
3903 }
3904 #endif
3905 }
3906 else
3907 say("SERVER: You must specify a server");
3908
3909 return window;
3910 }
3911
window_show(Window * window,char ** args,char * usage)3912 static Window *window_show (Window *window, char **args, char *usage)
3913 {
3914 Window *tmp;
3915
3916 if ((tmp = get_window("SHOW", args)))
3917 {
3918 show_window(tmp);
3919 window = window->screen->current_window;
3920 update_input(UPDATE_ALL);
3921 #ifdef GUI
3922 gui_setfocus(tmp->screen);
3923 #endif
3924 }
3925 return window;
3926 }
3927
window_scratch(Window * window,char ** args,char * usage)3928 static Window *window_scratch (Window *window, char **args, char *usage)
3929 {
3930 int scratch = 0;
3931
3932 if (get_boolean("SCRATCH", args, &scratch))
3933 return NULL;
3934
3935 if (scratch == 1)
3936 window->scratch_line = 0;
3937 else
3938 {
3939 window->scratch_line = -1;
3940 window->top_of_display = window->display_ip;
3941 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
3942 }
3943 return window;
3944 }
3945
window_scroll(Window * window,char ** args,char * usage)3946 Window *window_scroll (Window *window, char **args, char *usage)
3947 {
3948 int scroll = 0;
3949
3950 if (get_boolean("SCROLL", args, &scroll))
3951 return NULL;
3952
3953 if (scroll == 1 && window->scratch_line == -1)
3954 return window;
3955 if (scroll == 0 && window->scratch_line == 0)
3956 return window;
3957
3958 if (scroll == 1)
3959 {
3960 window->scratch_line = -1;
3961 window->top_of_display = window->display_ip;
3962 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
3963 }
3964 else
3965 {
3966 window->scratch_line = 0;
3967 window->noscroll = 1;
3968 }
3969 return window;
3970 }
3971
window_scrollback(Window * window,char ** args,char * usage)3972 static Window *window_scrollback (Window *window, char **args, char *usage)
3973 {
3974 int val = get_number("SCROLLBACK", args, NULL);
3975
3976 if (!val)
3977 return NULL;
3978 if (val < window->display_size * 2)
3979 window->display_buffer_max = window->display_size * 2;
3980 else
3981 window->display_buffer_max = val;
3982
3983 say("Window scrollback size set to %d", window->display_buffer_max);
3984 return window;
3985 }
3986
window_skip(Window * window,char ** args,char * usage)3987 static Window *window_skip (Window *window, char **args, char *usage)
3988 {
3989 if (get_boolean("SKIP", args, &window->skip))
3990 return NULL;
3991
3992 return window;
3993 }
3994
window_show_all(Window * window,char ** args,char * usage)3995 static Window *window_show_all (Window *window, char **args, char *usage)
3996 {
3997 while (invisible_list)
3998 show_window(invisible_list);
3999 return window;
4000 }
4001
window_shrink(Window * window,char ** args,char * usage)4002 static Window *window_shrink (Window *window, char **args, char *usage)
4003 {
4004 resize_window(RESIZE_REL, window, -get_number("SHRINK", args, NULL));
4005 return window;
4006 }
4007
window_size(Window * window,char ** args,char * usage)4008 static Window *window_size (Window *window, char **args, char *usage)
4009 {
4010 char *ptr = *args;
4011 int number;
4012
4013 number = parse_number(args);
4014 if(ptr == *args)
4015 say("Window size is %d", window->display_size);
4016 else
4017 resize_window(RESIZE_ABS, window, number);
4018
4019 return window;
4020 }
4021
window_stack(Window * window,char ** args,char * usage)4022 static Window *window_stack (Window *window, char **args, char *usage)
4023 {
4024 WindowStack *last, *tmp, *crap;
4025 Window *win = NULL;
4026 int len = 4;
4027
4028 while ((traverse_all_windows(&win)))
4029 {
4030 if (win->name && (strlen(win->name) > len))
4031 len = strlen(win->name);
4032 }
4033
4034 say("Window stack:");
4035 last = NULL;
4036 tmp = window->screen->window_stack;
4037 while (tmp)
4038 {
4039 if ((win = get_window_by_refnum(tmp->refnum)) != NULL)
4040 {
4041 list_a_window(win, len);
4042 last = tmp;
4043 tmp = tmp->next;
4044 }
4045 else
4046 {
4047 crap = tmp->next;
4048 new_free((char **)&tmp);
4049 if (last)
4050 last->next = crap;
4051 else
4052 window->screen->window_stack = crap;
4053
4054 tmp = crap;
4055 }
4056 }
4057
4058 return window;
4059 }
4060
window_status_special(Window * window,char ** args,char * usage)4061 static Window *window_status_special (Window *window, char **args, char *usage)
4062 {
4063 char *arg;
4064
4065 arg = new_next_arg(*args, args);
4066 if (window->wset)
4067 malloc_strcpy(&window->wset->window_special_format, arg);
4068 window->update |= REDRAW_STATUS;
4069
4070 return window;
4071 }
4072
window_swap(Window * window,char ** args,char * usage)4073 static Window *window_swap (Window *window, char **args, char *usage)
4074 {
4075 Window *tmp;
4076
4077 if ((tmp = get_invisible_window("SWAP", args)))
4078 swap_window(window, tmp);
4079
4080 return current_window;
4081 }
4082
window_unbind(Window * window,char ** args,char * usage)4083 static Window *window_unbind (Window *window, char **args, char *usage)
4084 {
4085 char *arg, *channel;
4086
4087 if ((arg = next_arg(*args, args)))
4088 {
4089 channel = make_channel(arg);
4090 if (channel && is_bound(channel, from_server))
4091 {
4092 say("Channel %s is no longer bound", channel);
4093 unbind_channel(channel, from_server);
4094 }
4095 else
4096 say("Channel %s is not bound", channel ? channel : empty_string);
4097 }
4098 else
4099 {
4100 say("Channel %s is no longer bound", window->bind_channel);
4101 new_free(&window->bind_channel);
4102 }
4103 return window;
4104 }
4105
window_set(Window * window,char ** args,char * usage)4106 static Window *window_set (Window *window, char **args, char *usage)
4107 {
4108 wset_variable(NULL, *args, NULL, NULL);
4109 *args = NULL;
4110 return window;
4111 }
4112
window_update(Window * window,char ** args,char * usage)4113 static Window *window_update (Window *window, char **args, char *usage)
4114 {
4115 update_window_status_all();
4116 return window;
4117 }
4118
4119
4120 /*
4121 * Associates a Menu with a Window
4122 */
4123
window_menu(Window * window,char ** args,char * usage)4124 static Window *window_menu(Window *window, char **args, char *usage)
4125 {
4126 #ifdef GUI
4127 MenuStruct *menutoadd = NULL;
4128 Screen *menuscreen;
4129 char *addthismenu;
4130
4131 if(window->screen != NULL)
4132 menuscreen=window->screen;
4133 else
4134 menuscreen=main_screen;
4135
4136 addthismenu = m_strdup(next_arg(*args, args));
4137
4138 if (my_stricmp(addthismenu, "-delete") && !(menutoadd = (MenuStruct *)findmenu(addthismenu)))
4139 {
4140 say("Menu not found!");
4141 return window;
4142 }
4143
4144 gui_menu(menuscreen, addthismenu);
4145 #endif /* GUI */
4146 return window;
4147 }
4148
4149 #ifdef GUI
window_setpos(Window * window,char ** args,char * usage)4150 static Window *window_setpos(Window *window, char **args, char *usage)
4151 {
4152 int x = 0,
4153 y = 0,
4154 cx = 0,
4155 cy = 0,
4156 min = 0,
4157 max = 0,
4158 restore = 0,
4159 activate = 0,
4160 bottom = 0,
4161 top = 0,
4162 size = 0,
4163 position = 0,
4164 t = 0;
4165 char *tmp;
4166
4167 if (!(tmp = next_arg(*args, args)))
4168 return window;
4169 for (t = 0; t < strlen(tmp); t++)
4170 {
4171 switch (tmp[t])
4172 {
4173 case 's':
4174 size = 1;
4175 break;
4176 case 'p':
4177 position = 1;
4178 break;
4179 case 'm':
4180 min = 1;
4181 break;
4182 case 'M':
4183 max = 1;
4184 break;
4185 case 'r':
4186 restore = 1;
4187 break;
4188 case 'a':
4189 activate = 1;
4190 break;
4191 case 'T':
4192 top = 1;
4193 break;
4194 case 'B':
4195 bottom = 1;
4196 break;
4197 }
4198 }
4199 if (!(tmp = next_arg(*args, args)))
4200 return window;
4201 x = my_atol(tmp);
4202
4203 if (!(tmp = next_arg(*args, args)))
4204 return window;
4205 y = my_atol(tmp);
4206
4207 if (!(tmp = next_arg(*args, args)))
4208 return window;
4209 cx = my_atol(tmp);
4210
4211 if (!(tmp = next_arg(*args, args)))
4212 return window;
4213 cy = my_atol(tmp);
4214
4215 gui_setwindowpos(window->screen, x, y, cx, cy, top, bottom, min, max, restore, activate, size, position);
4216 return window;
4217 }
4218
window_font(Window * window,char ** args,char * usage)4219 static Window *window_font(Window *window, char **args, char *usage)
4220 {
4221 char *tmp;
4222
4223 if ((tmp = next_arg(*args, args)))
4224 if (window && window->screen)
4225 gui_font_set(tmp, window->screen);
4226 return window;
4227 }
4228
window_nicklist(Window * window,char ** args,char * usage)4229 static Window *window_nicklist(Window *window, char **args, char *usage)
4230 {
4231 char *tmp;
4232
4233 if ((tmp = next_arg(*args, args)))
4234 if (window && window->screen)
4235 gui_nicklist_width(my_atol(tmp), window->screen);
4236 return window;
4237 }
4238 #endif
4239
4240 static Window *window_help (Window *, char **, char *);
4241
4242 static window_ops options [] = {
4243 { "ADD", window_add, "[nick|#channel|nick1,nick2,...]\n- Adds [nick|#channel|nick1,nick2,...] to the nicks to display in a window" },
4244 { "BACK", window_back, "\n- Moves you back one window" },
4245 { "BALANCE", window_balance, "\n- Balances the displayed windows" },
4246 { "BEEP_ALWAYS", window_beep_always, "[on|off|toggle]\n- Should this window beep always on/off/toggle" },
4247 { "BIND", window_bind, "[#channel]\n- Binds a channel to a window" },
4248 { "CHANNEL", window_channel, "[#channel|#chan1,#chan2,...]\n- Attempts to join a channel in current window" },
4249 { "CREATE", window_create, "\n- Create a new screen using wserv in X-windows" },
4250 { "DELETE", window_delete, "\n- Used to kill a screen (wserv) in X-windows" },
4251 { "DESCRIBE", window_describe, "[text]\n- Displays useful information about the current window" },
4252 { "DISCON", window_discon, "Disconnects window from a server" },
4253 { "DOUBLE", window_double, "[on|off|toggle]\n- Turns double status bar on/off/toggle" },
4254 { "ECHO", window_echo, "[text]\n- echo [text] which is in quotes to a window" },
4255 { "FIXED", window_fixed, "[on|off|toggle]\n- Turns fixed window sizing on/off/toggle" },
4256 #ifdef GUI
4257 { "FONT", window_font, "[fontname]\n- Sets the font for the window" },
4258 #endif
4259 { "GOTO", window_goto, "[refnum]\n- Go's to a N'th window" },
4260 { "GROW", window_grow, "[number]\n- Grows the current window by # of lines" },
4261 { "HELP", window_help, "- All of this commands work on the current window" },
4262 { "HIDE", window_hide, "\n- Hides the current window" },
4263 { "HIDE_OTHERS", window_hide_others, "\n- Hides all windows except the current one" },
4264 { "HOLD_MODE", window_hold_mode, "[on|off|toggle]\n- Sets the current window's hold mode status" },
4265 { "KILL", window_kill, "\n- Kills the current window" },
4266 { "KILL_OTHERS", window_kill_others, "\n- Kills all visible windows except the current one" },
4267 { "KILLSWAP", window_killswap, "\n- Swaps the current window with the last one hidden and kills the swapped out window" },
4268 { "LAST", window_last, "\n- Places you in the last window you were in" },
4269 { "LASTLOG", window_lastlog, "[number]\n- Sets this windows lastlog size to #" },
4270 { "LASTLOG_LEVEL", window_lastlog_level, "[level]\n- Sets the current windows lastlog level to [levels]" },
4271 { "LEVEL", window_level, "[level]\n- Sets the window's level to [levels]" },
4272 { "LIST", window_list, "\n- Displays a list of windows" },
4273 { "LOG", window_log, "[on|off|toggle]\n- Turns window logging on/off/toggle" },
4274 { "LOGFILE", window_logfile, "[filename]\n- Sets the filename for the current windows logfile" },
4275 { "MENU", window_menu, "[name]\n- Associate a menu with a window"},
4276 { "MOVE", window_move, "[number]\n- Moves the current window on the display [number] of times" },
4277 { "NAME", window_name, "[text]\n- Sets the name for the current window" },
4278 { "NEW", window_new, "\n- Creates a new window" },
4279 { "NEW_HIDE", window_new_hide, "\n- Creates a new window" },
4280 { "NEXT", window_next, "\n- Sets the current window to the next numbered window" },
4281 #ifdef GUI
4282 { "NICKLIST", window_nicklist, "\n- Sets the current window nicklist width" },
4283 #endif
4284 { "NOSERV", window_noserv, "\n- turns the server off for this window" },
4285 { "NOTIFY", window_notify, "[on|off|toggle]\n- Turns notification on/off/toggle for the current window." },
4286 { "NOTIFY_LEVEL", window_notify_level, "[level]\n- Set's current window notification level to [level]" },
4287 { "NUMBER", window_number, "[number]\n- Set's the current windows refnum to #" },
4288 { "POP", window_pop, "\n- Pops the top window off the window stack. if hidden it's made visible" },
4289 { "PREVIOUS", window_previous, "\n- Sets the current window to the previous numbered windows" },
4290 { "PROMPT", window_prompt, "[text]\n- Sets the current input prompt to [text]" },
4291 { "PUSH", window_push, "[refnum]\n- Places the current window or specified window on the window stack" },
4292 { "QUERY", window_query, "Adds/remove query for current window" },
4293 { "REFNUM", window_refnum, "[refnum]\n- Changes the current window to [refnum]" },
4294 { "REFRESH", window_refresh, "refreshes the current window" },
4295 { "REMOVE", window_remove, "[nick|#channel|nick1,nick2,...]\n- Removes nick|#channel from this window's display" },
4296 { "SERVER", window_server, "[servername[:[<port>][:[<password>][:[<nickname>]]]]]\n- Attempts to connect current window with a new server" },
4297 { "SET", window_set, "[text]\n- Displays or sets window specific set's" },
4298 #ifdef GUI
4299 { "SETWINDOWPOS", window_setpos, "[options]\n- Set's windows size, position and state." },
4300 #endif
4301 { "SCRATCH", window_scratch, "\n- Create a scratch window. this window has no scrollback or scroll" },
4302 { "SCROLL", window_scroll, "\n- toggle scratch window non-scroll" },
4303 { "SCROLLBACK", window_scrollback, "[lines]\n- Sets the scrollback size for this window" },
4304 { "SHOW", window_show, "[refnum]\n- Makes the specified [refnum] window visible again" },
4305 { "SHOW_ALL", window_show_all, "\n- Makes all hidden windows visibile again" },
4306 { "SHRINK", window_shrink, "[lines]\n- Shrinks the current window by # of lines" },
4307 { "SIZE", window_size, "[lines]\n- Set's the current window to # lines" },
4308 { "SKIP", window_skip, "[on|off|toggle]\n- Set's the current windows skip status on/off/toggle" },
4309 { "SPLIT", window_split, "[on|off|toggle]\n- Places a third status line at the top of the screen if possible on/off/toggle" },
4310 { "STACK", window_stack, "\n- Shows the current window stack which have been added using /window push" },
4311 { "STATUS_SPECIAL", window_status_special, "[text]\n- A special window format"},
4312 { "SWAP", window_swap, "[refnum]\n- Swap the current window with the specified hidden [refnum] window" },
4313 { "TRIPLE", window_triple, "[on|off|toggle]\n- Turns on/off/toggle a triple status bar" },
4314 { "UNBIND", window_unbind, "[#channel]\n- Removes a channel bound to a window. If not specified then the current channel is used" },
4315 { "UPDATE", window_update, "\n- Updates the window status on all windows" },
4316 { NULL, NULL, NULL }
4317 };
4318
4319
window_help(Window * window,char ** args,char * usage)4320 static Window *window_help (Window *window, char **args, char *usage)
4321 {
4322 int i, c = 0, done = 0;
4323 char *cmd;
4324 char buffer[BIG_BUFFER_SIZE];
4325
4326 *buffer = 0;
4327 cmd = next_arg(*args, args);
4328 if (!cmd)
4329 {
4330 for (i = 0; options[i].command; i++)
4331 {
4332 strlcat(buffer, options[i].command, sizeof buffer);
4333 strlcat(buffer, space, sizeof buffer);
4334 if (++c == 5)
4335 {
4336 put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
4337 *buffer = 0;
4338 c = 0;
4339 }
4340 }
4341 if (c)
4342 put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
4343 userage("WINDOW help", "%R[%ncommand%R]%n to get help on specific commands");
4344 }
4345 else
4346 {
4347 for (i = 0; options[i].command; i++)
4348 {
4349 if (!my_stricmp(options[i].command, cmd))
4350 {
4351 snprintf(buffer, sizeof buffer, "WINDOW %s", cmd);
4352 userage(buffer, options[i].usage ? options[i].usage : " - No help available");
4353 done++;
4354 }
4355 }
4356 if (!done)
4357 put_it("%s", convert_output_format("$G WINDOW - No such command", NULL, NULL));
4358 }
4359 return window;
4360 }
4361
BUILT_IN_COMMAND(windowcmd)4362 BUILT_IN_COMMAND(windowcmd)
4363 {
4364 char *arg;
4365 int nargs = 0;
4366 int old_status_update = status_update_flag;
4367 Window *window;
4368 int oiwc = in_window_command;
4369 #ifdef WANT_DLL
4370 WindowDll *dll = NULL;
4371 #endif
4372 in_window_command = 1;
4373 reset_display_target();
4374
4375 window = current_window;
4376
4377 while ((arg = next_arg(args, &args)))
4378 {
4379 int i;
4380 int len = strlen(arg);
4381
4382 if (*arg == '-' || *arg == '/')
4383 arg++, len--;
4384 #ifdef WANT_DLL
4385 if (dll_window && (dll = (WindowDll *)find_in_list((List **)&dll_window, arg, 0)))
4386 {
4387 window = dll->func(window, &args, dll->help);
4388 nargs++;
4389 if (!window)
4390 args = NULL;
4391 }
4392 else
4393 #endif
4394 {
4395 for (i = 0; options[i].func ; i++)
4396 {
4397 if (!my_strnicmp(arg, options[i].command, len))
4398 {
4399 window = options[i].func(window, &args, options[i].usage);
4400 nargs++;
4401 if (!window)
4402 args = NULL;
4403 break;
4404 }
4405 }
4406
4407 if (!options[i].func)
4408 {
4409 Window *s_window;
4410 if ((s_window = get_window_by_desc(arg)))
4411 {
4412 nargs++;
4413 window = s_window;
4414 }
4415 else
4416 yell("WINDOW: Invalid option: [%s]", arg);
4417 }
4418 }
4419 }
4420
4421 if (!nargs)
4422 window_describe(current_window, NULL, NULL);
4423 in_window_command = oiwc;
4424 status_update_flag = old_status_update;
4425
4426 update_all_windows();
4427 update_all_status(window, NULL, 0);
4428 update_input(UPDATE_ALL);
4429 cursor_to_input();
4430 }
4431
4432
4433
4434 /* * * * * * * * * * * SCROLLBACK BUFFER * * * * * * * * * * * * * * */
4435 /*
4436 * XXXX Dont you DARE touch this XXXX
4437 *
4438 * Most of the time, a delete_display_line() is followed somewhat
4439 * immediately by a new_display_line(). So most of the time we just
4440 * cache that one item and re-use it. That saves us thousands of
4441 * malloc()s. In the cases where its not, then we just do things the
4442 * normal way.
4443 */
4444 static Display *recycle = NULL;
4445
delete_display_line(Display * stuff)4446 void delete_display_line (Display *stuff)
4447 {
4448 if (recycle == stuff)
4449 ircpanic("error in delete_display_line");
4450 if (recycle)
4451 new_free(&recycle);
4452
4453 recycle = stuff;
4454 new_free(&recycle->line);
4455 }
4456
new_display_line(Display * prev)4457 Display *new_display_line (Display *prev)
4458 {
4459 Display *stuff;
4460
4461 if (recycle)
4462 {
4463 stuff = recycle;
4464 recycle = NULL;
4465 }
4466 else
4467 stuff = (Display *)new_malloc(sizeof(Display));
4468
4469 stuff->line = NULL;
4470 stuff->prev = prev;
4471 stuff->next = NULL;
4472 return stuff;
4473 }
4474
4475 /* * * * * * * * * * * Scrollback functionality * * * * * * * * * * */
BX_scrollback_backwards_lines(int lines)4476 void BX_scrollback_backwards_lines (int lines)
4477 {
4478 Window *window = current_window;
4479 Display *new_top = window->top_of_display;
4480 int new_lines;
4481 #ifdef GUI
4482 int position;
4483 float bleah = get_int_var(SCROLLBACK_VAR);
4484 #endif
4485
4486 if (new_top == window->top_of_scrollback)
4487 {
4488 #ifndef GUI
4489 term_beep();
4490 #endif
4491 return;
4492 }
4493
4494 if (!window->scrollback_point)
4495 window->scrollback_point = window->top_of_display;
4496
4497 for (new_lines = 0; new_lines < lines; new_lines++)
4498 {
4499 if (new_top == window->top_of_scrollback)
4500 break;
4501 new_top = new_top->prev;
4502 }
4503
4504 window->top_of_display = new_top;
4505 window->lines_scrolled_back += new_lines;
4506
4507 recalculate_window_cursor(window);
4508 repaint_window(window, 0, -1);
4509 update_window_status(window, 0);
4510 cursor_not_in_display(window->screen);
4511 update_input(UPDATE_JUST_CURSOR);
4512 #ifdef GUI
4513 position = (int)(bleah-((((float)(window->distance_from_display-window->display_size))/(float)(window->display_buffer_size-window->display_size))*bleah));
4514 gui_scrollerchanged(window->screen, position);
4515 #endif
4516 }
4517
BX_scrollback_forwards_lines(int lines)4518 void BX_scrollback_forwards_lines (int lines)
4519 {
4520 Window *window = current_window;
4521 Display *new_top = window->top_of_display;
4522 int new_lines = 0;
4523 #ifdef GUI
4524 int position;
4525 float bleah = get_int_var(SCROLLBACK_VAR);
4526 #endif
4527
4528 if (new_top == window->display_ip || !window->scrollback_point)
4529 {
4530 #ifndef GUI
4531 term_beep();
4532 #endif
4533 return;
4534 }
4535
4536 for (new_lines = 0; new_lines < lines; new_lines++)
4537 {
4538 if (new_top == window->scrollback_point/*display_ip*/)
4539 break;
4540 new_top = new_top->next;
4541 }
4542
4543 window->top_of_display = new_top;
4544 window->lines_scrolled_back -= new_lines;
4545 recalculate_window_cursor(window);
4546 repaint_window(window, 0, -1);
4547 update_window_status(window, 0);
4548 cursor_not_in_display(window->screen);
4549 update_input(UPDATE_JUST_CURSOR);
4550 if (window->lines_scrolled_back <= 0)
4551 scrollback_end (0, NULL);
4552 #ifdef GUI
4553 position = (int)(bleah-((((float)(window->distance_from_display-window->display_size))/(float)(window->display_buffer_size-window->display_size))*bleah));
4554 gui_scrollerchanged(window->screen, position);
4555 #endif
4556 }
4557
BX_scrollback_forwards(char dumb,char * dumber)4558 void BX_scrollback_forwards (char dumb, char *dumber)
4559 {
4560 int ratio = get_int_var(SCROLLBACK_RATIO_VAR);
4561 int lines;
4562
4563 if (ratio < 10 )
4564 ratio = 10;
4565 if (ratio > 100)
4566 ratio = 100;
4567
4568 lines = current_window->display_size * ratio / 100;
4569 scrollback_forwards_lines(lines);
4570 }
4571
BX_scrollback_backwards(char dumb,char * dumber)4572 void BX_scrollback_backwards (char dumb, char *dumber)
4573 {
4574 int ratio = get_int_var(SCROLLBACK_RATIO_VAR);
4575 int lines;
4576
4577 if (ratio < 10 )
4578 ratio = 10;
4579 if (ratio > 100)
4580 ratio = 100;
4581
4582 lines = current_window->display_size * ratio / 100;
4583 scrollback_backwards_lines(lines);
4584 }
4585
4586
BX_scrollback_end(char dumb,char * dumber)4587 void BX_scrollback_end (char dumb, char *dumber)
4588 {
4589 Window *window = current_window;
4590
4591 if (!window->scrollback_point)
4592 {
4593 term_beep();
4594 return;
4595 }
4596
4597 /* Adjust the top of window only if we would move forward. */
4598 if (window->lines_scrolled_back > 0)
4599 window->top_of_display = window->scrollback_point;
4600
4601 window->lines_scrolled_back = 0;
4602 window->scrollback_point = NULL;
4603 repaint_window(window, 0, -1);
4604 update_window_status(window, 0);
4605 cursor_not_in_display(window->screen);
4606 update_input(UPDATE_JUST_CURSOR);
4607 #ifdef GUI
4608 gui_scrollerchanged(window->screen, get_int_var(SCROLLBACK_VAR));
4609 #endif
4610 }
4611
BX_scrollback_start(char dumb,char * dumber)4612 void BX_scrollback_start (char dumb, char *dumber)
4613 {
4614 Window *window = current_window;
4615
4616 if (window->display_buffer_size <= window->display_size)
4617 {
4618 term_beep();
4619 return;
4620 }
4621
4622 if (!window->scrollback_point)
4623 window->scrollback_point = window->top_of_display;
4624
4625 while (window->top_of_display != window->top_of_scrollback)
4626 {
4627 window->top_of_display = window->top_of_display->prev;
4628 window->lines_scrolled_back++;
4629 }
4630
4631 repaint_window(window, 0, -1);
4632 update_window_status(window, 0);
4633 cursor_not_in_display(window->screen);
4634 update_input(UPDATE_JUST_CURSOR);
4635 #ifdef GUI
4636 gui_scrollerchanged(window->screen, 0);
4637 #endif
4638 }
4639
4640
4641 /* HOLD MODE STUFF */
4642 /*
4643 * hold_mode: sets the "hold mode". Really. If the update flag is true,
4644 * this will also update the status line, if needed, to display the hold mode
4645 * state. If update is false, only the internal flag is set.
4646 */
BX_set_hold_mode(Window * window,int flag,int update)4647 void BX_set_hold_mode (Window *window, int flag, int update)
4648 {
4649 if (window == NULL)
4650 window = current_window;
4651
4652 if (flag != ON && window->scrollback_point)
4653 return;
4654
4655 if (flag == TOGGLE)
4656 {
4657 if (window->hold_mode == OFF)
4658 window->hold_mode = ON;
4659 else
4660 window->hold_mode = OFF;
4661 }
4662 else
4663 window->hold_mode = flag;
4664
4665
4666 if (update)
4667 {
4668 if (window->lines_held != window->last_lines_held)
4669 {
4670 window->last_lines_held = window->lines_held;
4671 update_window_status(window, 0);
4672 if (window->update | UPDATE_STATUS)
4673 window->update -= UPDATE_STATUS;
4674 cursor_in_display(window);
4675 update_input(NO_UPDATE);
4676 }
4677 }
4678 else
4679 window->last_lines_held = -1;
4680 }
4681
4682 /*
4683 * This checks to see if any windows need to be unheld or not
4684 */
BX_unhold_windows(void)4685 int BX_unhold_windows(void)
4686 {
4687 Window *w = NULL;
4688 int retval = 0;
4689
4690 while (traverse_all_windows(&w))
4691 {
4692 if (!w->hold_mode && w->lines_held)
4693 {
4694 if ((unhold_a_window(w)))
4695 retval++;
4696 }
4697 }
4698
4699 return retval;
4700 }
4701
BX_unstop_all_windows(char dumb,char * dumber)4702 void BX_unstop_all_windows (char dumb, char *dumber)
4703 {
4704 Window *tmp = NULL;
4705
4706 while (traverse_all_windows(&tmp))
4707 set_hold_mode(tmp, OFF, 1);
4708 }
4709
4710 /*
4711 * reset_line_cnt: called by /SET HOLD_MODE to reset the line counter so we
4712 * always get a held screen after the proper number of lines
4713 */
BX_reset_line_cnt(Window * win,char * unused,int value)4714 void BX_reset_line_cnt (Window *win, char *unused, int value)
4715 {
4716 win->hold_mode = value;
4717 win->held_displayed = 0;
4718 if (!win->hold_mode && win->in_more)
4719 reset_hold_mode(win);
4720 }
4721
4722 /* toggle_stop_screen: the BIND function TOGGLE_STOP_SCREEN */
BX_toggle_stop_screen(char unused,char * not_used)4723 void BX_toggle_stop_screen (char unused, char *not_used)
4724 {
4725 set_hold_mode(NULL, TOGGLE, 1);
4726 update_all_windows();
4727 }
4728
4729 /*
4730 * If "scrollback_point" is set, then anything below the bottom of the screen
4731 * at that point gets nuked.
4732 * If "scrollback_point" is not set, anything below the current position of
4733 * the screen gets nuked.
4734 */
BX_flush_everything_being_held(Window * window)4735 void BX_flush_everything_being_held (Window *window)
4736 {
4737 Display *ptr, *save;
4738 int count;
4739
4740 if (!window)
4741 window = current_window;
4742
4743 count = window->display_size;
4744
4745 if (window->scrollback_point)
4746 ptr = window->scrollback_point;
4747 else
4748 ptr = window->top_of_display;
4749
4750 while (--count > 0)
4751 {
4752 ptr = ptr->next;
4753 if (ptr == window->display_ip)
4754 return; /* Nothing to flush */
4755 }
4756 save = ptr->next;
4757 ptr->next = window->display_ip;
4758 window->display_ip->prev = ptr;
4759 ptr = save;
4760
4761 while (ptr != window->display_ip)
4762 {
4763 Display *next = ptr->next;
4764 delete_display_line(ptr);
4765 window->lines_held--;
4766 ptr = next;
4767 }
4768
4769 if (window->lines_held != 0)
4770 ircpanic("erf. fix this.");
4771
4772 window->holding_something = 0;
4773 set_hold_mode(window, OFF, 1);
4774 }
4775
4776
4777 /*
4778 * This adjusts the viewport up one full screen. This calls rite()
4779 * indirectly, because repaint_window() uses rite() to do the work.
4780 * This belongs somewhere else.
4781 */
BX_unhold_a_window(Window * window)4782 int BX_unhold_a_window (Window *window)
4783 {
4784 int amount = window->display_size;
4785
4786 if (window->holding_something &&
4787 (window->distance_from_display < window->display_size))
4788 {
4789 window->holding_something = 0;
4790 window->lines_held = 0;
4791 }
4792
4793 if (!window->lines_held || window->scrollback_point)
4794 return 0; /* Right. */
4795
4796 if (window->lines_held < amount)
4797 amount = window->lines_held;
4798
4799 window->lines_held -= amount;
4800 window->held_displayed = 0;
4801
4802 if (!window->lines_held)
4803 window->holding_something = 0;
4804
4805 if (!amount)
4806 return 0; /* Whatever */
4807
4808 while (amount--)
4809 window->top_of_display = window->top_of_display->next;
4810
4811 repaint_window(window, 0, -1);
4812 update_window_status(window, 0);
4813 return 1;
4814 }
4815
BX_recalculate_window_cursor(Window * window)4816 void BX_recalculate_window_cursor (Window *window)
4817 {
4818 Display *tmp;
4819
4820 window->cursor = window->distance_from_display = 0;
4821 for (tmp = window->top_of_display; tmp != window->display_ip;
4822 tmp = tmp->next)
4823 window->cursor++, window->distance_from_display++;
4824
4825 if (window->cursor > window->display_size)
4826 window->cursor = window->display_size;
4827 }
4828
BX_set_screens_current_window(Screen * screen,Window * window)4829 void BX_set_screens_current_window (Screen *screen, Window *window)
4830 {
4831 if (!window)
4832 {
4833 window = get_window_by_refnum(screen->last_window_refnum);
4834 if (window && window->screen != screen)
4835 window = NULL;
4836 }
4837 if (!window)
4838 window = screen->window_list;
4839 if (window->deceased)
4840 ircpanic("This window is dead");
4841 if (window->screen != screen || !screen)
4842 ircpanic("The window is not on that screen");
4843
4844 if (screen->current_window != window)
4845 {
4846 if (screen->current_window)
4847 {
4848 screen->current_window->update |= UPDATE_STATUS;
4849 screen->last_window_refnum = screen->current_window->refnum;
4850 }
4851 screen->current_window = window;
4852 screen->current_window->update |= UPDATE_STATUS;
4853 }
4854 if (current_window != window)
4855 make_window_current(window);
4856 update_all_windows();
4857 xterm_settitle();
4858 }
4859
BX_make_window_current(Window * window)4860 void BX_make_window_current (Window *window)
4861 {
4862 Window *old_current_window = current_window;
4863 int old_screen, old_win;
4864 int new_screen, new_win;
4865
4866 if (!window)
4867 current_window = last_input_screen->current_window;
4868 else if (current_window != window)
4869 current_window = window;
4870 if (current_window->deceased)
4871 ircpanic("This window is dead. Cannot continue.");
4872
4873 if (current_window == old_current_window)
4874 return;
4875
4876 if (!old_current_window)
4877 old_screen = old_win = -1;
4878 else if (!old_current_window->screen)
4879 old_screen = -1, old_win = old_current_window->refnum;
4880 else
4881 old_screen = old_current_window->screen->screennum,
4882 old_win = old_current_window->refnum;
4883
4884 new_win = current_window->refnum;
4885 if (!current_window->screen)
4886 new_screen = -1;
4887 else
4888 new_screen = current_window->screen->screennum;
4889
4890 do_hook(WINDOW_FOCUS_LIST, "%d %d %d %d",
4891 old_screen, old_win,
4892 new_screen, new_win);
4893 }
4894
BX_clear_scrollback(Window * window)4895 void BX_clear_scrollback(Window *window)
4896 {
4897 while (window->display_buffer_size > 0)
4898 {
4899 Display *next;
4900 if (window->top_of_scrollback)
4901 {
4902 next = window->top_of_scrollback->next;
4903 new_free(&window->top_of_scrollback->line);
4904 new_free(&window->top_of_scrollback);
4905 window->top_of_scrollback = next;
4906 }
4907 window->display_buffer_size--;
4908 }
4909 window->cursor = window->distance_from_display = 0;
4910 resize_window_display(window);
4911 }
4912
make_to_window_by_desc(char * desc)4913 void make_to_window_by_desc (char *desc)
4914 {
4915 Window *new_win = get_window_by_desc(desc);
4916
4917 if (new_win)
4918 target_window = new_win;
4919 else
4920 say("Window [%s] doesn't exist any more. Punting.", desc);
4921 }
4922
get_current_winref(void)4923 int get_current_winref (void)
4924 {
4925 return current_window->refnum;
4926 }
4927
get_winref_by_desc(const char * desc)4928 int get_winref_by_desc (const char *desc)
4929 {
4930 Window *w;
4931
4932 if ((w = get_window_by_desc(desc)))
4933 return w->refnum;
4934
4935 return -1;
4936 }
4937
make_window_current_by_desc(char * desc)4938 void make_window_current_by_desc (char *desc)
4939 {
4940 Window *new_win = get_window_by_desc(desc);
4941
4942 if (new_win)
4943 make_window_current(new_win);
4944 else
4945 say("Window [%s] doesn't exist any more. Punting.", desc);
4946 }
4947
make_window_current_by_winref(int refnum)4948 void make_window_current_by_winref (int refnum)
4949 {
4950 Window *new_win;
4951
4952 if (refnum == -1)
4953 return;
4954
4955 if ((new_win = get_window_by_refnum(refnum)))
4956 make_window_current(new_win);
4957 else
4958 say("Window [%d] doesn't exist any more. Punting.", refnum);
4959 }
4960
4961
4962