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 Michael Sandrof.
8 * Copyright (c) 1991, 1992 Troy Rollo.
9 * Copyright (c) 1992-2021 Matthew R. Green.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "irc.h"
37 IRCII_RCSID("@(#)$eterna: window.c,v 1.237 2021/02/27 08:02:14 mrg Exp $");
38
39 #include "screen.h"
40 #include "menu.h"
41 #include "window.h"
42 #include "vars.h"
43 #include "server.h"
44 #include "list.h"
45 #include "ircterm.h"
46 #include "names.h"
47 #include "ircaux.h"
48 #include "input.h"
49 #include "status.h"
50 #include "output.h"
51 #include "log.h"
52 #include "hook.h"
53 #include "dcc.h"
54 #include "translat.h"
55 #include "icb.h"
56 #include "parse.h"
57 #include "strsep.h"
58 #include "sl_irc.h"
59
60 /*
61 * WindowStack: The structure for the POP, PUSH, and STACK functions. A
62 * simple linked list with window refnums as the data.
63 *
64 * The code for this probably should move into screen.c.
65 */
66 struct window_stack_stru
67 {
68 unsigned int refnum;
69 WindowStack *next;
70 };
71
72 struct display_stru
73 {
74 u_char *line;
75 int linetype;
76 Display *next;
77 };
78
79 /*
80 * The main Window structure.
81 */
82 struct window_stru
83 {
84 unsigned refnum; /* the unique reference number,
85 assigned by IRCII */
86 u_char *name; /* window's logical name */
87 int server; /* server index */
88 int prev_server; /* previous server index */
89
90 int top; /* The top line of the window, screen
91 coordinates */
92 int bottom; /* The botton line of the window, screen
93 coordinates */
94 int cursor; /* The cursor position in the window,
95 window relative coordinates */
96 int line_cnt; /* counter of number of lines displayed
97 in window */
98 int scroll; /* true, window scrolls... false window
99 wraps */
100 int display_size; /* number of lines of window - menu
101 lines */
102 int old_size; /* if new_size != display_size,
103 resize_display is called */
104 int visible; /* true, window is drawn... false window
105 is hidden */
106 int update; /* window needs updating flag */
107 unsigned miscflags; /* Miscellaneous flags. */
108
109 u_char *prompt; /* A prompt string, usually set by
110 EXEC'd process */
111 u_char *status_line[2]; /* The status line strings */
112
113 int double_status; /* Display the 2nd status line ?*/
114
115 Display *top_of_display, /* Pointer to first line of display
116 structure */
117 *display_ip; /* Pointer to insertiong point of
118 display structure */
119
120 /* hold stuff */
121 HoldInfo *hold_info; /* link to our hold info */
122 int hold_mode; /* true, hold mode is on for window */
123 int hold_on_next_rite; /* if true, activate a hold on next call
124 to rite() */
125
126 int scrolled_lines; /* number of lines scrolled back */
127 int new_scrolled_lines; /* number of lines since scroll back
128 keys where pressed */
129
130 /* stuff that is a property of this window */
131 u_char *current_channel; /* Window's current channel */
132 u_char *bound_channel; /* Channel that belongs in this window */
133 u_char *query_nick; /* User being QUERY'ied in this window */
134 NickList *nicks; /* List of nicks that will go to window */
135 int window_level; /* The LEVEL of the window, determines
136 what messages go to it */
137 WindowMenu *menu; /* The menu (if any) */
138
139 /* lastlog stuff */
140 LastlogInfo *lastlog_info; /* pointer to lastlog info */
141
142 int notify_level; /* the notify level.. */
143
144 /* window log stuff */
145 u_char *logfile; /* window's logfile name */
146 int log; /* file logging for window is on */
147 FILE *log_fp; /* file pointer for the log file */
148
149 Screen *screen; /* our currently attached screen */
150 int server_group; /* server group number */
151
152 Window *next; /* pointer to next entry in window list
153 (null is end) */
154 Window *prev; /* pointer to previous entry in window
155 list (null is end) */
156 int sticky; /* make channels stick to window when
157 changing servers ? */
158 };
159
160 /*
161 * The following should synthesize MAXINT on any machine with an 8 bit
162 * word.
163 */
164 #undef MAXINT
165 #define MAXINT (-1&~(1<<(sizeof(int)*8-1)))
166
167 static Window *invisible_list = NULL; /* list of hidden windows */
168 static u_char *who_from = NULL; /* nick of person whose message
169 * is being displayed */
170 static int who_level = LOG_CRAP; /* Log level of message being
171 displayed */
172
173 /*
174 * status_update_flag: if 1, the status is updated as normal. If 0, then all
175 * status updating is suppressed
176 */
177 static int status_update_flag = 1;
178
179 #ifdef lines
180 #undef lines
181 #endif /* lines */
182
183 static void remove_from_window_list(Window *);
184 static void hide_window(Window *);
185 static void hide_other_windows(void);
186 static void remove_from_invisible_list(Window *);
187 static void revamp_window_levels(Window *);
188 static void swap_window(Window *, Window *);
189 static void move_window(Window *, int);
190 static void grow_window(Window *, int);
191 static Window *get_next_window(void);
192 static Window *get_previous_window(void);
193 static void delete_other_windows(void);
194 static void bind_channel(u_char *, Window *);
195 static void unbind_channel(u_char *, Window *);
196 static void irc_goto_window(int);
197 static void list_a_window(Window *, int, int);
198 static void list_windows(void);
199 static void show_window(Window *);
200 static void push_window_by_refnum(u_int);
201 static void pop_window(void);
202 static void show_stack(void);
203 static u_int create_refnum(void);
204 static int is_window_name_unique(u_char *);
205 static void add_nicks_by_refnum(u_int, u_char *, int);
206 static Window *get_window(u_char *, u_char **);
207 static Window *get_invisible_window(u_char *, u_char **);
208 static int get_number(u_char *, u_char **);
209 static int get_boolean(u_char *, u_char **, int *);
210 static void display_lastlog_lines(int, int, Window *);
211 static u_char **split_up_line(u_char *);
212 static void redraw_window(Window *, int, int);
213 static int lastlog_lines(Window *);
214 static void scrollback_backwards_lines(int);
215 static void scrollback_forwards_lines(int);
216
217 /*
218 * window_traverse: This will do as the name implies, traverse every
219 * window (visible and invisible) and return a pointer to each window on
220 * subsequent calls. If flag points to a non-zero value, then the traversal
221 * in started from the beginning again, and flag is set to point to 0. This
222 * returns all visible windows first, then all invisible windows. It returns
223 * null after all windows have been returned. It should generally be used as
224 * follows:
225 *
226 * Win_Trav wt;
227 * Window *tmp;
228 *
229 * wt.init = 1;
230 * while ((tmp = window_traverse(&wt)))
231 * { code here }
232 *
233 * this version is recursive.
234 */
235 Window *
window_traverse(Win_Trav * wt)236 window_traverse(Win_Trav *wt)
237 {
238 int foo = 1;
239
240 /* First call, return the current window basically */
241 if (wt->init)
242 {
243 wt->init = 0;
244 wt->visible = 1;
245 if (!screen_first())
246 return NULL;
247 wt->screen = screen_first();
248 wt->which = screen_get_window_list(wt->screen);
249 if (wt->which)
250 return (wt->which);
251 else
252 foo = 0;
253 }
254
255 /*
256 * foo is used to indicate the the current screen has no windows.
257 * This happens when we create a new screen.. either way, we want
258 * to go on to the next screen, so if foo isn't set, then if which
259 * is already null, return it again (this should never happen, if
260 * window_traverse()'s is called properly), else move on to
261 * the next window
262 */
263 if (foo)
264 {
265 if (!wt->which)
266 return NULL;
267 else
268 wt->which = wt->which->next;
269 }
270
271 if (!wt->which)
272 {
273 while (wt->screen)
274 {
275 wt->screen = screen_get_next(wt->screen);
276 if (wt->screen && screen_get_alive(wt->screen))
277 break;
278 }
279 if (wt->screen)
280 wt->which = screen_get_window_list(wt->screen);
281 }
282
283 if (wt->which)
284 return (wt->which);
285 /*
286 * Got to the end of the visible list.. so we do the invisible list..
287 * Should also mean, that we've got to the end of all the visible
288 * screen..
289 */
290 if (wt->visible)
291 {
292 wt->visible = 0;
293 wt->which = invisible_list;
294 return (wt->which);
295 }
296 return (NULL);
297 }
298
299 void
add_window_to_server_group(Window * window,u_char * group)300 add_window_to_server_group(Window *window, u_char *group)
301 {
302 int i = find_server_group(group, 1);
303 Win_Trav wt;
304 Window *tmp;
305
306 wt.init = 1;
307 while ((tmp = window_traverse(&wt)) != NULL)
308 if ((tmp->server_group == i) && (tmp->server != window->server))
309 {
310 say("Group %s already contains a different server", group);
311 return;
312 }
313 window->server_group = i;
314 say("Window's server group is now %s", group);
315 update_window_status(window, 1);
316 }
317
318 /*
319 * set_scroll_lines: called by /SET SCROLL_LINES to check the scroll lines
320 * value
321 */
322 void
set_scroll_lines(int size)323 set_scroll_lines(int size)
324 {
325 if (size == 0)
326 {
327 set_var_value(SCROLL_VAR, UP(var_settings(0)));
328 if (curr_scr_win)
329 curr_scr_win->scroll = 0;
330 }
331 else if (size > curr_scr_win->display_size)
332 {
333 say("Maximum lines that may be scrolled is %d",
334 curr_scr_win->display_size);
335 set_int_var(SCROLL_LINES_VAR, (u_int)curr_scr_win->display_size);
336 }
337 }
338
339 /*
340 * scroll_window: Given a pointer to a window, this determines if that window
341 * should be scrolled, or the cursor moved to the top of the screen again, or
342 * if it should be left alone.
343 */
344 void
scroll_window(Window * window)345 scroll_window(Window *window)
346 {
347 if (term_basic())
348 return;
349 if (window->cursor == window->display_size)
350 {
351 if (window->scroll)
352 {
353 int do_scroll,
354 i;
355
356 if ((do_scroll = get_int_var(SCROLL_LINES_VAR)) <= 0)
357 do_scroll = 1;
358
359 for (i = 0; i < do_scroll; i++)
360 {
361 new_free(&window->top_of_display->line);
362 window->top_of_display =
363 window->top_of_display->next;
364 }
365 if (window->visible)
366 {
367 if (term_scroll(window->top + window_menu_lines(window),
368 window->top + window_menu_lines(window) + window->cursor - 1,
369 do_scroll))
370 {
371 if (number_of_windows() == 1)
372 {
373 Window *tmp;
374
375 /*
376 * this method of sim-u-scroll seems to work fairly
377 * well. The penalty is that you can only have one
378 * window, and of course you can't use the scrollback
379 * buffer either. Or menus. Actually, this method
380 * really doesn't work very well at all anymore.
381 */
382 tmp = get_cursor_window();
383 term_move_cursor(0, get_li() - 2);
384 if (term_clear_to_eol())
385 term_space_erase(0);
386 term_cr();
387 term_newline();
388 for (i = 0; i < do_scroll; i++)
389 {
390 term_cr();
391 term_newline();
392 }
393 update_window_status(window, 1);
394 update_input(UPDATE_ALL);
395 set_cursor_window(tmp);
396 Debug(DB_SCROLL, "scroll_window: screen %d cursor_window set to window %d (%d)",
397 screen_get_screennum(get_current_screen()), window->refnum,
398 screen_get_screennum(window->screen));
399 }
400 else
401 redraw_window(window, 1, 0);
402 }
403 window->cursor -= do_scroll;
404 term_move_cursor(0, window->cursor + window->top + window_menu_lines(window));
405 }
406 else
407 window->cursor -= do_scroll;
408 }
409 else
410 {
411 window->cursor = 0;
412 if (window->visible)
413 term_move_cursor(0, window->top + window_menu_lines(window));
414 }
415 }
416 else if (window->visible && get_cursor_window() == window)
417 {
418 term_cr();
419 term_newline();
420 }
421 if (window->visible && get_cursor_window())
422 {
423 if (term_clear_to_eol()) /* && !window->hold_mode && !window->hold_on_next_rite) */
424 {
425 term_space_erase(0);
426 term_cr();
427 }
428 term_flush();
429 }
430 }
431
432 /*
433 * set_scroll: called by /SET SCROLL to make sure the SCROLL_LINES variable
434 * is set correctly
435 */
436 void
set_scroll(int value)437 set_scroll(int value)
438 {
439 if (value && (get_int_var(SCROLL_LINES_VAR) == 0))
440 {
441 put_it("You must set SCROLL_LINES to a positive value first!");
442 if (curr_scr_win)
443 curr_scr_win->scroll = 0;
444 }
445 else
446 {
447 if (curr_scr_win)
448 {
449 int old_value = curr_scr_win->scroll;
450
451 curr_scr_win->scroll = value;
452 if (old_value != value)
453 scroll_window(curr_scr_win);
454 }
455 }
456 }
457
458 /*
459 * this is where the real work of scrolling backwards and forwards
460 * through the history is done.
461 *
462 * what happens is some functions are called from other code to
463 * make scroll requests: forward, back, start, end. these functions
464 * do some minor house keeping, and then call the function
465 * display_lastlog_lines() to do the real work.
466 *
467 * we keep a split up copy of each line attached to the Display
468 * structure, as well as the original full line, so we can split
469 * it up again when the number of columns changes. this splitting
470 * can occur either when adding the lines to the lastlog itself,
471 * or, if the line wasn't added to the lastlog, directly below
472 * by calling split_up_line().
473 */
474
475 /*
476 * how many lastlog lines in this window?
477 */
478 static int
lastlog_lines(Window * window)479 lastlog_lines(Window *window)
480 {
481 Display *Disp;
482 int num_lines = 0, i;
483 LastlogLineBackInfo *info;
484
485 info = lastlog_line_back_alloc(window);
486
487 for (i = window->new_scrolled_lines; i--; num_lines++)
488 (void)lastlog_line_back(info);
489
490 for (i = 0, Disp = window->top_of_display; i < window->display_size;
491 Disp = Disp->next, i++)
492 if (Disp->linetype)
493 (void)lastlog_line_back(info);
494
495 while (lastlog_line_back(info))
496 num_lines++;
497
498 lastlog_line_back_free(info);
499
500 Debug(DB_LASTLOG, " num_lines ends up as %d", num_lines);
501 return (num_lines);
502 }
503
504 /*
505 * in window "window", display the lastlog lines from "start" to "end".
506 */
507 static void
display_lastlog_lines(int start,int end,Window * window)508 display_lastlog_lines(int start, int end, Window *window)
509 {
510 Display *Disp;
511 u_char *Line;
512 int i;
513 LastlogLineBackInfo *info;
514
515 info = lastlog_line_back_alloc(window);
516
517 for (i = window->new_scrolled_lines; i--;)
518 (void)lastlog_line_back(info);
519
520 for (i = 0, Disp = window->top_of_display; i < window->display_size;
521 Disp = Disp->next, i++)
522 if (Disp->linetype)
523 (void)lastlog_line_back(info);
524
525 for (i = 0; i < start; i++)
526 (void)lastlog_line_back(info);
527
528 for (; i < end; i++)
529 {
530 if (!(Line = lastlog_line_back(info)))
531 break;
532 term_move_cursor(0, window->top + window_menu_lines(window) +
533 window->scrolled_lines - i - 1);
534 rite(window, Line, 0, 0, 1, 0);
535 }
536
537 lastlog_line_back_free(info);
538 }
539
540 /*
541 * scrollback_{back,forw}wards_lines: scroll the named distance, called by
542 * internal functions here.
543 */
544 static void
scrollback_backwards_lines(int ScrollDist)545 scrollback_backwards_lines(int ScrollDist)
546 {
547 Window *window;
548 int totallines;
549
550 Debug(DB_SCROLL, "scrollback_backwards_lines(%d)", ScrollDist);
551 window = curr_scr_win;
552 if (!window->scrolled_lines && !window->scroll)
553 {
554 term_beep();
555 return;
556 }
557 totallines = lastlog_lines(window);
558 Debug(DB_SCROLL, "totallines = %d, scrolled_lines = %d", totallines, window->scrolled_lines);
559 if (ScrollDist + window->scrolled_lines > totallines)
560 {
561 ScrollDist = totallines - window->scrolled_lines;
562 Debug(DB_SCROLL, " adjusting ScrollDist to %d", ScrollDist);
563 }
564 if (ScrollDist == 0)
565 {
566 term_beep();
567 return;
568 }
569 window->scrolled_lines += ScrollDist;
570
571 Debug(DB_SCROLL, "going to term_scroll(%d, %d, %d)",
572 window->top + window_menu_lines(window),
573 window->top + window_menu_lines(window) + window->display_size - 1,
574 -ScrollDist);
575 term_scroll(window->top + window_menu_lines(window),
576 window->top + window_menu_lines(window) + window->display_size - 1,
577 -ScrollDist);
578
579 Debug(DB_SCROLL, "scrolled_lines=%d, new_scrolled_lines=%d, display_size=%d",
580 window->scrolled_lines,
581 window->new_scrolled_lines,
582 window->display_size);
583
584 Debug(DB_SCROLL, "going to display_lastlog_lines(%d, %d, %s)",
585 window->scrolled_lines - ScrollDist,
586 window->scrolled_lines,
587 window->name);
588 display_lastlog_lines(window->scrolled_lines - ScrollDist,
589 window->scrolled_lines,
590 window);
591 cursor_not_in_display();
592 update_input(UPDATE_JUST_CURSOR);
593 window->update |= UPDATE_STATUS;
594 update_window_status(window, 0);
595 }
596
597 static void
scrollback_forwards_lines(int ScrollDist)598 scrollback_forwards_lines(int ScrollDist)
599 {
600 Window *window;
601
602 Debug(DB_SCROLL, "scrollback_forward_lines(%d)", ScrollDist);
603 window = curr_scr_win;
604 if (!window->scrolled_lines)
605 {
606 term_beep();
607 return;
608 }
609 if (ScrollDist > window->scrolled_lines)
610 ScrollDist = window->scrolled_lines;
611
612 Debug(DB_SCROLL, "scrolled_lines = %d", window->scrolled_lines);
613 window->scrolled_lines -= ScrollDist;
614 Debug(DB_SCROLL, "going to term_scroll(%d, %d, %d)",
615 window->top + window_menu_lines(window),
616 window->top + window_menu_lines(window) + window->display_size - 1,
617 ScrollDist);
618 term_scroll(window->top + window_menu_lines(window),
619 window->top + window_menu_lines(window) + window->display_size - 1,
620 ScrollDist);
621
622 Debug(DB_SCROLL, "scrolled_lines=%d, new_scrolled_lines=%d, display_size=%d",
623 window->scrolled_lines,
624 window->new_scrolled_lines,
625 window->display_size);
626
627 if (window->scrolled_lines < window->display_size)
628 redraw_window(window,
629 ScrollDist + window->scrolled_lines - window->display_size, 1);
630
631 Debug(DB_SCROLL, "going to display_lastlog_lines(%d, %d, %s)",
632 window->scrolled_lines - window->display_size,
633 window->scrolled_lines - window->display_size + ScrollDist,
634 window->name);
635 display_lastlog_lines(window->scrolled_lines - window->display_size,
636 window->scrolled_lines - window->display_size + ScrollDist,
637 window);
638 cursor_not_in_display();
639 update_input(UPDATE_JUST_CURSOR);
640
641 if (!window->scrolled_lines)
642 {
643 window->new_scrolled_lines = 0;
644 if (window->hold_mode)
645 window_hold_mode(window, ON, 1);
646 else
647 window_hold_mode(window, OFF, 0);
648 }
649 window->update |= UPDATE_STATUS;
650 update_window_status(window, 0);
651 }
652
653 /*
654 * scrollback_{forw,back}wards: scrolls the window up or down half the screen.
655 * these are called when the respective key are pressed.
656 */
657 void
scrollback_forwards(u_int key,u_char * ptr)658 scrollback_forwards(u_int key, u_char *ptr)
659 {
660 scrollback_forwards_lines(curr_scr_win->display_size/2);
661 }
662
663 void
scrollback_backwards(u_int key,u_char * ptr)664 scrollback_backwards(u_int key, u_char *ptr)
665 {
666 scrollback_backwards_lines(curr_scr_win->display_size/2);
667 }
668
669 /*
670 * scrollback_end: exits scrollback mode and moves the display back
671 * to the end of the scrollback buffer.
672 */
673 void
scrollback_end(u_int key,u_char * ptr)674 scrollback_end(u_int key, u_char *ptr)
675 {
676 Window *window;
677
678 window = curr_scr_win;
679 window->new_scrolled_lines = 0;
680
681 if (!window->scrolled_lines)
682 {
683 term_beep();
684 return;
685 }
686 if (window->scrolled_lines < window->display_size)
687 scrollback_forwards_lines(window->scrolled_lines);
688 else
689 {
690 window->scrolled_lines = window->new_scrolled_lines = 0;
691 redraw_window(window, 1, 1);
692 cursor_not_in_display();
693 update_input(UPDATE_JUST_CURSOR);
694 if (window->hold_mode)
695 window_hold_mode(window, ON, 1);
696 else
697 window_hold_mode(window, OFF, 0);
698 window->update |= UPDATE_STATUS;
699 update_window_status(window, 0);
700 }
701 }
702
703 /*
704 * scrollback_start: moves the current screen back to the start of
705 * the scrollback buffer.
706 */
707 void
scrollback_start(u_int key,u_char * ptr)708 scrollback_start(u_int key, u_char *ptr)
709 {
710 Window *window;
711 int num_lines;
712
713 window = curr_scr_win;
714 if (!window_get_lastlog_size(window))
715 {
716 term_beep();
717 return;
718 }
719
720 Debug(DB_SCROLL, "scrollback_start: new_scrolled_lines=%d display_size=%d",
721 window->new_scrolled_lines, window->display_size);
722 num_lines = lastlog_lines(window);
723
724 if (num_lines < window->display_size)
725 scrollback_backwards_lines(num_lines);
726 else
727 {
728 window->scrolled_lines = num_lines;
729 Debug(DB_SCROLL, "going to display_lastlog_lines(%d, %d, %s)",
730 num_lines - window->display_size, window->scrolled_lines, window->name);
731 display_lastlog_lines(num_lines - window->display_size,
732 window->scrolled_lines, window);
733 cursor_not_in_display();
734 update_input(UPDATE_JUST_CURSOR);
735 window->new_scrolled_lines = 0;
736 if (window->hold_mode)
737 window_hold_mode(window, ON, 1);
738 else
739 window_hold_mode(window, OFF, 0);
740 window->update |= UPDATE_STATUS;
741 update_window_status(window, 0);
742 }
743 }
744
745 /*
746 * window_refresh_lastlog: Backend for the REFRESH_WINDOW_LASTLOG
747 * function and more.
748 *
749 * this clears the screen and redisplays the end of the lastlog while
750 * also ensuring scrolling up works properly. it's kind of like a
751 * reverse ^L.
752 */
753 void
window_refresh_lastlog(Window * window)754 window_refresh_lastlog(Window *window)
755 {
756 Display *next;
757 LastlogLineBackInfo *info;
758 StringList *sl;
759 u_char *line;
760 size_t iter;
761 int cnt;
762
763 sl = sl_init();
764 info = lastlog_line_back_alloc(window);
765
766 for (cnt = 0; cnt < window->display_size; cnt++)
767 {
768 line = lastlog_line_back(info);
769 if (!line)
770 break;
771 sl_add(sl, CP(line));
772 }
773
774 erase_display(window);
775
776 iter = 0;
777 for (next = window->top_of_display;
778 (line = sl_iter_rev(sl, &iter)) != NULL;
779 window->cursor++, next = next->next)
780 {
781 malloc_strcpy(&next->line, line);
782 next->linetype = 1;
783 }
784 window->display_ip = next;
785 window->line_cnt = 1;
786
787 redraw_window(window, 1, 1);
788 cursor_not_in_display();
789 if (window->hold_mode)
790 window_hold_mode(window, ON, 1);
791 else
792 window_hold_mode(window, OFF, 0);
793 window->update |= UPDATE_STATUS;
794 update_window_status(window, 0);
795
796 sl_free(sl, 0);
797 lastlog_line_back_free(info);
798 }
799
800 /*
801 * window_refresh_lastlog_key: REFRESH_WINDOW_LASTLOG frontend
802 */
803 void
window_refresh_lastlog_key(u_int key,u_char * ptr)804 window_refresh_lastlog_key(u_int key, u_char *ptr)
805 {
806 window_refresh_lastlog(curr_scr_win);
807 }
808
809 /*
810 * update_all_windows: This goes through each visible window and draws the
811 * necessary portions according the the update field of the window.
812 */
813 void
update_all_windows(void)814 update_all_windows(void)
815 {
816 Window *tmp;
817 int fast_window,
818 full_window,
819 r_status,
820 u_status;
821
822 for (tmp = screen_get_window_list(get_current_screen()); tmp; tmp = window_get_next(tmp))
823 {
824 if (tmp->display_size != tmp->old_size)
825 resize_display(tmp);
826 if (tmp->update)
827 {
828 fast_window = tmp->update & REDRAW_DISPLAY_FAST;
829 full_window = tmp->update & REDRAW_DISPLAY_FULL;
830 r_status = tmp->update & REDRAW_STATUS;
831 u_status = tmp->update & UPDATE_STATUS;
832 if (full_window)
833 redraw_window(tmp, 1, 0);
834 else if (fast_window)
835 redraw_window(tmp, 0, 0);
836 if (r_status)
837 update_window_status(tmp, 1);
838 else if (u_status)
839 update_window_status(tmp, 0);
840 }
841 tmp->update = 0;
842 }
843 for (tmp = invisible_list; tmp; tmp = window_get_next(tmp))
844 {
845 if (tmp->display_size != tmp->old_size)
846 resize_display(tmp);
847 tmp->update = 0;
848 }
849 update_input(UPDATE_JUST_CURSOR);
850 term_flush();
851 }
852
853 /*
854 * reset_line_cnt: called by /SET HOLD_MODE to reset the line counter so we
855 * always get a held screen after the proper number of lines
856 */
857 void
reset_line_cnt(int value)858 reset_line_cnt(int value)
859 {
860 curr_scr_win->hold_mode = value;
861 curr_scr_win->hold_on_next_rite = 0;
862 curr_scr_win->line_cnt = 0;
863 }
864
865 /*
866 * XXX This needs to be rewritten to not use fixed-size arrays
867 * XXX for both output[] and lbuf[].
868 */
869 #define MAXIMUM_SPLITS 80
870 static u_char **
split_up_line(u_char * str)871 split_up_line(u_char *str)
872 {
873 static u_char *output[MAXIMUM_SPLITS] =
874 {
875 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
876 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
877 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
878 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
879 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
880 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
881 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
882 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
883 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
884 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
885 };
886 u_char lbuf[BIG_BUFFER_SIZE];
887 u_char *ptr;
888 u_char *cont_ptr,
889 *cont = NULL,
890 *temp = NULL,
891 *mystr = NULL,
892 c;
893 int pos = 0,
894 col = 0,
895 nd_cnt = 0,
896 word_break = 0,
897 start = 0,
898 i,
899 indent = 0,
900 beep_cnt = 0,
901 beep_max,
902 tab_cnt = 0,
903 tab_max,
904 line = 0;
905 int bold_state = 0,
906 invert_state = 0,
907 underline_state = 0,
908 fg_colour_state = 16,
909 bg_colour_state = 16;
910 size_t len;
911
912 struct mb_data mbdata;
913 #ifdef HAVE_ICONV_OPEN
914 mbdata_init(&mbdata, CP(current_irc_encoding()));
915 #else
916 mbdata_init(&mbdata, NULL);
917 #endif /* HAVE_ICONV_OPEN */
918
919 memset(lbuf, 0, sizeof(lbuf));
920
921 for (i = 0; i < MAXIMUM_SPLITS; i++)
922 new_free(&output[i]);
923 if (!str || !*str)
924 {
925 /* special case to make blank lines show up */
926 malloc_strcpy(&mystr, UP(" "));
927 str = mystr;
928 }
929
930 beep_max = get_int_var(BEEP_VAR) ? get_int_var(BEEP_MAX_VAR) : -1;
931 tab_max = get_int_var(TAB_VAR) ? get_int_var(TAB_MAX_VAR) : -1;
932 for (ptr = (u_char *) str; *ptr && (pos < sizeof(lbuf) - 8); ptr++)
933 {
934 switch (*ptr)
935 {
936 case '\007': /* bell */
937 if (beep_max == -1)
938 {
939 lbuf[pos++] = REV_TOG;
940 lbuf[pos++] = (*ptr & 127) | 64;
941 lbuf[pos++] = REV_TOG;
942 nd_cnt += 2;
943 col++;
944 }
945 else if (!beep_max || (++beep_cnt <= beep_max))
946 {
947 lbuf[pos++] = *ptr;
948 nd_cnt++;
949 col++;
950 }
951 break;
952 case '\011': /* tab */
953 if (tab_max && (++tab_cnt > tab_max))
954 {
955 lbuf[pos++] = REV_TOG;
956 lbuf[pos++] = (*ptr & 127) | 64;
957 lbuf[pos++] = REV_TOG;
958 nd_cnt += 2;
959 col++;
960 }
961 else
962 {
963 if (indent == 0)
964 indent = -1;
965 len = 8 - (col % 8);
966 word_break = pos;
967 for (i = 0; i < len; i++)
968 lbuf[pos++] = ' ';
969 col += len;
970 }
971 break;
972 case UND_TOG:
973 case ALL_OFF:
974 case REV_TOG:
975 case BOLD_TOG:
976 switch(*ptr)
977 {
978 case UND_TOG:
979 underline_state = !underline_state;
980 break;
981 case REV_TOG:
982 invert_state = !invert_state;
983 break;
984 case BOLD_TOG:
985 bold_state = !bold_state;
986 break;
987 case ALL_OFF:
988 underline_state = invert_state = bold_state = 0;
989 fg_colour_state = bg_colour_state = 16;
990 break;
991 }
992 lbuf[pos++] = *ptr;
993 nd_cnt++;
994 break;
995 case COLOUR_TAG:
996 {
997 int fg, bg;
998
999 lbuf[pos++] = *ptr++;
1000 decode_colour(&ptr, &fg, &bg);
1001
1002 lbuf[pos++] = (u_char)(fg_colour_state = fg) + 1;
1003 lbuf[pos++] = (u_char)(bg_colour_state = bg) + 1;
1004 nd_cnt += 3;
1005 break;
1006 }
1007 case ' ': /* word break */
1008 if (indent == 0)
1009 indent = -1;
1010 word_break = pos;
1011 lbuf[pos++] = *ptr;
1012 col++;
1013 break;
1014 default: /* Anything else, make it displayable */
1015 if (indent == -1)
1016 indent = pos - nd_cnt;
1017
1018 decode_mb(ptr, lbuf + pos, sizeof(lbuf) - pos, &mbdata);
1019
1020 /* If the sequence takes multiple columns,
1021 * be wrappable now when we can
1022 */
1023 if (mbdata.num_columns > 1)
1024 word_break = pos;
1025
1026 pos += mbdata.output_bytes;
1027 nd_cnt += mbdata.output_bytes - mbdata.num_columns;
1028 ptr += mbdata.input_bytes - 1;
1029 col += mbdata.num_columns;
1030 break;
1031 }
1032 if (pos >= sizeof(lbuf) - 1)
1033 *ptr = '\0';
1034
1035 if (col > get_co())
1036 {
1037 char c1;
1038 int oldpos;
1039
1040 /* one big long line, no word breaks */
1041 if (word_break == 0)
1042 word_break = pos - (col - get_co());
1043 c = lbuf[word_break];
1044 c1 = lbuf[word_break+1];
1045 lbuf[word_break] = FULL_OFF;
1046 lbuf[word_break+1] = '\0';
1047 if (cont)
1048 {
1049 malloc_strcpy(&temp, cont);
1050 malloc_strcat(&temp, &lbuf[start]);
1051 }
1052 else
1053 malloc_strcpy(&temp, &lbuf[start]);
1054 malloc_strcpy(&output[line++], temp);
1055 if (line == MAXIMUM_SPLITS)
1056 break;
1057 lbuf[word_break] = c;
1058 lbuf[word_break+1] = c1;
1059 start = word_break;
1060 word_break = 0;
1061 while (lbuf[start] == ' ')
1062 start++;
1063 if (start > pos)
1064 start = pos;
1065
1066 if (!(cont_ptr = get_string_var(CONTINUED_LINE_VAR)))
1067 cont_ptr = empty_string();
1068
1069 if (!cont) /* Build it only the first time */
1070 {
1071 if (get_int_var(INDENT_VAR) && (indent < get_co() / 3))
1072 {
1073 /* Visual length */
1074 int vlen = my_strlen_c(cont_ptr);
1075 /* Converted length */
1076 int clen = my_strlen_ci(cont_ptr);
1077 int padlen = indent - vlen;
1078
1079 if (padlen < 0)
1080 padlen = 0;
1081
1082 cont = new_malloc(clen + padlen + 1);
1083 my_strcpy_ci(cont, clen + padlen + 1,
1084 cont_ptr);
1085
1086 for (; padlen > 0; --padlen)
1087 {
1088 cont[clen++] = ' ';
1089 /* Add space */
1090 }
1091 cont[clen] = '\0';
1092 }
1093 else
1094 {
1095 /* Converted length */
1096 int clen = my_strlen_ci(cont_ptr);
1097
1098 /* No indent, just prefix only */
1099 cont = new_malloc(clen + 1);
1100 my_strcpy_ci(cont, clen + 1, cont_ptr);
1101 }
1102 }
1103
1104 /* cont contains internal codes, so use my_strlen_i */
1105 col = my_strlen_i(cont) + (pos - start);
1106
1107 /* rebuild previous state */
1108 oldpos = pos;
1109 if (underline_state)
1110 {
1111 lbuf[pos++] = UND_TOG;
1112 nd_cnt++;
1113 }
1114 if (invert_state)
1115 {
1116 lbuf[pos++] = REV_TOG;
1117 nd_cnt++;
1118 }
1119 if (bold_state)
1120 {
1121 lbuf[pos++] = BOLD_TOG;
1122 nd_cnt++;
1123 }
1124 if (fg_colour_state != 16 || bg_colour_state != 16)
1125 {
1126 lbuf[pos++] = COLOUR_TAG;
1127 lbuf[pos++] = fg_colour_state + 1;
1128 lbuf[pos++] = bg_colour_state + 1;
1129 nd_cnt++;
1130 }
1131 if (pos != oldpos)
1132 while (start < oldpos)
1133 lbuf[pos++] = lbuf[start++];
1134 }
1135 }
1136 mbdata_done(&mbdata);
1137
1138 if (line < MAXIMUM_SPLITS) {
1139 lbuf[pos++] = FULL_OFF;
1140 lbuf[pos] = '\0';
1141 if (lbuf[start])
1142 {
1143 if (cont)
1144 {
1145 malloc_strcpy(&temp, cont);
1146 malloc_strcat(&temp, &lbuf[start]);
1147 }
1148 else
1149 malloc_strcpy(&temp, &lbuf[start]);
1150 malloc_strcpy(&output[line++], temp);
1151 }
1152 }
1153
1154 new_free(&mystr);
1155 new_free(&cont);
1156 new_free(&temp);
1157 return output;
1158 }
1159
1160 /*
1161 * split_up_line_alloc(): like split_up_line() except it doesn't
1162 * return the static arrays, but copies them. eventually when we
1163 * eliminate split_up_line() usage, we can make this entirely
1164 * dynamic.
1165 */
1166 u_char **
split_up_line_alloc(u_char * str)1167 split_up_line_alloc(u_char *str)
1168 {
1169 u_char **lines, **new_lines, **tmp;
1170 size_t total_lines = 0, count;
1171
1172 lines = split_up_line(str);
1173
1174 for (tmp = lines; *tmp; tmp++) {
1175 total_lines++;
1176 }
1177
1178 new_lines = new_malloc(sizeof(*new_lines) * (total_lines + 1));
1179
1180 /* Copy the pointers; clear the original from lines[] */
1181 for (count = 0; count < total_lines; count++) {
1182 new_lines[count] = lines[count];
1183 lines[count] = NULL;
1184 }
1185 new_lines[count] = NULL;
1186
1187 return new_lines;
1188 }
1189
1190 /*
1191 * add_to_window: adds the given string to the display. No kidding. This
1192 * routine handles the whole ball of wax. It keeps track of what's on the
1193 * screen, does the scrolling, everything... well, not quite everything...
1194 * The CONTINUED_LINE idea thanks to Jan L. Peterson (jlp@hamblin.byu.edu)
1195 *
1196 * At least it used to. Now most of this is done by split_up_line, and this
1197 * function just dumps it onto the screen. This is because the scrollback
1198 * functions need to be able to figure out how to split things up too.
1199 */
1200 void
add_to_window(Window * window,u_char * str)1201 add_to_window(Window *window, u_char *str)
1202 {
1203 int flag;
1204
1205 flag = do_hook(WINDOW_LIST, "%u %s", window_get_refnum(window), str);
1206
1207 if (flag)
1208 {
1209 size_t len = my_strlen(str);
1210 u_char *my_str = new_malloc(len + 2);
1211 u_char **lines, **curlinep, **freelines;
1212 int logged;
1213
1214 add_to_window_log(window, str);
1215 display_highlight(OFF);
1216 display_bold(OFF);
1217 display_colours(get_int_var(FOREGROUND_COLOUR_VAR),
1218 get_int_var(BACKGROUND_COLOUR_VAR));
1219 memmove(my_str, str, len);
1220 my_str[len] = ALL_OFF;
1221 my_str[len + 1] = '\0';
1222 lines = add_to_lastlog(window, my_str);
1223 if (!lines)
1224 freelines = lines = split_up_line(my_str);
1225 logged = islogged(window);
1226 /*
1227 * For each of the lines created by split_up_line(),
1228 * display the line.
1229 * rite() will assume each input line fits on 1 line.
1230 */
1231 for (curlinep = lines; *curlinep; curlinep++)
1232 rite(window, *curlinep, 0, 0, 0, logged);
1233 new_free(&my_str);
1234 if (0)
1235 new_free(&freelines);
1236 term_flush();
1237 }
1238 }
1239
1240 /*
1241 * set_continued_line: checks the value of CONTINUED_LINE for validity,
1242 * altering it if its no good
1243 */
1244 void
set_continued_line(u_char * value)1245 set_continued_line(u_char *value)
1246 {
1247 if (value && ((int) my_strlen(value) > (get_co() / 2)))
1248 value[get_co() / 2] = '\0';
1249 }
1250
1251 static void
remove_from_invisible_list(Window * window)1252 remove_from_invisible_list(Window *window)
1253 {
1254 window->visible = 1;
1255 window->screen = get_current_screen();
1256 window->miscflags &= ~WINDOW_NOTIFIED;
1257 if (window->prev)
1258 window->prev->next = window->next;
1259 else
1260 invisible_list = window->next;
1261 if (window->next)
1262 window->next->prev = window->prev;
1263 }
1264
1265 void
add_to_invisible_list(Window * window)1266 add_to_invisible_list(Window *window)
1267 {
1268 if ((window->next = invisible_list) != NULL)
1269 invisible_list->prev = window;
1270 invisible_list = window;
1271 window->prev = NULL;
1272 window->visible = 0;
1273 window->screen = NULL;
1274 }
1275
1276 /*
1277 * swap_window: This swaps the given window with the current window. The
1278 * window passed must be invisible. Swapping retains the positions of both
1279 * windows in their respective window lists, and retains the dimensions of
1280 * the windows as well, but update them depending on the number of status
1281 * lines displayed
1282 */
1283 static void
swap_window(Window * v_window,Window * window)1284 swap_window(Window *v_window, Window *window)
1285 {
1286 Window tmp, *prev, *next;
1287 int top, bottom, size;
1288
1289 if (window->visible || !v_window->visible)
1290 {
1291 say("You can only SWAP a hidden window with a visible window.");
1292 return;
1293 }
1294
1295 channel_swap_win_ptr(v_window, window);
1296
1297 prev = v_window->prev;
1298 next = v_window->next;
1299
1300 set_last_window_refnum(v_window->refnum);
1301 remove_from_invisible_list(window);
1302
1303 tmp = *v_window;
1304 *v_window = *window;
1305 v_window->top = tmp.top;
1306 v_window->bottom = tmp.bottom + tmp.double_status -
1307 v_window->double_status;
1308 v_window->display_size = tmp.display_size + menu_lines(tmp.menu) +
1309 tmp.double_status -
1310 menu_lines(v_window->menu) - v_window->double_status -
1311 SCROLL_DISPLAY_OFFSET;
1312 v_window->prev = prev;
1313 v_window->next = next;
1314
1315 /* I don't understand the use of the following, I'll ignore it
1316 * If double status screws window sizes, I should look here
1317 * again - krys
1318 */
1319 top = window->top;
1320 bottom = window->bottom;
1321 size = window->display_size;
1322 *window = tmp;
1323 window->top = top;
1324 window->bottom = bottom - tmp.double_status;
1325 window->display_size = size - SCROLL_DISPLAY_OFFSET;
1326
1327 add_to_invisible_list(window);
1328
1329 v_window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
1330 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
1331
1332 do_hook(WINDOW_SWAP_LIST, "%d %d", v_window->refnum, window->refnum);
1333 }
1334
1335 /*
1336 * move_window: This moves a window offset positions in the window list. This
1337 * means, of course, that the window will move on the screen as well
1338 */
1339 static void
move_window(Window * window,int offset)1340 move_window(Window *window, int offset)
1341 {
1342 Window *tmp, *last;
1343 int win_pos, pos, num;
1344
1345 if (offset == 0)
1346 return;
1347 last = NULL;
1348 for (win_pos = 0, tmp = screen_get_window_list(get_current_screen()); tmp;
1349 tmp = tmp->next, win_pos++)
1350 {
1351 if (window == tmp)
1352 break;
1353 last = tmp;
1354 }
1355 if (tmp == NULL)
1356 return;
1357 if (last == NULL)
1358 screen_set_window_list(get_current_screen(), tmp->next);
1359 else
1360 last->next = tmp->next;
1361 if (tmp->next)
1362 tmp->next->prev = last;
1363 else
1364 screen_set_window_list_end(get_current_screen(), last);
1365 num = screen_get_visible_windows(window->screen);
1366 win_pos = (offset + win_pos) % num;
1367 if (win_pos < 0)
1368 win_pos = num + win_pos;
1369 last = NULL;
1370 for (pos = 0, tmp = screen_get_window_list(get_current_screen());
1371 pos != win_pos; tmp = tmp->next, pos++)
1372 last = tmp;
1373 if (last == NULL)
1374 screen_set_window_list(get_current_screen(), window);
1375 else
1376 last->next = window;
1377 if (tmp)
1378 tmp->prev = window;
1379 else
1380 screen_set_window_list_end(get_current_screen(), window);
1381 window->prev = last;
1382 window->next = tmp;
1383 recalculate_window_positions();
1384 }
1385
1386 /*
1387 * grow_window: This will increase or descrease the size of the given window
1388 * by offset lines (positive offset increases, negative decreases).
1389 * Obviously, with a fixed terminal size, this means that some other window
1390 * is going to have to change size as well. Normally, this is the next
1391 * window in the window list (the window below the one being changed) unless
1392 * the window is the last in the window list, then the previous window is
1393 * changed as well
1394 */
1395 static void
grow_window(Window * window,int offset)1396 grow_window(Window *window, int offset)
1397 {
1398 Window *other,
1399 *tmp;
1400 int after,
1401 window_size,
1402 other_size;
1403
1404 if (window == NULL)
1405 window = curr_scr_win;
1406 if (!window->visible)
1407 {
1408 say("You cannot change the size of hidden windows!");
1409 return;
1410 }
1411 if (window->next)
1412 {
1413 other = window->next;
1414 after = 1;
1415 }
1416 else
1417 {
1418 other = NULL;
1419 for (tmp = screen_get_window_list(get_current_screen()); tmp; tmp = tmp->next)
1420 {
1421 if (tmp == window)
1422 break;
1423 other = tmp;
1424 }
1425 if (other == NULL)
1426 {
1427 say("Can't change the size of this window!");
1428 return;
1429 }
1430 after = 0;
1431 }
1432 window_size = window->display_size + offset;
1433 other_size = other->display_size - offset;
1434 if ((window_size < 4) || (other_size < 4))
1435 {
1436 say("Not enough room to resize this window!");
1437 return;
1438 }
1439 if (after)
1440 {
1441 window->bottom += offset;
1442 other->top += offset;
1443 }
1444 else
1445 {
1446 window->top -= offset;
1447 other->bottom -= offset;
1448 }
1449 window->display_size = window_size - SCROLL_DISPLAY_OFFSET;
1450 other->display_size = other_size - SCROLL_DISPLAY_OFFSET;
1451 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
1452 other->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
1453 term_flush();
1454 }
1455
1456 /*
1457 * the message_from stack structure.
1458 */
1459 static struct mfstack
1460 {
1461 u_char *who_from; /* saved from */
1462 int who_level; /* saved level */
1463 struct mfstack *next; /* next in the list */
1464 } mfstack_head = { NULL, 0, NULL };
1465
1466 /*
1467 * save_message_from: this is used to save (for later restoration) the
1468 * who_from variable. This comes in handy very often when a routine might
1469 * call another routine that might change who_from. Note that if you
1470 * call this routine, you *must* call restore_message_from().
1471 */
1472 void
save_message_from(void)1473 save_message_from(void)
1474 {
1475 struct mfstack *mfs;
1476
1477 mfs = new_malloc(sizeof *mfs);
1478
1479 mfs->who_from = NULL;
1480 malloc_strcpy(&mfs->who_from, who_from);
1481 mfs->who_level = who_level;
1482 mfs->next = mfstack_head.next;
1483
1484 mfstack_head.next = mfs;
1485 }
1486
1487 /* restore_message_from: restores a previously saved who_from variable */
1488 void
restore_message_from(void)1489 restore_message_from(void)
1490 {
1491 struct mfstack *mfs = mfstack_head.next;
1492
1493 if (mfs == NULL)
1494 {
1495 /*yell("--- restore_message_from: NULL next pointer, fudging..");*/
1496 malloc_strcpy(&who_from, NULL);
1497 who_level = LOG_CRAP;
1498 }
1499 else
1500 {
1501 malloc_strcpy(&who_from, mfs->who_from);
1502 who_level = mfs->who_level;
1503 mfstack_head.next = mfs->next;
1504 new_free(&mfs->who_from);
1505 new_free(&mfs);
1506 }
1507 }
1508
1509 /*
1510 * message_from: With this you can the who_from variable and the who_level
1511 * variable, used by the display routines to decide which window messages
1512 * should go to.
1513 */
1514 void
message_from(u_char * who,int level)1515 message_from(u_char *who, int level)
1516 {
1517 malloc_strcpy(&who_from, who);
1518 who_level = level;
1519 }
1520
1521 /*
1522 * message_from_level: Like set_lastlog_msg_level, except for message_from.
1523 * this is needed by XECHO, because we could want to output things in more
1524 * than one level.
1525 */
1526 int
message_from_level(int level)1527 message_from_level(int level)
1528 {
1529 int temp;
1530
1531 temp = who_level;
1532 who_level = level;
1533 return temp;
1534 }
1535
1536 /*
1537 * get_window_by_refnum: Given a reference number to a window, this returns a
1538 * pointer to that window if a window exists with that refnum, null is
1539 * returned otherwise. The "safe" way to reference a window is throught the
1540 * refnum, since a window might be delete behind your back and and Window
1541 * pointers might become invalid.
1542 */
1543 Window *
get_window_by_refnum(u_int refnum)1544 get_window_by_refnum(u_int refnum)
1545 {
1546 Window *tmp;
1547
1548 if (refnum)
1549 {
1550 Win_Trav wt;
1551
1552 wt.init = 1;
1553 while ((tmp = window_traverse(&wt)) != NULL)
1554 {
1555 if (tmp->refnum == refnum)
1556 return (tmp);
1557 }
1558 }
1559 else
1560 return (curr_scr_win);
1561 return (NULL);
1562 }
1563
1564 /*
1565 * clear_window_by_refnum: just like clear_window(), but it uses a refnum. If
1566 * the refnum is invalid, the current window is cleared.
1567 */
1568 void
clear_window_by_refnum(u_int refnum)1569 clear_window_by_refnum(u_int refnum)
1570 {
1571 Window *tmp;
1572
1573 if ((tmp = get_window_by_refnum(refnum)) == NULL)
1574 tmp = curr_scr_win;
1575 clear_window(tmp);
1576 }
1577
1578 /*
1579 * revamp_window_levels: Given a level setting for the current window, this
1580 * makes sure that that level setting is unused by any other window. Thus
1581 * only one window in the system can be set to a given level. This only
1582 * revamps levels for windows with servers matching the given window
1583 * it also makes sure that only one window has the level `DCC', as this is
1584 * not dependant on a server.
1585 */
1586 static void
revamp_window_levels(Window * window)1587 revamp_window_levels(Window *window)
1588 {
1589 Window *tmp;
1590 Win_Trav wt;
1591 int got_dcc;
1592
1593 got_dcc = (LOG_DCC & window->window_level) ? 1 : 0;
1594 wt.init = 1;
1595 while ((tmp = window_traverse(&wt)) != NULL)
1596 {
1597 if (tmp == window)
1598 continue;
1599 if (LOG_DCC & tmp->window_level)
1600 {
1601 if (0 != got_dcc)
1602 tmp->window_level &= ~LOG_DCC;
1603 got_dcc = 1;
1604 }
1605 if (window->server == tmp->server)
1606 tmp->window_level ^= (tmp->window_level & window->window_level);
1607 }
1608 }
1609
1610 /*
1611 * set_level_by_refnum: This sets the window level given a refnum. It
1612 * revamps the windows levels as well using revamp_window_levels()
1613 */
1614 void
set_level_by_refnum(u_int refnum,int level)1615 set_level_by_refnum(u_int refnum, int level)
1616 {
1617 Window *tmp;
1618
1619 if ((tmp = get_window_by_refnum(refnum)) == NULL)
1620 tmp = curr_scr_win;
1621 tmp->window_level = level;
1622 revamp_window_levels(tmp);
1623 }
1624
1625 /*
1626 * set_prompt_by_refnum: changes the prompt for the given window. A window
1627 * prompt will be used as the target in place of the query user or current
1628 * channel if it is set
1629 */
1630 void
set_prompt_by_refnum(u_int refnum,u_char * prompt)1631 set_prompt_by_refnum(u_int refnum, u_char *prompt)
1632 {
1633 Window *tmp;
1634
1635 if ((tmp = get_window_by_refnum(refnum)) == NULL)
1636 tmp = curr_scr_win;
1637 malloc_strcpy(&tmp->prompt, prompt);
1638 }
1639
1640 /*
1641 * message_to: This allows you to specify a window (by refnum) as a
1642 * destination for messages. Used by EXEC routines quite nicely
1643 */
1644 void
message_to(u_int refnum)1645 message_to(u_int refnum)
1646 {
1647 if (refnum)
1648 set_to_window(get_window_by_refnum(refnum));
1649 else
1650 set_to_window(NULL);
1651 }
1652
1653 /*
1654 * get_next_window: This returns a pointer to the next *visible* window in
1655 * the window list. It automatically wraps at the end of the list back to
1656 * the beginning of the list
1657 */
1658 static Window *
get_next_window(void)1659 get_next_window(void)
1660 {
1661 if (curr_scr_win && curr_scr_win->next)
1662 return window_get_next(curr_scr_win);
1663 else
1664 return screen_get_window_list(get_current_screen());
1665 }
1666
1667 /*
1668 * get_previous_window: this returns the previous *visible* window in the
1669 * window list. This automatically wraps to the last window in the window
1670 * list
1671 */
1672 static Window *
get_previous_window(void)1673 get_previous_window(void)
1674 {
1675 if (curr_scr_win && curr_scr_win->prev)
1676 return window_get_prev(curr_scr_win);
1677 else
1678 return screen_get_window_list_end(get_current_screen());
1679 }
1680
1681 /*
1682 * set_current_window: This sets the "current" window to window. It also
1683 * keeps track of the last_get_current_screen()->current_window by setting it to the
1684 * previous current window. This assures you that the new current window is
1685 * visible.
1686 * If not, a new current window is chosen from the window list
1687 */
1688 void
set_current_window(Window * window)1689 set_current_window(Window *window)
1690 {
1691 Window *tmp;
1692 unsigned int refnum;
1693
1694 refnum = get_last_window_refnum();
1695 if (curr_scr_win)
1696 {
1697 curr_scr_win->update |= UPDATE_STATUS;
1698 set_last_window_refnum(curr_scr_win->refnum);
1699 }
1700 if ((window == NULL) || (!window->visible))
1701
1702 {
1703 if ((tmp = get_window_by_refnum(refnum)) && (tmp->visible))
1704 set_curr_scr_win(tmp);
1705 else
1706 set_curr_scr_win(get_next_window());
1707 }
1708 else
1709 set_curr_scr_win(window);
1710 curr_scr_win->update |= UPDATE_STATUS;
1711 }
1712
1713 /*
1714 * swap_last_window: This swaps the current window with the last window
1715 * that was hidden.
1716 */
1717
1718 void
swap_last_window(u_int key,u_char * ptr)1719 swap_last_window(u_int key, u_char *ptr)
1720 {
1721 if (invisible_list == NULL)
1722 {
1723 /* say("There are no hidden windows"); */
1724 /* Not sure if we need to warn - phone. */
1725 return;
1726 }
1727 swap_window(curr_scr_win, invisible_list);
1728 update_all_windows();
1729 cursor_to_input();
1730 }
1731
1732 /*
1733 * next_window_key: This switches the current window to the next visible window
1734 */
1735 void
next_window_key(u_int key,u_char * ptr)1736 next_window_key(u_int key, u_char *ptr)
1737 {
1738 if (number_of_windows() == 1)
1739 return;
1740 set_current_window(get_next_window());
1741 update_all_windows();
1742 }
1743
1744 /*
1745 * swap_next_window: This swaps the current window with the next hidden
1746 * window.
1747 */
1748
1749 void
swap_next_window(u_int key,u_char * ptr)1750 swap_next_window(u_int key, u_char *ptr)
1751 {
1752 Win_Trav wt;
1753 Window *tmp;
1754 u_int next = MAXINT;
1755 int smallest;
1756
1757 if (invisible_list == NULL)
1758 {
1759 say("There are no hidden windows");
1760 return;
1761 }
1762 smallest = curr_scr_win->refnum;
1763 wt.init = 1;
1764 while ((tmp = window_traverse(&wt)) != NULL)
1765 {
1766 if (!tmp->visible)
1767 {
1768 if (tmp->refnum < smallest)
1769 smallest = tmp->refnum;
1770 if ((tmp->refnum > curr_scr_win->refnum)
1771 && (next > tmp->refnum))
1772 next = tmp->refnum;
1773 }
1774 }
1775 if (next != MAXINT)
1776 tmp = get_window_by_refnum(next);
1777 else
1778 tmp = get_window_by_refnum((u_int)smallest);
1779 if (tmp)
1780 {
1781 swap_window(curr_scr_win, tmp);
1782 update_all_windows();
1783 update_all_status();
1784 cursor_to_input();
1785 }
1786 }
1787
1788 /*
1789 * previous_window: This switches the current window to the previous visible
1790 * window
1791 */
1792 void
previous_window(u_int key,u_char * ptr)1793 previous_window(u_int key, u_char *ptr)
1794 {
1795 if (number_of_windows() == 1)
1796 return;
1797 set_current_window(get_previous_window());
1798 update_all_windows();
1799 }
1800
1801 /*
1802 * swap_previous_window: This swaps the current window with the next
1803 * hidden window.
1804 */
1805
1806 void
swap_previous_window(u_int key,u_char * ptr)1807 swap_previous_window(u_int key, u_char *ptr)
1808 {
1809 Win_Trav wt;
1810 Window *tmp;
1811 int previous = 0;
1812 int largest;
1813
1814 if (invisible_list == NULL)
1815 {
1816 say("There are no hidden windows");
1817 return;
1818 }
1819 largest = curr_scr_win->refnum;
1820 wt.init = 1;
1821 while ((tmp = window_traverse(&wt)) != NULL)
1822 {
1823 if (!tmp->visible)
1824 {
1825 if (tmp->refnum > largest)
1826 largest = tmp->refnum;
1827 if ((tmp->refnum < curr_scr_win->refnum)
1828 && (previous < tmp->refnum))
1829 previous = tmp->refnum;
1830 }
1831 }
1832 if (previous)
1833 tmp = get_window_by_refnum((u_int)previous);
1834 else
1835 tmp = get_window_by_refnum((u_int)largest);
1836 if (tmp)
1837 {
1838 swap_window(curr_scr_win,tmp);
1839 update_all_windows();
1840 update_all_status();
1841 cursor_to_input();
1842 }
1843 }
1844
1845 /*
1846 * back_window: goes to the last window that was current. Swapping the
1847 * current window if the last window was hidden.
1848 */
1849
1850 void
back_window(u_int key,u_char * ptr)1851 back_window(u_int key, u_char *ptr)
1852 {
1853 Window *tmp;
1854
1855 tmp = get_window_by_refnum(get_last_window_refnum());
1856 if (tmp)
1857 {
1858 if (tmp->visible)
1859 set_current_window(tmp);
1860 else
1861 {
1862 swap_window(curr_scr_win, tmp);
1863 update_all_windows();
1864 update_all_status();
1865 cursor_to_input();
1866 }
1867 }
1868 }
1869
1870 /*
1871 * The common way to set display_size(), also used externally.
1872 */
1873 void
window_set_display_size_normal(Window * window)1874 window_set_display_size_normal(Window *window)
1875 {
1876 window->display_size = window->bottom - window->top -
1877 menu_lines(window->menu) - SCROLL_DISPLAY_OFFSET;
1878 }
1879
1880 /*
1881 * add_to_window_list: This inserts the given window into the visible window
1882 * list (and thus adds it to the displayed windows on the screen). The
1883 * window is added by splitting the current window. If the current window is
1884 * too small, the next largest window is used. The added window is returned
1885 * as the function value or null is returned if the window couldn't be added
1886 */
1887 Window *
add_to_window_list(Window * new)1888 add_to_window_list(Window *new)
1889 {
1890 Window *biggest = NULL,
1891 *tmp;
1892
1893 incr_visible_windows();
1894 if (curr_scr_win == NULL)
1895 {
1896 screen_set_window_list(get_current_screen(), new);
1897 screen_set_window_list_end(get_current_screen(), new);
1898 if (term_basic())
1899 {
1900 /* what the hell */
1901 new->display_size = 24 - SCROLL_DISPLAY_OFFSET;
1902 set_current_window(new);
1903 return (new);
1904 }
1905 recalculate_windows();
1906 }
1907 else
1908 {
1909 /* split current window, or find a better window to split */
1910 if ((curr_scr_win->display_size < 4) ||
1911 get_int_var(ALWAYS_SPLIT_BIGGEST_VAR))
1912 {
1913 int size = 0;
1914
1915 for (tmp = screen_get_window_list(get_current_screen()); tmp;
1916 tmp = tmp->next)
1917 {
1918 if (tmp->display_size > size)
1919 {
1920 size = tmp->display_size;
1921 biggest = tmp;
1922 }
1923 }
1924 if ((biggest == NULL) || (size < 4))
1925 {
1926 say("Not enough room for another window!");
1927 /* Probably a source of memory leaks */
1928 new_free(&new);
1929 decr_visible_windows();
1930 return (NULL);
1931 }
1932 }
1933 else
1934 biggest = curr_scr_win;
1935 if ((new->prev = biggest->prev) != NULL)
1936 new->prev->next = new;
1937 else
1938 screen_set_window_list(get_current_screen(), new);
1939 new->next = biggest;
1940 biggest->prev = new;
1941 new->top = biggest->top;
1942 new->bottom = (biggest->top + biggest->bottom) / 2 -
1943 new->double_status;
1944 biggest->top = new->bottom + new->double_status + 1;
1945 new->display_size = new->bottom - new->top -
1946 SCROLL_DISPLAY_OFFSET;
1947 biggest->display_size = biggest->bottom - biggest->top -
1948 menu_lines(biggest->menu) -
1949 SCROLL_DISPLAY_OFFSET;
1950 new->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
1951 biggest->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
1952 }
1953 return (new);
1954 }
1955
1956 /*
1957 * remove_from_window_list: this removes the given window from the list of
1958 * visible windows. It closes up the hole created by the windows absense in
1959 * a nice way
1960 */
1961 static void
remove_from_window_list(Window * window)1962 remove_from_window_list(Window *window)
1963 {
1964 Window *other;
1965
1966 /* find adjacent visible window to close up the screen */
1967 for (other = window->next; other; other = other->next)
1968 {
1969 if (other->visible)
1970 {
1971 other->top = window->top;
1972 break;
1973 }
1974 }
1975 if (other == NULL)
1976 {
1977 for (other = window->prev; other; other = other->prev)
1978 {
1979 if (other->visible)
1980 {
1981 other->bottom = window->bottom + window->double_status - other->double_status;
1982 break;
1983 }
1984 }
1985 }
1986 /* remove window from window list */
1987 if (window->prev)
1988 window->prev->next = window->next;
1989 else
1990 screen_set_window_list(get_current_screen(), window->next);
1991 if (window->next)
1992 window->next->prev = window->prev;
1993 else
1994 screen_set_window_list_end(get_current_screen(), window->prev);
1995 if (window->visible)
1996 {
1997 decr_visible_windows();
1998 other->display_size = other->bottom - other->top -
1999 menu_lines(other->menu) - SCROLL_DISPLAY_OFFSET;
2000 if (window == curr_scr_win)
2001 set_current_window(NULL);
2002 if (window->refnum == get_last_window_refnum())
2003 set_last_window_refnum(curr_scr_win->refnum);
2004 }
2005 }
2006
2007 /*
2008 * window_check_servers: this checks the validity of the open servers vs the
2009 * current window list. Every open server must have at least one window
2010 * associated with it. If a window is associated with a server that's no
2011 * longer open, that window's server is set to the primary server. If an
2012 * open server has no assicatiate windows, that server is closed. If the
2013 * primary server is no more, a new primary server is picked from the open
2014 * servers
2015 */
2016 void
window_check_servers(void)2017 window_check_servers(void)
2018 {
2019 Window *tmp;
2020 Win_Trav wt;
2021 int cnt, max, i, not_connected;
2022 int alive_servers = 0;
2023 int prime = -1;
2024
2025 max = number_of_servers();
2026 for (i = 0; i < max; i++)
2027 {
2028 not_connected = !is_server_open(i);
2029 cnt = 0;
2030 wt.init = 1;
2031 while ((tmp = window_traverse(&wt)) != NULL)
2032 {
2033 if (tmp->server == i)
2034 {
2035 if (not_connected)
2036 {
2037 tmp->server = get_primary_server();
2038 if (tmp->current_channel)
2039 new_free(&tmp->current_channel);
2040 }
2041 else
2042 {
2043 prime = tmp->server;
2044 cnt++;
2045 }
2046 }
2047 }
2048 if (cnt == 0)
2049 {
2050 #ifdef NON_BLOCKING_CONNECTS
2051 if (!server_get_flag(i, CLOSE_PENDING))
2052 #endif /* NON_BLOCKING_CONNECTS */
2053 close_server(i, empty_string());
2054 }
2055 else
2056 alive_servers++;
2057 }
2058 if (!is_server_open(get_primary_server()))
2059 {
2060 wt.init = 1;
2061 while ((tmp = window_traverse(&wt)) != NULL)
2062 if (tmp->server == get_primary_server())
2063 {
2064 tmp->server = prime;
2065 }
2066 set_primary_server(prime);
2067 }
2068 set_connected_to_server(alive_servers);
2069 update_all_status();
2070 cursor_to_input();
2071 }
2072
2073 /*
2074 * restore_previous_server: Attempts to restore all windows that were
2075 * associated with `server', that currently contain nothing, to said
2076 * server.
2077 */
2078 void
window_restore_server(int server)2079 window_restore_server(int server)
2080 {
2081 Window *tmp;
2082 int max = number_of_servers(),
2083 i;
2084
2085 for (i = 0; i < max; i++)
2086 {
2087 Win_Trav wt;
2088
2089 wt.init = 1;
2090 while ((tmp = window_traverse(&wt)) != NULL)
2091 {
2092 if (tmp->server == get_primary_server() &&
2093 tmp->prev_server == server)
2094 {
2095 tmp->server = tmp->prev_server;
2096 realloc_channels(tmp);
2097 }
2098 }
2099 }
2100 }
2101
2102 /*
2103 * delete_window: This deletes the given window. It frees all data and
2104 * structures associated with the window, and it adjusts the other windows so
2105 * they will display correctly on the screen.
2106 */
2107 void
delete_window(Window * window)2108 delete_window(Window *window)
2109 {
2110 u_char *tmp = NULL;
2111
2112 if (window == NULL)
2113 return;
2114 if (window->visible && number_of_windows() == 1)
2115 {
2116 if (invisible_list)
2117 {
2118 swap_window(window, invisible_list);
2119 window = invisible_list;
2120 }
2121 else
2122 {
2123 say("You can't kill the last window!");
2124 return;
2125 }
2126 }
2127 if (window->name)
2128 malloc_strcpy(&tmp, window->name);
2129 else
2130 malloc_snprintf(&tmp, "%u", window->refnum);
2131 realloc_channels(window);
2132 new_free(&window->status_line[0]);
2133 new_free(&window->status_line[1]);
2134 new_free(&window->query_nick);
2135 new_free(&window->current_channel);
2136 new_free(&window->logfile);
2137 new_free(&window->name);
2138 new_free(&window->menu);
2139 free_display(window);
2140 free_hold_info(&window->hold_info);
2141 free_lastlog(window);
2142 free_nicks(window);
2143 if (window->visible)
2144 remove_from_window_list(window);
2145 else
2146 remove_from_invisible_list(window);
2147 new_free(&window);
2148 window_check_servers();
2149 do_hook(WINDOW_KILL_LIST, "%s", tmp);
2150 new_free(&tmp);
2151 }
2152
2153 /* delete_other_windows: zaps all visible windows except the current one */
2154 static void
delete_other_windows(void)2155 delete_other_windows(void)
2156 {
2157 Window *tmp,
2158 *cur,
2159 *next;
2160
2161 cur = curr_scr_win;
2162 tmp = screen_get_window_list(get_current_screen());
2163 while (tmp)
2164 {
2165 next = tmp->next;
2166 if (tmp != cur)
2167 {
2168 delete_window(tmp);
2169 update_all_windows();
2170 }
2171 tmp = next;
2172 }
2173 }
2174
2175 /*
2176 * window_kill_swap: Swaps with the last window that was hidden, then
2177 * kills the window that was swapped. Give the effect of replacing the
2178 * current window with the last one, and removing it at the same time.
2179 */
2180
2181 void
window_kill_swap(void)2182 window_kill_swap(void)
2183 {
2184 if (invisible_list != NULL)
2185 {
2186 swap_last_window(0, NULL);
2187 delete_window(get_window_by_refnum(get_last_window_refnum()));
2188 }
2189 else
2190 say("There are no hidden windows!");
2191 }
2192
2193 /*
2194 * unhold_windows: This is used by the main io loop to display held
2195 * information at an appropriate time. Each time this is called, each
2196 * windows hold list is checked. If there is info in the hold list and the
2197 * window is not held, the first line is displayed and removed from the hold
2198 * list. Zero is returned if no infomation is displayed
2199 */
2200 int
unhold_windows(void)2201 unhold_windows(void)
2202 {
2203 Window *tmp;
2204 Win_Trav wt;
2205 u_char *stuff;
2206 int hold_flag = 0;
2207 int logged;
2208
2209 wt.init = 1;
2210 while ((tmp = window_traverse(&wt)) != NULL)
2211 {
2212 if (!window_hold_output(tmp) && (stuff = hold_queue(tmp->hold_info)))
2213 {
2214 logged = hold_queue_logged(tmp->hold_info);
2215 if (rite(tmp, stuff, 1, 0, 0, logged) == 0)
2216 {
2217 remove_from_hold_list(tmp->hold_info);
2218 hold_flag = 1;
2219 }
2220 }
2221 }
2222 return (hold_flag);
2223 }
2224
2225 /*
2226 * update_window_status: This updates the status line for the given window.
2227 * If the refresh flag is true, the entire status line is redrawn. If not,
2228 * only some of the changed portions are redrawn
2229 */
2230 void
update_window_status(Window * window,int refreshit)2231 update_window_status(Window *window, int refreshit)
2232 {
2233 if (term_basic() || (!window->visible) || !status_update_flag || never_connected())
2234 return;
2235 if (window == NULL)
2236 window = curr_scr_win;
2237 if (refreshit)
2238 {
2239 new_free(&window->status_line[0]);
2240 new_free(&window->status_line[1]);
2241 }
2242 make_status(window);
2243 }
2244
2245 /*
2246 * redraw_all_status: This redraws all of the status lines for all of the
2247 * windows.
2248 */
2249 void
redraw_all_status(void)2250 redraw_all_status(void)
2251 {
2252 Window *tmp;
2253
2254 if (term_basic())
2255 return;
2256 for (tmp = screen_get_window_list(get_current_screen()); tmp; tmp = tmp->next)
2257 {
2258 new_free(&tmp->status_line[0]);
2259 new_free(&tmp->status_line[1]);
2260 make_status(tmp);
2261 }
2262 update_input(UPDATE_JUST_CURSOR);
2263 term_flush();
2264 }
2265
2266 /*
2267 * update_all_status: This updates all of the status lines for all of the
2268 * windows. By updating, it only draws from changed portions of the status
2269 * line to the right edge of the screen
2270 */
2271 void
update_all_status(void)2272 update_all_status(void)
2273 {
2274 Window *window;
2275 Screen *screen;
2276
2277 if (term_basic() || !status_update_flag || never_connected())
2278 return;
2279 for (screen = screen_first(); screen; screen = screen_get_next(screen))
2280 {
2281 if (!screen_get_alive(screen))
2282 continue;
2283 for (window = screen_get_window_list(screen);window; window = window->next)
2284 if (window->visible)
2285 make_status(window);
2286 }
2287 update_input(UPDATE_JUST_CURSOR);
2288 term_flush();
2289 }
2290
2291 /*
2292 * status_update: sets the status_update_flag to whatever flag is. This also
2293 * calls update_all_status(), which will update the status line if the flag
2294 * was true, otherwise it's just ignored
2295 */
2296 void
status_update(int flag)2297 status_update(int flag)
2298 {
2299 status_update_flag = flag;
2300 update_all_status();
2301 cursor_to_input();
2302 }
2303
2304 void
redraw_resized(Window * window,int bottom)2305 redraw_resized(Window *window, int bottom)
2306 {
2307 if (bottom < 0)
2308 term_scroll(window->top + window_menu_lines(window) + bottom,
2309 window->top + window_menu_lines(window) +
2310 window->display_size - 1,
2311 bottom);
2312 else if (bottom)
2313 term_scroll(window->top + window_menu_lines(window),
2314 window->top + window_menu_lines(window) +
2315 window->display_size -1, bottom);
2316 }
2317
2318 /*
2319 * resize_display: After determining that the screen has changed sizes, this
2320 * resizes all the internal stuff. If the screen grew, this will add extra
2321 * empty display entries to the end of the display list. If the screen
2322 * shrank, this will remove entries from the end of the display list. By
2323 * doing this, we try to maintain as much of the display as possible.
2324 *
2325 * This has now been improved so that it returns enough information for
2326 * redraw_resized to redisplay the contents of the window without having
2327 * to redraw too much.
2328 */
2329 int
resize_display(Window * window)2330 resize_display(Window *window)
2331 {
2332 int cnt,
2333 i;
2334 Display *tmp, *pre_ip;
2335 int Wrapped = 0;
2336 int bottom;
2337
2338 bottom = 0;
2339 if (term_basic())
2340 {
2341 return bottom;
2342 }
2343 if (!window->top_of_display)
2344 {
2345 window->top_of_display = new_malloc(sizeof(Display));
2346 window->top_of_display->line = NULL;
2347 window->top_of_display->linetype = 0;
2348 window->top_of_display->next = window->top_of_display;
2349 window->display_ip = window->top_of_display;
2350 window->old_size = 1;
2351 }
2352 /* cnt = size - window->display_size; */
2353 cnt = window->display_size - window->old_size;
2354 if (cnt > 0)
2355 {
2356 Display *new = NULL;
2357
2358 /*
2359 * screen got bigger: got to last display entry and link
2360 * in new entries
2361 */
2362 for (tmp = window->top_of_display, i = 0;
2363 i < (window->old_size - 1);
2364 i++, tmp = tmp->next);
2365 for (i = 0; i < cnt; i++)
2366 {
2367 new = new_malloc(sizeof *new);
2368 new->line = NULL;
2369 new->linetype = 0;
2370 new->next = tmp->next;
2371 tmp->next = new;
2372 }
2373 if (window->display_ip == window->top_of_display &&
2374 window->top_of_display->line)
2375 window->display_ip = new;
2376 bottom = cnt;
2377 }
2378 else if (cnt < 0)
2379
2380 {
2381 Display *ptr;
2382 int top = 0;
2383
2384 /*
2385 * screen shrank: find last display entry we want to keep,
2386 * and remove all after that point
2387 */
2388 cnt = -cnt;
2389 for (pre_ip = window->top_of_display;
2390 pre_ip->next != window->display_ip;
2391 pre_ip = pre_ip->next);
2392 for (tmp = pre_ip->next, i = 0; i < cnt; i++, tmp = ptr)
2393 {
2394 ptr = tmp->next;
2395 if (tmp == window->top_of_display)
2396
2397 {
2398 if (tmp->line)
2399 Wrapped = 1;
2400 window->top_of_display = ptr;
2401 }
2402 if (Wrapped)
2403 top--;
2404 else
2405 bottom--;
2406 new_free(&(tmp->line));
2407 new_free(&tmp);
2408 }
2409 window->display_ip = pre_ip->next = tmp;
2410 window->cursor += top;
2411 if (!window->scroll)
2412 {
2413 if (window->cursor == window->display_size)
2414 window->cursor = 0;
2415 new_free(&window->display_ip->line);
2416 }
2417 }
2418 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
2419 window->old_size = window->display_size;
2420 return bottom;
2421 }
2422
2423 /*
2424 * helper for recalculate_windows(): set the sizes for one window.
2425 */
2426 static void
window_set_one_size(Window * window,int size,int top)2427 window_set_one_size(Window *window, int size, int top)
2428 {
2429 window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
2430 window->display_size = size - window_menu_lines(window)
2431 - window->double_status - SCROLL_DISPLAY_OFFSET;
2432 if (window->display_size <= 0)
2433 window->display_size = 1;
2434 window->top = top;
2435 window->bottom = top + size - window->double_status;
2436
2437 Debug(DB_WINDOW, "size %d top %d set refnum %d display_size %d bottom %d",
2438 size, top, window->refnum, window->display_size, window->bottom);
2439 return;
2440 }
2441
2442 /*
2443 * helper for recalculate_windows(): hide one window
2444 */
2445 static void
hide_window_recalc(Window * window)2446 hide_window_recalc(Window *window)
2447 {
2448 remove_from_window_list(window);
2449 add_to_invisible_list(window);
2450 window->display_size = get_li() - 2 - SCROLL_DISPLAY_OFFSET;
2451 if (window == curr_scr_win)
2452 set_current_window(NULL);
2453 }
2454
2455 /*
2456 * recalculate_windows: this is called when the terminal size changes (as
2457 * when an xterm window size is changed). It recalculates the sized and
2458 * positions of all the windows.
2459 *
2460 * XXX currently still buggy.
2461 */
2462 void
recalculate_windows(void)2463 recalculate_windows(void)
2464 {
2465 Window *window, *last_window, *next_window;
2466 int total_size = 0, total_menu_size = 0, total_status_size = 0;
2467 int win_count = 0;
2468 int lines, old_lines;
2469 int top, extra = 0;
2470 int recalc_failed = 0;
2471 double change;
2472
2473 if (term_basic() || number_of_windows() == 0)
2474 return;
2475
2476 /*
2477 * Calculate the totals we have right now.
2478 */
2479 for (window = screen_get_window_list(get_current_screen());
2480 window; window = window_get_next(window))
2481 {
2482 total_status_size += window->double_status - SCROLL_DISPLAY_OFFSET;
2483 total_size += window->display_size;
2484 total_menu_size += window_menu_lines(window);
2485 win_count++;
2486 }
2487 Debug(DB_WINDOW, "old total size %d menu lines %d wincount %d",
2488 total_size, total_menu_size, win_count);
2489
2490 old_lines = screen_get_old_li() - 2;
2491 lines = get_li() - 2;
2492
2493 if (win_count == 1)
2494 {
2495 window = screen_get_window_list(get_current_screen());
2496 window_set_one_size(window, lines, 0);
2497 return;
2498 }
2499
2500 /*
2501 * Check everything still fits. If not, hide windows until they do.
2502 */
2503 if (total_status_size + win_count > lines) {
2504 for (window = screen_get_window_list(get_current_screen());
2505 window; window = next_window)
2506 {
2507 next_window = window_get_next(window);
2508
2509 Debug(DB_WINDOW, "hiding window %d", window->refnum);
2510 total_status_size -= window->double_status - SCROLL_DISPLAY_OFFSET;
2511 win_count--;
2512
2513 hide_window_recalc(window);
2514
2515 if (total_status_size + win_count <= lines)
2516 break;
2517 }
2518 /* Now we've hidden a bunch, re-balance the rest */
2519 balance_windows();
2520 return;
2521 }
2522
2523 change = lines;
2524 change /= old_lines;
2525
2526 Debug(DB_WINDOW, "change %lf (old %d / new %d)", change, old_lines, lines);
2527
2528 for (top = 0, window = screen_get_window_list(get_current_screen());
2529 window;
2530 last_window = window, window = next_window)
2531 {
2532 int new_size;
2533 double adjsize; /* could use fixed-point */
2534
2535 next_window = window_get_next(window);
2536
2537 adjsize = window->display_size;
2538 adjsize *= change;
2539 new_size = (int)adjsize;
2540 if (new_size == 0)
2541 new_size = 1;
2542
2543 if (lines - (top + new_size) < 0)
2544 {
2545 Debug(DB_WINDOW, "hiding window %d", window->refnum);
2546 hide_window_recalc(window);
2547 recalc_failed = 1;
2548 win_count--;
2549 continue;
2550 }
2551
2552 Debug(DB_WINDOW, "refnum %d new display size %d (old %d)",
2553 window->refnum, new_size, window->display_size);
2554
2555 /*
2556 * calculate the extra lines when we're at the last window.
2557 */
2558 if (--win_count == 0 && (top + new_size != lines))
2559 {
2560 extra = lines - (top + new_size);
2561 Debug(DB_WINDOW, "top[%d] + new_size[%d] != lines[%d], "
2562 "saving extra = %d",
2563 top, new_size, lines, extra);
2564 }
2565
2566 window_set_one_size(window, new_size, top);
2567 top += new_size + 1;
2568 }
2569
2570 /*
2571 * If we failed while recalculating, fall back to balance.
2572 */
2573 if (recalc_failed)
2574 {
2575 balance_windows();
2576 return;
2577 }
2578
2579 if (!extra)
2580 return;
2581
2582 /* if extra is negative, we've really gone wrong .. */
2583 if (extra < 0)
2584 abort();
2585
2586 /*
2587 * if we had extra, we distribute it out to the windows from the
2588 * bottom up, adjusting them as we go.
2589 */
2590 for (window = last_window; extra; extra--, window = window_get_prev(window))
2591 {
2592 if (window == NULL)
2593 window = last_window;
2594 window->display_size++;
2595 window->top += extra - 1;
2596 window->bottom += extra;
2597 Debug(DB_WINDOW, "refnum %d now top = %d bottom = %d display_size = %d",
2598 window->refnum, window->top, window->bottom, window->display_size);
2599 }
2600 }
2601
2602 /*
2603 * balance_windows: back end for /window balance. window sizes are
2604 * spread as evenly as possible.
2605 */
2606 void
balance_windows(void)2607 balance_windows(void)
2608 {
2609 int base_size,
2610 size,
2611 top,
2612 extra;
2613 Window *tmp;
2614
2615 if (term_basic() || number_of_windows() == 0)
2616 return;
2617
2618 base_size = ((get_li() - 1) / number_of_windows()) - 1;
2619 extra = (get_li() - 1) - ((base_size + 1) * number_of_windows());
2620 top = 0;
2621 for (tmp = screen_get_window_list(get_current_screen()); tmp; tmp = window_get_next(tmp))
2622 {
2623 tmp->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
2624 if (extra)
2625 {
2626 extra--;
2627 size = base_size + 1;
2628 }
2629 else
2630 size = base_size;
2631 tmp->display_size = size - window_menu_lines(tmp)
2632 - tmp->double_status - SCROLL_DISPLAY_OFFSET;
2633 if (tmp->display_size <= 0)
2634 tmp->display_size = 1;
2635 tmp->top = top;
2636 tmp->bottom = top + size - tmp->double_status;
2637 top += size + 1;
2638 }
2639 }
2640
2641 /*
2642 * clear_window: This clears the display list for the given window, or
2643 * current window if null is given.
2644 */
2645 void
clear_window(Window * window)2646 clear_window(Window *window)
2647 {
2648 int i,
2649 cnt;
2650
2651 if (term_basic())
2652 return;
2653 if (window == NULL)
2654 window = curr_scr_win;
2655 erase_display(window);
2656 term_move_cursor(0, window->top + window_menu_lines(window));
2657 cnt = window->bottom - window->top - window_menu_lines(window);
2658 for (i = 0; i < cnt; i++)
2659 {
2660 if (term_clear_to_eol())
2661 term_space_erase(0);
2662 term_newline();
2663 }
2664 term_flush();
2665 }
2666
2667 /* clear_all_windows: This clears all *visible* windows */
2668 void
clear_all_windows(int unhold)2669 clear_all_windows(int unhold)
2670 {
2671 Window *tmp;
2672
2673 for (tmp = screen_get_window_list(get_current_screen()); tmp; tmp = window_get_next(tmp))
2674 {
2675 if (unhold)
2676 window_hold_mode(tmp, OFF, 1);
2677 clear_window(tmp);
2678 }
2679 }
2680
2681 /*
2682 * redraw_window: This redraws the display list for the given window. Some
2683 * special considerations are made if you are just redrawing one window as
2684 * opposed to using this routine to redraw the whole screen one window at a
2685 * time
2686 *
2687 * A negative value in just_one indicates not all of the window needs to
2688 * be redrawn.
2689 */
2690 static void
redraw_window(Window * window,int just_one,int backscroll)2691 redraw_window(Window *window, int just_one, int backscroll)
2692 {
2693 Display *tmp;
2694 int i;
2695 int StartPoint;
2696 int yScr;
2697
2698 if (term_basic() || !window->visible)
2699 return;
2700 window = window ? window : curr_scr_win;
2701 if (just_one < 0)
2702 {
2703 /* This part of the window is scrolling into view */
2704 StartPoint = -just_one;
2705 just_one = 0;
2706 }
2707 else
2708 {
2709 StartPoint = 0;
2710 if (window->scrolled_lines)
2711 display_lastlog_lines(window->scrolled_lines - window->display_size,
2712 window->scrolled_lines, window);
2713 }
2714 if (menu_active(window_get_menu(window)))
2715 show_menu_by_window(window, just_one ? SMF_ERASE : 0);
2716 if (window->scrolled_lines + StartPoint < window->display_size)
2717 yScr = window->scrolled_lines + StartPoint;
2718 else
2719 yScr = 0;
2720 term_move_cursor(0, window->top+window_menu_lines(window)+yScr);
2721 /*
2722 * if (term_clear_to_eol())
2723 * { term_space_erase(0); term_cr(); }
2724 */
2725 for (tmp = window->top_of_display, i = 0; i < window->display_size-window->scrolled_lines; i++, tmp = tmp->next)
2726 {
2727 if (i < StartPoint)
2728 continue;
2729 if (tmp->line)
2730 rite(window, tmp->line, 1, 1, backscroll, 0);
2731 else
2732 {
2733 if (just_one)
2734 {
2735 if (term_clear_to_eol())
2736 term_space_erase(0);
2737 }
2738 term_newline();
2739 }
2740 }
2741 term_flush();
2742 }
2743
2744 /*
2745 * recalculate_window_positions: This runs through the window list and
2746 * re-adjusts the top and bottom fields of the windows according to their
2747 * current positions in the window list. This doesn't change any sizes of
2748 * the windows
2749 */
2750 void
recalculate_window_positions(void)2751 recalculate_window_positions(void)
2752 {
2753 Window *tmp;
2754 int top;
2755
2756 top = 0;
2757 for (tmp = screen_get_window_list(get_current_screen()); tmp; tmp = window_get_next(tmp))
2758 {
2759 tmp->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS;
2760 tmp->top = top;
2761 tmp->bottom = top + tmp->display_size + window_menu_lines(tmp);
2762 top += tmp->display_size + window_menu_lines(tmp) + 1 +
2763 tmp->double_status;
2764 }
2765 }
2766
2767 /*
2768 * redraw_all_windows: This basically clears and redraws the entire display
2769 * portion of the screen. All windows and status lines are draws. This does
2770 * nothing for the input line of the screen. Only visible windows are drawn
2771 */
2772 void
redraw_all_windows(void)2773 redraw_all_windows(void)
2774 {
2775 Window *tmp;
2776
2777 if (term_basic())
2778 return;
2779 for (tmp = screen_get_window_list(get_current_screen()); tmp; tmp = window_get_next(tmp))
2780 tmp->update |= REDRAW_STATUS | REDRAW_DISPLAY_FAST;
2781 }
2782
2783 /*
2784 * is_current_channel: Returns true is channel is a current channel for any
2785 * window. If the delete_window is not 0, then unset channel as the current
2786 * channel and attempt to replace it by a non-current channel or the
2787 * current_channel of window specified by value of delete
2788 */
2789 int
is_current_channel(u_char * channel,int server,int delete)2790 is_current_channel(u_char *channel, int server, int delete)
2791 {
2792 Window *tmp,
2793 *found_window = NULL;
2794 Win_Trav wt;
2795 int found = 0;
2796
2797 wt.init = 1;
2798 while ((tmp = window_traverse(&wt)) != NULL)
2799 {
2800 u_char *c = tmp->current_channel;
2801
2802 if (c && !my_stricmp(channel, c) && tmp->server == server)
2803 {
2804 found_window = tmp;
2805 found = 1;
2806 if (delete)
2807 {
2808 new_free(&tmp->current_channel);
2809 tmp->update |= UPDATE_STATUS;
2810 }
2811 }
2812 }
2813 if (found && delete)
2814 found = channel_is_on_window(channel, server, found_window, delete);
2815
2816 return found;
2817 }
2818
2819 Window *
is_bound(u_char * channel,int server)2820 is_bound(u_char *channel, int server)
2821 {
2822 Win_Trav wt;
2823 Window *tmp;
2824
2825 wt.init = 1;
2826 while ((tmp = window_traverse(&wt)))
2827 {
2828 if (tmp->server == server && tmp->bound_channel &&
2829 !my_stricmp(channel, tmp->bound_channel))
2830 return tmp;
2831 }
2832
2833 return NULL;
2834 }
2835
2836 static void
bind_channel(u_char * channel,Window * window)2837 bind_channel(u_char *channel, Window *window)
2838 {
2839 Win_Trav wt;
2840 Window *tmp;
2841
2842 /* check it isn't bound on this server elsewhere */
2843 wt.init = 1;
2844 while ((tmp = window_traverse(&wt)))
2845 {
2846 if (tmp->server != window->server && tmp == window)
2847 continue;
2848 if (!my_stricmp(tmp->bound_channel, channel) && tmp != window)
2849 {
2850 say("Channel %s is already bound to window %d", channel, tmp->refnum);
2851 return;
2852 }
2853 }
2854 if (is_on_channel(channel, window->server, server_get_nickname(window->server)))
2855 {
2856 is_current_channel(channel, window->server, (int)window->refnum);
2857 set_channel_by_refnum(0, channel);
2858 }
2859 /* XXX fix this */
2860 #if 0
2861 else
2862 {
2863 int server, sg = -1, fsg = -2; /* different */
2864 u_char *group;
2865
2866 server = set_from_server(window->server);
2867
2868 group = server_get_server_group(server);
2869 if (group)
2870 sg = find_server_group(group, 0);
2871
2872 if (sg == 0 || fsg == 0)
2873 yell("--- huh. coudn't find server groups");
2874
2875 if (sg == fsg)
2876 {
2877 switch (server_get_version(window->server)) {
2878 case ServerICB:
2879 icb_put_group(channel);
2880 break;
2881 default:
2882 send_to_server("JOIN %s", channel);
2883 }
2884 add_channel(channel, 0, get_from_server(), CHAN_JOINING, NULL);
2885 }
2886 set_from_server(server);
2887 }
2888 #endif
2889 malloc_strcpy(&window->bound_channel, channel);
2890 say("Channel %s bound to window %d", channel, window->refnum);
2891 }
2892
2893 static void
unbind_channel(u_char * channel,Window * window)2894 unbind_channel(u_char *channel, Window *window)
2895 {
2896
2897 window = is_bound(channel, window->server);
2898 if (!window)
2899 return;
2900 new_free(&window->bound_channel);
2901 }
2902
2903 /*
2904 * get_window_server: returns the server index for the window with the given
2905 * refnum
2906 */
2907 int
get_window_server(unsigned refnum)2908 get_window_server(unsigned refnum)
2909 {
2910 Window *tmp;
2911
2912 if ((tmp = get_window_by_refnum(refnum)) == NULL)
2913 tmp = curr_scr_win;
2914 return (tmp->server);
2915 }
2916
2917 /*
2918 * window_set_server: This sets the server of the given window to server.
2919 * If refnum is -1 then we are setting the primary server and all windows
2920 * that are set to the current primary server are changed to server. The misc
2921 * flag is ignored in this case. If refnum is not -1, then that window is
2922 * set to the given server. If WIN_ALL is set in misc, then all windows
2923 * with the same server as refnum are set to the new server as well.
2924 * If the window is in a group, all the group is set to the new server.
2925 * WIN_TRANSFER will move the channels to the new server, WIN_FORCE will
2926 * force a 'sticky' behaviour of the window. -Sol
2927 */
2928 void
window_set_server(int refnum,int server,int misc)2929 window_set_server(int refnum, int server, int misc)
2930 {
2931 int old_serv = -2; // -2 for unset
2932 Window *window = 0, *ptr, *new_win = NULL;
2933 int moved = 0;
2934 Win_Trav wt;
2935
2936 if (refnum == -1)
2937 {
2938 old_serv = get_primary_server();
2939 set_primary_server(server);
2940 misc |= WIN_ALL;
2941 }
2942 else
2943 {
2944 window = get_window_by_refnum((u_int)refnum);
2945 if (window)
2946 {
2947 old_serv = window->server;
2948 }
2949 }
2950
2951 if (server == old_serv)
2952 return;
2953
2954 /* Moving all windows associated with old_serv -Sol */
2955 if (misc & WIN_ALL)
2956 {
2957 if ((misc & WIN_TRANSFER) && (old_serv >= 0))
2958 {
2959 moved = channels_move_server_simple(old_serv, server);
2960
2961 #ifdef NON_BLOCKING_CONNECTS
2962 if (server_get_flag(old_serv, CLOSE_PENDING))
2963 server_set_flag(old_serv, CLEAR_PENDING, 1);
2964 else
2965 #endif /* NON_BLOCKING_CONNECTS */
2966 clear_channel_list(old_serv);
2967 }
2968 wt.init = 1;
2969 while ((ptr = window_traverse(&wt)) != NULL)
2970 if (ptr->server == old_serv)
2971 {
2972 ptr->server = server;
2973 /*
2974 * XXX we could save this to old_current_channel and use
2975 * that after other checks to decide where a channel should
2976 * go, maybe??
2977 */
2978 if (ptr->current_channel)
2979 new_free(&ptr->current_channel);
2980 }
2981 window_check_servers();
2982 return;
2983 }
2984
2985 /*
2986 * We are setting only some windows of the old server : let's look
2987 * for a window of that server that is not being moved.
2988 * refnum == -1 has been dealt with above so window is defined. -Sol
2989 */
2990
2991 wt.init = 1;
2992 while ((ptr = window_traverse(&wt)) != NULL)
2993 if (ptr != window &&
2994 (!ptr->server_group || (ptr->server_group != window->server_group)) &&
2995 ptr->server == old_serv)
2996 {
2997 /* Possible relocation -Sol */
2998 new_win = ptr;
2999
3000 /* Immediately retain window if no group -Sol */
3001 if (!ptr->server_group)
3002 break;
3003 }
3004
3005 /* No relocation : we're closing last windows for old_serv -Sol */
3006 if (!new_win)
3007 {
3008 window_set_server(refnum, server, misc | WIN_ALL);
3009 return;
3010 }
3011
3012 /*
3013 * Now that we know that server still has at least one window open,
3014 * move what we're supposed to -Sol
3015 */
3016
3017 if ((misc & WIN_TRANSFER) && (old_serv >= 0) && server_get_version(old_serv) != ServerICB)
3018 channels_move_server_complex(window, new_win, old_serv, server, misc, moved);
3019
3020 wt.init = 1;
3021 while ((ptr = window_traverse(&wt)) != NULL)
3022 if ((ptr == window) || (ptr->server_group && (ptr->server_group == window->server_group)))
3023 {
3024 ptr->server = server;
3025 if (ptr->current_channel)
3026 new_free(&ptr->current_channel);
3027 }
3028 window_check_servers();
3029 }
3030
3031 /*
3032 * set_channel_by_refnum: This sets the current channel for the current
3033 * window. It returns the current channel as its value. If channel is null,
3034 * the * current channel is not changed, but simply reported by the function
3035 * result. This treats as a special case setting the current channel to
3036 * channel "0". This frees the current_channel for the
3037 * get_current_screen()->current_window, * setting it to null
3038 */
3039 u_char *
set_channel_by_refnum(unsigned refnum,u_char * channel)3040 set_channel_by_refnum(unsigned refnum, u_char *channel)
3041 {
3042 Window *tmp;
3043 Window *tmp2;
3044 Win_Trav wt;
3045
3046 if ((tmp = get_window_by_refnum(refnum)) == NULL)
3047 tmp = curr_scr_win;
3048 if (channel && my_strcmp(channel, zero()) == 0)
3049 channel = NULL;
3050
3051 wt.init = 1;
3052 while ((tmp2 = window_traverse(&wt)))
3053 if (tmp2->server == tmp->server && my_stricmp(tmp2->current_channel, channel) == 0)
3054 new_free(&tmp2->current_channel);
3055
3056 malloc_strcpy(&tmp->current_channel, channel);
3057 tmp->update |= UPDATE_STATUS;
3058 set_channel_window(tmp, channel, tmp->server);
3059 return (channel);
3060 }
3061
3062 /* get_channel_by_refnum: returns the current channel for window refnum */
3063 u_char *
get_channel_by_refnum(u_int refnum)3064 get_channel_by_refnum(u_int refnum)
3065 {
3066 Window *tmp;
3067
3068 if ((tmp = get_window_by_refnum(refnum)) == NULL)
3069 tmp = curr_scr_win;
3070 return (tmp->current_channel);
3071 }
3072
3073 /* current_refnum: returns the reference number for the current window */
3074 unsigned int
current_refnum(void)3075 current_refnum(void)
3076 {
3077 return (curr_scr_win->refnum);
3078 }
3079
3080 /* query_nick: Returns the query nick for the current channel */
3081 u_char *
query_nick(void)3082 query_nick(void)
3083 {
3084 return (curr_scr_win->query_nick);
3085 }
3086
3087 /* get_prompt_by_refnum: returns the prompt for the given window refnum */
3088 u_char *
get_prompt_by_refnum(u_int refnum)3089 get_prompt_by_refnum(u_int refnum)
3090 {
3091 Window *tmp;
3092
3093 if ((tmp = get_window_by_refnum(refnum)) == NULL)
3094 tmp = curr_scr_win;
3095 if (tmp->prompt)
3096 return (tmp->prompt);
3097 else
3098 return (empty_string());
3099 }
3100
3101 /*
3102 * get_target_by_refnum: returns the target for the window with the given
3103 * refnum (or for the current window). The target is either the query nick
3104 * or current channel for the window
3105 */
3106 u_char *
get_target_by_refnum(u_int refnum)3107 get_target_by_refnum(u_int refnum)
3108 {
3109 Window *tmp;
3110
3111 if ((tmp = get_window_by_refnum(refnum)) == NULL)
3112 tmp = curr_scr_win;
3113 if (tmp->query_nick)
3114 return tmp->query_nick;
3115 else if (tmp->current_channel)
3116 return tmp->current_channel;
3117 else
3118 return NULL;
3119 }
3120
3121 /* set_query_nick: sets the query nick for the current channel to nick */
3122 void
set_query_nick(u_char * nick)3123 set_query_nick(u_char *nick)
3124 {
3125 if (curr_scr_win->query_nick)
3126 {
3127 new_free(&curr_scr_win->query_nick);
3128 curr_scr_win->update |= UPDATE_STATUS;
3129 }
3130
3131 if (nick)
3132 {
3133 malloc_strcpy(&curr_scr_win->query_nick, nick);
3134 curr_scr_win->update |= UPDATE_STATUS;
3135 }
3136 update_window_status(curr_scr_win, 0);
3137 }
3138
3139 /*
3140 * irc_goto_window: This will switch the current window to the window numbered
3141 * "which", where which is 0 through the number of visible windows on the
3142 * screen. The which has nothing to do with the windows refnum.
3143 */
3144 static void
irc_goto_window(int which)3145 irc_goto_window(int which)
3146 {
3147 Window *tmp;
3148 int i;
3149
3150
3151 if (which == 0)
3152 return;
3153 if ((which < 0) || (which > number_of_windows()))
3154 {
3155 say("GOTO: Illegal value");
3156 return;
3157 }
3158 tmp = screen_get_window_list(get_current_screen());
3159 for (i = 1; tmp && (i != which); tmp = tmp->next, i++)
3160 ;
3161 set_current_window(tmp);
3162 }
3163
3164 /*
3165 * hide_window: sets the given window to invisible and recalculates remaing
3166 * windows to fill the entire screen
3167 */
3168 static void
hide_window(Window * window)3169 hide_window(Window *window)
3170 {
3171 if (number_of_windows() == 1)
3172 {
3173 say("You can't hide the last window.");
3174 return;
3175 }
3176 if (window->visible)
3177 {
3178 remove_from_window_list(window);
3179 add_to_invisible_list(window);
3180 window->display_size = get_li() - 2 - SCROLL_DISPLAY_OFFSET;
3181 set_current_window(NULL);
3182 }
3183 }
3184
3185 /* hide_other_windows: makes all visible windows but the current one hidden */
3186 static void
hide_other_windows(void)3187 hide_other_windows(void)
3188 {
3189 Window *tmp,
3190 *cur,
3191 *next;
3192
3193 cur = curr_scr_win;
3194 tmp = screen_get_window_list(get_current_screen());
3195 while (tmp)
3196 {
3197 next = tmp->next;
3198 if (tmp != cur)
3199 hide_window(tmp);
3200 tmp = next;
3201 }
3202 }
3203
3204 #define WIN_FORM "%%-4s %%-%u.%us %%-%u.%us %%-%u.%us %%-9.9s %%-10.10s %%s%%s"
3205 #define WIN_FORM_HOOK "%d %s %s %s %s %s %s %s %s"
3206
3207 static void
list_a_window(Window * window,int len,int clen)3208 list_a_window(Window *window, int len, int clen)
3209 {
3210 u_char tmp[10];
3211
3212 snprintf(CP(tmp), sizeof tmp, "%-4u", window->refnum);
3213 if (do_hook(WINDOW_LIST_LIST, WIN_FORM_HOOK,
3214 len,
3215 tmp,
3216 window->server ?
3217 server_get_nickname(window->server) : (u_char *) "<None>",
3218 window->name ?
3219 window->name : (u_char *) "<None>",
3220 window->current_channel ?
3221 window->current_channel : (u_char *) "<None>",
3222 window->query_nick ?
3223 window->query_nick : (u_char *) "<None>",
3224 window->server != -1 ?
3225 server_get_itsname(window->server) : (u_char *) "<None>",
3226 bits_to_lastlog_level(window->window_level),
3227 (window->visible) ?
3228 "" : " Hidden"))
3229 {
3230 const unsigned old_nick_len = 9;
3231 u_char *buffer = NULL;
3232
3233 malloc_snprintf(&buffer, WIN_FORM, old_nick_len,
3234 old_nick_len, len, len, clen, clen);
3235 say(CP(buffer), tmp,
3236 window->server ?
3237 server_get_nickname(window->server) : (u_char *) "<None>",
3238 window->name ?
3239 window->name : (u_char *) "<None>",
3240 window->current_channel ?
3241 window->current_channel : (u_char *) "<None>",
3242 window->query_nick ?
3243 window->query_nick : (u_char *) "<None>",
3244 window->server != -1 ?
3245 server_get_itsname(window->server) : (u_char *) "<None>",
3246 bits_to_lastlog_level(window->window_level),
3247 (window->visible) ?
3248 "" : " Hidden");
3249 new_free(&buffer);
3250 }
3251 }
3252
3253 /*
3254 * list_windows: This Gives a terse list of all the windows, visible or not,
3255 * by displaying their refnums, current channel, and current nick
3256 */
3257 static void
list_windows(void)3258 list_windows(void)
3259 {
3260 Window *tmp;
3261 Win_Trav wt;
3262 int len = 4;
3263 int clen = get_int_var(CHANNEL_NAME_WIDTH_VAR);
3264 int check_clen = clen == 0;
3265
3266 wt.init = 1;
3267 while ((tmp = window_traverse(&wt)) != NULL)
3268 {
3269 if (tmp->name && ((int) my_strlen(tmp->name) > len))
3270 len = my_strlen(tmp->name);
3271 if (check_clen == 0)
3272 continue;
3273 if (tmp->current_channel &&
3274 ((int) my_strlen(tmp->current_channel) > clen))
3275 clen = my_strlen(tmp->current_channel);
3276 }
3277 if (do_hook(WINDOW_LIST_LIST, WIN_FORM_HOOK, len,
3278 "Ref", "Nick", "Name", "Channel", "Query",
3279 "Server", "Level", empty_string()))
3280 {
3281 const unsigned old_nick_len = 9;
3282 u_char *buffer = NULL;
3283
3284 malloc_snprintf(&buffer, WIN_FORM, old_nick_len,
3285 old_nick_len, len, len, clen, clen);
3286 say(CP(buffer),
3287 "Ref", "Nick", "Name", "Channel", "Query",
3288 "Server", "Level", empty_string());
3289 new_free(&buffer);
3290 }
3291 wt.init = 1;
3292 while ((tmp = window_traverse(&wt)) != NULL)
3293 list_a_window(tmp, len, clen);
3294 }
3295
3296 /* show_window: This makes the given window visible. */
3297 static void
show_window(Window * window)3298 show_window(Window *window)
3299 {
3300 if (window->visible)
3301 {
3302 set_current_window(window);
3303 return;
3304 }
3305 remove_from_invisible_list(window);
3306 if (add_to_window_list(window))
3307 set_current_window(window);
3308 else
3309 add_to_invisible_list(window);
3310 }
3311
3312 /* push_window_by_refnum: This pushes the given refnum onto the window stack */
3313 static void
push_window_by_refnum(u_int refnum)3314 push_window_by_refnum(u_int refnum)
3315 {
3316 WindowStack *new;
3317
3318 new = new_malloc(sizeof *new);
3319 new->refnum = refnum;
3320 new->next = get_window_stack();
3321 set_window_stack(new);
3322 }
3323
3324 /*
3325 * pop_window: this pops the top entry off the window stack and sets the
3326 * current window to that window. If the top of the window stack is no
3327 * longer a valid window, then that entry is discarded and the next entry
3328 * down is tried (as so on). If the stack is empty, the current window is
3329 * left unchanged
3330 */
3331 static void
pop_window(void)3332 pop_window(void)
3333 {
3334 int refnum;
3335 WindowStack *tmp;
3336 Window *win;
3337
3338 while (1)
3339 {
3340 WindowStack *window_stack = get_window_stack();
3341
3342 if (window_stack)
3343 {
3344 refnum = window_stack->refnum;
3345 tmp = window_stack->next;
3346 new_free(&window_stack);
3347 set_window_stack(tmp);
3348 if ((win = get_window_by_refnum((u_int)refnum)) != NULL)
3349 {
3350 if (!win->visible)
3351 show_window(win);
3352 else
3353 set_current_window(win);
3354 break;
3355 }
3356 }
3357 else
3358 {
3359 say("The window stack is empty!");
3360 break;
3361 }
3362 }
3363 }
3364
3365 /*
3366 * show_stack: displays the current window stack. This also purges out of
3367 * the stack any window refnums that are no longer valid
3368 */
3369 static void
show_stack(void)3370 show_stack(void)
3371 {
3372 WindowStack *last = NULL,
3373 *tmp, *crap;
3374 Window *win;
3375 Win_Trav wt;
3376 int len = 4;
3377 int clen = get_int_var(CHANNEL_NAME_WIDTH_VAR);
3378 int check_clen = clen == 0;
3379
3380 wt.init = 1;
3381 while ((win = window_traverse(&wt)) != NULL)
3382 {
3383 if (win->name && ((int) my_strlen(win->name) > len))
3384 len = my_strlen(win->name);
3385 if (check_clen == 0)
3386 continue;
3387 if (win->current_channel && ((int) my_strlen(win->current_channel) > clen))
3388 clen = my_strlen(win->current_channel);
3389 }
3390 say("Window stack:");
3391 tmp = get_window_stack();
3392 while (tmp)
3393 {
3394 if ((win = get_window_by_refnum(tmp->refnum)) != NULL)
3395 {
3396 list_a_window(win, len, clen);
3397 tmp = tmp->next;
3398 }
3399 else
3400 {
3401 crap = tmp->next;
3402 new_free(&tmp);
3403 if (last)
3404 last->next = crap;
3405 else
3406 set_window_stack(crap);
3407 tmp = crap;
3408 }
3409 }
3410 }
3411
3412 /*
3413 * create_refnum: this generates a reference number for a new window that is
3414 * not currently is use by another window. A refnum of 0 is reserved (and
3415 * never returned by this routine). Using a refnum of 0 in the message_to()
3416 * routine means no particular window (stuff goes to CRAP)
3417 */
3418 static u_int
create_refnum(void)3419 create_refnum(void)
3420 {
3421 unsigned int new_refnum = 1;
3422 Window *tmp;
3423 int done = 0;
3424
3425 while (!done)
3426 {
3427 Win_Trav wt;
3428
3429 done = 1;
3430 if (new_refnum == 0)
3431 new_refnum++;
3432
3433 wt.init = 1;
3434 while ((tmp = window_traverse(&wt)) != NULL)
3435 {
3436 if (window_get_refnum(tmp) == new_refnum)
3437 {
3438 done = 0;
3439 new_refnum++;
3440 break;
3441 }
3442 }
3443 }
3444 return (new_refnum);
3445 }
3446
3447 /*
3448 * new_window: This creates a new window on the screen. It does so by either
3449 * splitting the current window, or if it can't do that, it splits the
3450 * largest window. The new window is added to the window list and made the
3451 * current window
3452 *
3453 * move this into window.c.
3454 */
3455 Window *
new_window(void)3456 new_window(void)
3457 {
3458 Window *new;
3459 static int no_screens = 1;
3460
3461 if (no_screens)
3462 {
3463 set_current_screen(create_new_screen());
3464 set_main_screen(get_current_screen());
3465 no_screens = 0;
3466 }
3467 if (term_basic() && (number_of_windows() == 1))
3468 return NULL;
3469 new = new_malloc(sizeof *new);
3470 new->refnum = create_refnum();
3471 if (curr_scr_win)
3472 new->server = curr_scr_win->server;
3473 else
3474 new->server = get_primary_server();
3475 new->prev_server = -1;
3476 new->line_cnt = 0;
3477 if (number_of_windows() == 0)
3478 new->window_level = LOG_DEFAULT;
3479 else
3480 new->window_level = LOG_NONE;
3481 new->hold_mode = get_int_var(HOLD_MODE_VAR);
3482 new->hold_info = alloc_hold_info();
3483 new->scroll = get_int_var(SCROLL_VAR);
3484 new->lastlog_info = lastlog_new_window();
3485 new->nicks = 0;
3486 new->name = 0;
3487 new->prompt = 0;
3488 new->current_channel = 0;
3489 new->bound_channel = 0;
3490 new->query_nick = 0;
3491 new->hold_on_next_rite = 0;
3492 new->status_line[0] = NULL;
3493 new->status_line[1] = NULL;
3494 new->double_status = 0;
3495 new->top_of_display = 0;
3496 new->display_ip = 0;
3497 new->display_size = 1;
3498 new->old_size = 1;
3499 new->scrolled_lines = 0;
3500 new->new_scrolled_lines = 0;
3501 new->next = 0;
3502 new->prev = 0;
3503 new->cursor = 0;
3504 new->visible = 1;
3505 new->screen = get_current_screen();
3506 new->logfile = 0;
3507 new->log = 0;
3508 new->log_fp = 0;
3509 new->miscflags = 0;
3510 new->update = 0;
3511 new->menu = menu_init();
3512 new->notify_level = real_notify_level();
3513 new->server_group = 0;
3514 new->sticky = 1;
3515 resize_display(new);
3516 if (add_to_window_list(new))
3517 set_current_window(new);
3518 term_flush();
3519 return (new);
3520 }
3521
3522 /*
3523 * is_window_name_unique: checks the given name vs the names of all the
3524 * windows and returns true if the given name is unique, false otherwise
3525 */
3526 static int
is_window_name_unique(u_char * name)3527 is_window_name_unique(u_char *name)
3528 {
3529 Window *tmp;
3530 Win_Trav wt;
3531
3532 if (name)
3533 {
3534 wt.init = 1;
3535 while ((tmp = window_traverse(&wt)) != NULL)
3536 {
3537 if (tmp->name && (my_stricmp(tmp->name, name) == 0))
3538 return (0);
3539 }
3540 }
3541 return (1);
3542 }
3543
3544 /*
3545 * free_display: This frees all memory for the display list for a given
3546 * window. It resets all of the structures related to the display list
3547 * appropriately as well
3548 */
3549 void
free_display(Window * window)3550 free_display(Window *window)
3551 {
3552 Display *tmp, *next;
3553 int i;
3554
3555 if (window == NULL)
3556 window = curr_scr_win;
3557 for (tmp = window->top_of_display, i = 0; i < window->display_size - window->double_status; i++, tmp = next)
3558 {
3559 next = tmp->next;
3560 new_free(&(tmp->line));
3561 new_free(&tmp);
3562 }
3563 window->top_of_display = NULL;
3564 window->display_ip = NULL;
3565 window->display_size = 0;
3566 }
3567
3568 /*
3569 * erase_display: This effectively causes all members of the display list for
3570 * a window to be set to empty strings, thus "clearing" a window. It sets
3571 * the cursor to the top of the window, and the display insertion point to
3572 * the top of the display. Note, this doesn't actually refresh the screen,
3573 * just cleans out the display list
3574 */
3575 void
erase_display(Window * window)3576 erase_display(Window *window)
3577 {
3578 int i;
3579 Display *tmp;
3580
3581 if (term_basic())
3582 return;
3583 if (window == NULL)
3584 window = curr_scr_win;
3585 for (tmp = window->top_of_display, i = 0; i < window->display_size;
3586 i++, tmp = tmp->next)
3587 new_free(&(tmp->line));
3588 window->cursor = 0;
3589 window->line_cnt = 0;
3590 window->hold_on_next_rite = 0;
3591 window->display_ip = window->top_of_display;
3592 }
3593
3594 void
window_add_display_line(Window * window,u_char * str,int logged)3595 window_add_display_line(Window *window, u_char *str, int logged)
3596 {
3597 if (window->scroll)
3598 scroll_window(window);
3599 malloc_strcpy(&window->display_ip->line, str);
3600 window->display_ip->linetype = logged;
3601 window->display_ip = window->display_ip->next;
3602 if (!window->scroll)
3603 new_free(&window->display_ip->line);
3604 }
3605
3606 /*
3607 * add_nicks_by_refnum: This adds the given str to the nicklist of the
3608 * window refnum. Only unique names are added to the list. If add is zero
3609 * or the name is preceeded by a ^ it is removed from the list. The str
3610 * may be a comma separated list of nicks, channels, etc .
3611 */
3612 static void
add_nicks_by_refnum(u_int refnum,u_char * str,int add)3613 add_nicks_by_refnum(u_int refnum, u_char *str, int add)
3614 {
3615 Window *tmp;
3616 u_char *ptr;
3617
3618 if ((tmp = get_window_by_refnum(refnum)) != NULL)
3619 {
3620 while (str)
3621 {
3622 if ((ptr = my_index(str, ',')) != NULL)
3623 *(ptr++) = '\0';
3624 if (add == 0 || *str == '^')
3625 {
3626 if (add == 0 && *str == '^')
3627 str++;
3628 if (nicks_remove_from_window(tmp, str))
3629 say("%s removed from window name list", str);
3630 else
3631 say("%s is not on the list for this window!", str);
3632 }
3633 else
3634 {
3635 if (nicks_add_to_window(tmp, str))
3636 say("%s add to window name list", str);
3637 else
3638 say("%s already on window name list", str);
3639 }
3640 str = ptr;
3641 }
3642 }
3643 else
3644 say("No such window!");
3645 }
3646
3647 /* below is stuff used for parsing of WINDOW command */
3648
3649 /*
3650 * get_window_by_name: returns a pointer to a window with a matching logical
3651 * name or null if no window matches
3652 */
3653 Window *
get_window_by_name(u_char * name)3654 get_window_by_name(u_char *name)
3655 {
3656 Window *tmp;
3657 Win_Trav wt;
3658
3659 wt.init = 1;
3660 while ((tmp = window_traverse(&wt)) != NULL)
3661 {
3662 if (tmp->name && (my_stricmp(tmp->name, name) == 0))
3663 return (tmp);
3664 }
3665 return (NULL);
3666 }
3667
3668 /*
3669 * get_window: this parses out any window (visible or not) and returns a
3670 * pointer to it
3671 */
3672 static Window *
get_window(u_char * name,u_char ** args)3673 get_window(u_char *name, u_char **args)
3674 {
3675 u_char *arg;
3676 Window *tmp;
3677
3678 if ((arg = next_arg(*args, args)) != NULL)
3679 {
3680 if (is_number(arg))
3681 {
3682 if ((tmp = get_window_by_refnum((u_int)my_atoi(arg))) != NULL)
3683 return (tmp);
3684 }
3685 if ((tmp = get_window_by_name(arg)) != NULL)
3686 return (tmp);
3687 say("%s: No such window: %s", name, arg);
3688 }
3689 else
3690 say("%s: Please specify a window refnum or name", name);
3691 return (NULL);
3692 }
3693
3694 /*
3695 * get_invisible_window: parses out an invisible window by reference number.
3696 * Returns the pointer to the window, or null. The args can also be "LAST"
3697 * indicating the top of the invisible window list (and thus the last window
3698 * made invisible)
3699 */
3700 static Window *
get_invisible_window(u_char * name,u_char ** args)3701 get_invisible_window(u_char *name, u_char **args)
3702 {
3703 u_char *arg;
3704 Window *tmp;
3705
3706 if ((arg = next_arg(*args, args)) != NULL)
3707 {
3708 if (my_strnicmp(arg, UP("LAST"), my_strlen(arg)) == 0)
3709 {
3710 if (invisible_list == NULL)
3711 say("%s: There are no hidden windows", name);
3712 return (invisible_list);
3713 }
3714 if ((tmp = get_window(name, &arg)) != NULL)
3715 {
3716 if (!tmp->visible)
3717 return (tmp);
3718 else
3719 {
3720 if (tmp->name)
3721 say("%s: Window %s is not hidden!",
3722 name, tmp->name);
3723 else
3724 say("%s: Window %d is not hidden!",
3725 name, tmp->refnum);
3726 }
3727 }
3728 }
3729 else
3730 say("%s: Please specify a window refnum or LAST", name);
3731 return (NULL);
3732 }
3733
3734 /* get_number: parses out an integer number and returns it */
3735 static int
get_number(u_char * name,u_char ** args)3736 get_number(u_char *name, u_char **args)
3737 {
3738 u_char *arg;
3739
3740 if ((arg = next_arg(*args, args)) != NULL)
3741 return (my_atoi(arg));
3742 else
3743 say("%s: You must specify the number of lines", name);
3744 return (0);
3745 }
3746
3747 /*
3748 * get_boolean: parses either ON, OFF, or TOGGLE and sets the var
3749 * accordingly. Returns 0 if all went well, -1 if a bogus or missing value
3750 * was specified
3751 */
3752 static int
get_boolean(u_char * name,u_char ** args,int * var)3753 get_boolean(u_char *name, u_char **args, int *var)
3754 {
3755 u_char *arg;
3756
3757 if (((arg = next_arg(*args, args)) == NULL) || do_boolean(arg, var))
3758 {
3759 say("Value for %s must be ON, OFF, or TOGGLE", name);
3760 return (-1);
3761 }
3762 else
3763 {
3764 say("Window %s is %s", name, var_settings(*var));
3765 return (0);
3766 }
3767 }
3768
3769 void
windowcmd(u_char * command,u_char * args,u_char * subargs)3770 windowcmd(u_char *command, u_char *args, u_char *subargs)
3771 {
3772 u_char *arg;
3773 int no_args = 1;
3774 Window *window;
3775
3776 update_all_windows();
3777 save_message_from();
3778 message_from(NULL, LOG_CURRENT);
3779 window = curr_scr_win;
3780 while ((arg = next_arg(args, &args)) != NULL)
3781 {
3782 size_t len;
3783 Window *tmp;
3784 u_char *cmd = NULL;
3785
3786 no_args = 0;
3787 len = my_strlen(arg);
3788 malloc_strcpy(&cmd, arg);
3789 upper(cmd);
3790 if (my_strncmp("NEW", cmd, len) == 0)
3791 {
3792 if ((tmp = new_window()) != NULL)
3793 window = tmp;
3794 }
3795 #ifdef WINDOW_CREATE
3796 else if (my_strncmp("CREATE", cmd, len) == 0)
3797 {
3798 int type;
3799
3800 if (*args == '-' &&
3801 (arg = next_arg(args, &args)) != NULL)
3802 {
3803 if (my_stricmp(arg, UP("-SCREEN")) == 0)
3804 type = ST_SCREEN;
3805 else if (my_stricmp(arg, UP("-XTERM")) == 0)
3806 type = ST_XTERM;
3807 else {
3808 say("Unknown /WINDOW CREATE option");
3809 continue;
3810 }
3811 }
3812 else
3813 type = ST_NOTHING;
3814 if ((tmp = create_additional_screen(type)) != NULL)
3815 window = tmp;
3816 else
3817 say("Cannot create new screen!");
3818 }
3819 else if (!my_strncmp("DELETE", cmd, len))
3820 kill_screen(get_current_screen());
3821 #endif /* WINODW_CREATE */
3822 else if (my_strncmp("REFNUM", cmd, len) == 0)
3823 {
3824 if ((tmp = get_window(UP("REFNUM"), &args)) != NULL)
3825 {
3826 if (tmp->screen && tmp->screen !=window->screen)
3827 say("Window in another screen!");
3828 else if (tmp->visible)
3829 {
3830 set_current_window(tmp);
3831 window = tmp;
3832 }
3833 else
3834 say("Window not visible!");
3835 }
3836 else
3837 {
3838 say("No such window!");
3839 new_free(&cmd);
3840 goto out;
3841 }
3842 }
3843 else if (my_strncmp("KILL", cmd, len) == 0)
3844 delete_window(window);
3845 else if (my_strncmp("SHRINK", cmd, len) == 0)
3846 grow_window(window, -get_number(UP("SHRINK"), &args));
3847 else if (my_strncmp("GROW", cmd, len) == 0)
3848 grow_window(window, get_number(UP("SHRINK"), &args));
3849 else if (my_strncmp("SCROLL", cmd, len) == 0)
3850 get_boolean(UP("SCROLL"), &args, &(window->scroll));
3851 else if (my_strncmp("STICKY", cmd, len) == 0)
3852 get_boolean(UP("STICKY"), &args, &(window->sticky));
3853 else if (my_strncmp("LOG", cmd, len) == 0)
3854 {
3855 if (get_boolean(UP("LOG"), &args, &(window->log)))
3856 break;
3857 else
3858 {
3859 u_char *buffer = NULL;
3860 u_char *logfile;
3861 int add_ext = 1;
3862
3863 if ((logfile = window->logfile) != NULL)
3864 add_ext = 0;
3865 else if (!(logfile = get_string_var(LOGFILE_VAR)))
3866 logfile = empty_string();
3867 if (!add_ext)
3868 malloc_snprintf(&buffer, "%s", logfile);
3869 else if (window->current_channel)
3870 malloc_snprintf(&buffer, "%s.%s", logfile, window->current_channel);
3871 else if (window->query_nick)
3872 malloc_snprintf(&buffer, "%s.%s", logfile, window->query_nick);
3873 else
3874 malloc_snprintf(&buffer, "%s.Window_%d", logfile, window->refnum);
3875 do_log(window->log, buffer, &window->log_fp);
3876 new_free(&buffer);
3877 if (window->log_fp == NULL)
3878 window->log = 0;
3879 }
3880 }
3881 else if (my_strncmp("HOLD_MODE", cmd, len) == 0)
3882 get_boolean(UP("HOLD_MODE"), &args, &window->hold_mode);
3883 else if (my_strncmp("LASTLOG_LEVEL", cmd, len) == 0)
3884 {
3885 if ((arg = next_arg(args, &args)) != NULL)
3886 {
3887 int lastlog_level = parse_lastlog_level(arg);
3888 lastlog_set_level(window->lastlog_info,
3889 lastlog_level);
3890 say("Lastlog level is %s",
3891 bits_to_lastlog_level(lastlog_level));
3892 }
3893 else
3894 say("Level required");
3895 }
3896 else if (my_strncmp("LEVEL", cmd, len) == 0)
3897 {
3898 if ((arg = next_arg(args, &args)) != NULL)
3899 {
3900 window->window_level = parse_lastlog_level(arg);
3901 say("Window level is %s",
3902 bits_to_lastlog_level(window->window_level));
3903 revamp_window_levels(window);
3904 }
3905 else
3906 say("LEVEL: Level required");
3907 }
3908 else if (my_strncmp("BALANCE", cmd, len) == 0)
3909 balance_windows();
3910 else if (my_strncmp("NAME", cmd, len) == 0)
3911 {
3912 if ((arg = next_arg(args, &args)) != NULL)
3913 {
3914 if (is_window_name_unique(arg))
3915 {
3916 malloc_strcpy(&window->name, arg);
3917 window->update |= UPDATE_STATUS;
3918 }
3919 else
3920 say("%s is not unique!", arg);
3921 }
3922 else
3923 say("You must specify a name for the window!");
3924 }
3925 else if (my_strncmp("PROMPT", cmd, len) == 0)
3926 {
3927 if ((arg = next_arg(args, &args)) != NULL)
3928 {
3929 malloc_strcpy(&window->prompt, arg);
3930 window->update |= UPDATE_STATUS;
3931 }
3932 else
3933 say("You must specify a prompt for the window!");
3934 }
3935 else if (my_strncmp("GOTO", cmd, len) == 0)
3936 {
3937 irc_goto_window(get_number(UP("GOTO"), &args));
3938 window = curr_scr_win;
3939 }
3940 else if (my_strncmp("LAST", cmd, len) == 0)
3941 set_current_window(NULL);
3942 else if (my_strncmp("MOVE", cmd, len) == 0)
3943 {
3944 move_window(window, get_number(UP("MOVE"), &args));
3945 window = curr_scr_win;
3946 }
3947 else if (my_strncmp("SWAP", cmd, len) == 0)
3948 {
3949 if ((tmp = get_invisible_window(UP("SWAP"), &args)) != NULL)
3950 swap_window(window, tmp);
3951 }
3952 else if (my_strncmp("HIDE", cmd, len) == 0)
3953 hide_window(window);
3954 else if (my_strncmp("PUSH", cmd, len) == 0)
3955 push_window_by_refnum(window->refnum);
3956 else if (my_strncmp("POP", cmd, len) == 0)
3957 pop_window();
3958 else if (my_strncmp("ADD", cmd, len) == 0)
3959 {
3960 if ((arg = next_arg(args, &args)) != NULL)
3961 add_nicks_by_refnum(window->refnum, arg, 1);
3962 else
3963 say("ADD: Do something! Geez!");
3964 }
3965 else if (my_strncmp("REMOVE", cmd, len) == 0)
3966 {
3967 if ((arg = next_arg(args, &args)) != NULL)
3968 add_nicks_by_refnum(window->refnum, arg, 0);
3969 else
3970 say("REMOVE: Do something! Geez!");
3971 }
3972 else if (my_strncmp("STACK", cmd, len) == 0)
3973 show_stack();
3974 else if (my_strncmp("LIST", cmd, len) == 0)
3975 list_windows();
3976 else if (my_strncmp("SERVER", cmd, len) == 0)
3977 {
3978 if ((arg = next_arg(args, &args)) != NULL)
3979 {
3980 u_char *group = 0,
3981 *proxy_name = NULL,
3982 *proxy_port_str;
3983 int type = Server2_8;
3984 int proxy_port = 0;
3985 server_ssl_level level = SSL_OFF;
3986
3987 while (*arg == '-')
3988 {
3989 if (my_stricmp(UP("-ICB"), arg) == 0)
3990 type = ServerICB;
3991 else if (my_stricmp(UP("-IRC"), arg) == 0)
3992 type = Server2_8;
3993 else if (my_stricmp(UP("-SSL"), arg) == 0)
3994 level = SSL_VERIFY;
3995 else if (my_stricmp(UP("-SSLNOCHECK"), arg) == 0)
3996 level = SSL_ON;
3997 else if (my_stricmp(UP("-NOSSL"), arg) == 0)
3998 level = SSL_OFF;
3999 else if (my_stricmp(UP("-GROUP"), arg) == 0)
4000 {
4001 if ((group = next_arg(args, &args)) == NULL)
4002 {
4003 say("SERVER -GROUP needs <group> and <server>");
4004 new_free(&cmd);
4005 goto out;
4006 }
4007 }
4008 else if (my_stricmp(UP("-PROXY"), arg) == 0)
4009 {
4010 if ((proxy_name = next_arg(args, &args)) == NULL ||
4011 (proxy_port_str = next_arg(args, &args)) == NULL)
4012 {
4013 say("SERVER -PROXY needs <proxy> and <host>");
4014 new_free(&cmd);
4015 goto out;
4016 }
4017 proxy_port = my_atoi(proxy_port_str);
4018 }
4019 else
4020 say("SERVER: %s: unknown flag", arg);
4021 if ((arg = next_arg(args, &args)) == NULL)
4022 say("SERVER: You must specify a server");
4023 }
4024 window_get_connected(window, arg, -1, args,
4025 proxy_name, proxy_port, group, type, level);
4026 }
4027 else
4028 say("SERVER: You must specify a server");
4029 }
4030 else if (my_strncmp("SHOW", cmd, len) == 0)
4031 {
4032 if ((tmp = get_window(UP("SHOW"), &args)) != NULL)
4033 {
4034 show_window(tmp);
4035 window = curr_scr_win;
4036 }
4037 }
4038 else if (my_strncmp("HIDE_OTHERS", cmd, len) == 0)
4039 hide_other_windows();
4040 else if (my_strncmp("KILL_OTHERS", cmd, len) == 0)
4041 delete_other_windows();
4042 else if (my_strncmp("NOTIFY", cmd, len) == 0)
4043 {
4044 window->miscflags ^= WINDOW_NOTIFY;
4045 say("Notification when hidden set to %s",
4046 (window->miscflags & WINDOW_NOTIFY)? "ON" : "OFF");
4047 }
4048 else if (my_strncmp("WHERE", cmd, len) == 0)
4049 window_list_channels(curr_scr_win);
4050 else if (my_strncmp("QUERY", cmd, len) == 0)
4051 {
4052 u_char *a = 0;
4053
4054 a = next_arg(args, &args);
4055 query(cmd, a, 0);
4056 }
4057 else if (my_strncmp("CHANNEL", cmd, len) == 0)
4058 {
4059 if ((arg = next_arg(args, &args)) != NULL)
4060 {
4061 u_char *key, *t;
4062
4063 t = arg;
4064 arg = my_strsep(&t, UP(","));
4065 if ((key = my_strsep(&t, UP(", "))) == 0)
4066 key = 0;
4067
4068 if (is_bound(arg, window->server))
4069 {
4070 say("Channel %s is bound", arg);
4071 }
4072 else
4073 {
4074 if (is_on_channel(arg, window->server,
4075 server_get_nickname(window->server)))
4076 {
4077 is_current_channel(arg, window->server,
4078 (int)window->refnum);
4079 say("You are now talking to channel %s", arg);
4080 set_channel_by_refnum(0, arg);
4081 }
4082 else if (*arg == '0' && !*(arg + 1))
4083 set_channel_by_refnum(0, NULL);
4084 else
4085 {
4086 int server;
4087
4088 server = set_from_server(window->server);
4089 switch (server_get_version(window->server)) {
4090 case ServerICB:
4091 icb_put_group(arg);
4092 break;
4093 default:
4094 send_to_server("JOIN %s%s%s", arg,
4095 key ? (u_char *) " " : empty_string(),
4096 key ? key : empty_string());
4097 }
4098 add_channel(arg, key, window->server, CHAN_JOINING, NULL);
4099 set_from_server(server);
4100 }
4101 }
4102 }
4103 else
4104 set_channel_by_refnum(0, zero());
4105 }
4106 else if (my_strncmp("PREVIOUS", cmd, len) == 0)
4107 {
4108 swap_previous_window(0, NULL);
4109 }
4110 else if (my_strncmp("NEXT", cmd, len) == 0)
4111 {
4112 swap_next_window(0, NULL);
4113 }
4114 else if (my_strncmp("BACK", cmd, len) == 0)
4115 {
4116 back_window(0, NULL);
4117 }
4118 else if (my_strncmp("KILLSWAP", cmd, len) == 0)
4119 {
4120 window_kill_swap();
4121 }
4122 else if (my_strncmp("LOGFILE", cmd, len) == 0)
4123 {
4124 if ((arg = next_arg(args, &args)) != NULL)
4125 {
4126 malloc_strcpy(&window->logfile, arg);
4127 say("Window LOGFILE set to %s", arg);
4128 }
4129 else
4130 say("No LOGFILE given");
4131 }
4132 else if (my_strncmp("NOTIFY_LEVEL", cmd, len) == 0)
4133 {
4134 if ((arg = next_arg(args, &args)) != NULL)
4135 {
4136 window->notify_level = parse_lastlog_level(arg);
4137 say("Window notify level is %s",
4138 bits_to_lastlog_level(window->notify_level));
4139 }
4140 else
4141 say("Level missing");
4142 }
4143 else if (my_strncmp("NUMBER", cmd, len) == 0)
4144 {
4145 if ((arg = next_arg(args, &args)) != NULL)
4146 {
4147 int i;
4148 Window *wtmp;
4149
4150 i = my_atoi(arg);
4151 if (i > 0)
4152 {
4153 /* check if window number exists */
4154
4155 wtmp = get_window_by_refnum((u_int)i);
4156 if (!wtmp)
4157 window->refnum = i;
4158 else
4159 {
4160 wtmp->refnum = window->refnum;
4161 window->refnum = i;
4162 }
4163 update_all_status();
4164 }
4165 else
4166 say("Window number must be greater "
4167 "than 1");
4168 }
4169 else
4170 say("Window number missing");
4171 }
4172 else if (my_strncmp("BIND", cmd, len) == 0)
4173 {
4174 if ((arg = next_arg(args, &args)) != NULL)
4175 {
4176 if (!is_channel(arg))
4177 say("BIND: %s is not a valid "
4178 "channel name", arg);
4179 else
4180 {
4181 bind_channel(arg, window);
4182 }
4183 }
4184 else
4185 if (window->bound_channel)
4186 say("Channel %s is bound to window %d",
4187 window->bound_channel,
4188 window->refnum);
4189 }
4190 else if (my_strncmp("UNBIND", cmd, len) == 0)
4191 {
4192 if ((arg = next_arg(args, &args)) != NULL)
4193 {
4194 if (is_bound(arg, window->server))
4195 {
4196 say("Channel %s is no longer bound",
4197 arg);
4198 unbind_channel(arg, window);
4199 }
4200 else
4201 say("Channel %s is not bound", arg);
4202 }
4203 else
4204 say("UNBIND: You must specify a channel name");
4205 }
4206 else if (my_strncmp("ADDGROUP", cmd, len) == 0)
4207 {
4208 if ((arg = next_arg(args, &args)) != NULL)
4209 add_window_to_server_group(window, arg);
4210 else
4211 say("WINDOW ADDGROUP requires a group name");
4212 }
4213 else if (my_strncmp("DELGROUP", cmd, len) == 0)
4214 {
4215 window->server_group = 0;
4216 say("Window no longer has a server group");
4217 update_window_status(window, 1);
4218 }
4219 else if (my_strncmp("DOUBLE", cmd, len) == 0)
4220 {
4221 int current = window->double_status;
4222
4223 if (get_boolean(UP("DOUBLE"), &args,
4224 &window->double_status) == 0)
4225 {
4226 window->display_size += current -
4227 window->double_status;
4228 recalculate_window_positions();
4229 update_all_windows();
4230 build_status((u_char *) NULL);
4231 }
4232 }
4233 else if (my_strncmp("NOSTATUS", cmd, len) == 0)
4234 {
4235 int current = window->double_status;
4236
4237 window->double_status = -1;
4238 window->display_size += current - window->double_status;
4239 recalculate_window_positions();
4240 update_all_windows();
4241 build_status((u_char *) NULL);
4242 }
4243 else
4244 say("Unknown WINDOW command: %s", arg);
4245 new_free(&cmd);
4246 }
4247 if (no_args)
4248 {
4249 if (window->name)
4250 say("Window %s (%u)", window->name, window->refnum);
4251 else
4252 say("Window %u", window->refnum);
4253 if (window->server == -1)
4254 say("\tServer: <None>");
4255 else
4256 say("\tServer: %s", server_get_name(window->server));
4257 say("\tCurrent channel: %s",
4258 window->current_channel ?
4259 window->current_channel : UP("<None>"));
4260 say("\tQuery User: %s",
4261 window->query_nick ? window->query_nick : UP("<None>"));
4262 say("\tPrompt: %s",
4263 window->prompt ? window->prompt : (u_char *) "<None>");
4264 say("\tSecond status line is %s",
4265 var_settings(window->double_status));
4266 say("\tScrolling is %s", var_settings(window->scroll));
4267 say("\tLogging is %s", var_settings(window->log));
4268 if (window->logfile)
4269 say("\tLogfile is %s", window->logfile);
4270 else
4271 say("\tNo logfile given");
4272 say("\tNotification is %s",
4273 var_settings(window->miscflags & WINDOW_NOTIFY));
4274 say("\tHold mode is %s", var_settings(window->hold_mode));
4275 say("\tSticky behaviour is %s", var_settings(window->sticky));
4276 say("\tWindow level is %s",
4277 bits_to_lastlog_level(window->window_level));
4278 say("\tLastlog level is %s",
4279 bits_to_lastlog_level(lastlog_get_level(window->lastlog_info)));
4280 say("\tNotify level is %s",
4281 bits_to_lastlog_level(window->notify_level));
4282 if (window->server_group)
4283 say("\tServer Group is (%d) %s", window->server_group,
4284 find_server_group_name(window->server_group));
4285 if (window->bound_channel)
4286 say("\tBound Channel is %s", window->bound_channel);
4287 display_nicks_info(window);
4288 }
4289 out:
4290 restore_message_from();
4291 update_all_windows();
4292 cursor_to_input();
4293 }
4294
4295 int
number_of_windows(void)4296 number_of_windows(void)
4297 {
4298 return screen_get_visible_windows(get_current_screen());
4299 }
4300
4301 void
unstop_all_windows(u_int key,u_char * ptr)4302 unstop_all_windows(u_int key, u_char *ptr)
4303 {
4304 Window *tmp;
4305
4306 for (tmp = screen_get_window_list(get_current_screen()); tmp;
4307 tmp = tmp->next)
4308 window_hold_mode(tmp, OFF, 1);
4309 }
4310
4311 /* this will make underline toggle between 2 and -1 and never let it get to 0 */
4312 void
set_underline_video(int value)4313 set_underline_video(int value)
4314 {
4315 if (value == OFF)
4316 set_underline(-1);
4317 else
4318 set_underline(1);
4319 }
4320
4321 /*
4322 * if "arg" is NULL, nargs is a server to connect to.
4323 */
4324 void
window_get_connected(Window * window,u_char * arg,int narg,u_char * args,u_char * proxy_name,int proxy_port,u_char * group,int type,server_ssl_level level)4325 window_get_connected(Window *window, u_char *arg, int narg, u_char *args,
4326 u_char *proxy_name, int proxy_port,
4327 u_char *group, int type, server_ssl_level level)
4328 {
4329 int i,
4330 port_num,
4331 new_server_flags = WIN_TRANSFER;
4332 u_char *port,
4333 *password = NULL,
4334 *nick = NULL,
4335 *extra = NULL,
4336 *icbmode = NULL;
4337
4338 if (arg)
4339 {
4340 if (*arg == '=')
4341 {
4342 new_server_flags |= WIN_ALL;
4343 arg++;
4344 }
4345 else if (*arg == '~')
4346 {
4347 new_server_flags |= WIN_FORCE;
4348 arg++;
4349 }
4350 /*
4351 * work in progress.. window->prev_server needs to be set for
4352 * all windows that used to be associated with a server as it
4353 * switches [successfully] to a new server.
4354 * this'll be fun since that can happen in server.c and
4355 * window.c and non-blocking-connects will throw yet another
4356 * wrench into things since we only want it to happen on
4357 * a successful connect. - gkm
4358 */
4359 else if (*arg == '.')
4360 {
4361 if (*(++arg))
4362 {
4363 say("syntax error - nothing may be specified "
4364 "after the '.'");
4365 return;
4366 }
4367 if (window->prev_server != -1)
4368 {
4369 if (group)
4370 add_server_to_server_group(
4371 window->prev_server, group);
4372
4373 window_restore_server(window->prev_server);
4374 if (!proxy_name)
4375 proxy_name = server_get_proxy_name(
4376 window->prev_server, 0);
4377 if (proxy_port == 0)
4378 proxy_port = server_get_proxy_port(
4379 window->prev_server, 0);
4380 window_get_connected(window, NULL,
4381 window->server, NULL,
4382 proxy_name, proxy_port,
4383 group, type, level);
4384 }
4385 else
4386 say("No server previously in use in this window");
4387 return;
4388 }
4389 parse_server_info(&arg, &port, &password, &nick,
4390 group ? 0 : &group, &extra, &type, &level,
4391 &proxy_name, &proxy_port);
4392 if (port)
4393 {
4394 port_num = my_atoi(port);
4395 if (!port_num)
4396 port_num = -1;
4397 }
4398 else
4399 port_num = -1;
4400 if (extra)
4401 {
4402 if (type == ServerICB)
4403 {
4404 if ((icbmode = my_index(extra, ':')) && icbmode[1])
4405 *icbmode++ = 0;
4406 else
4407 icbmode = NULL;
4408 }
4409 /* XXX should handle extra as :#chan:#chan2:etc for IRC */
4410 }
4411 /* relies on parse_server_info putting a null in */
4412 /* This comes first for "/serv +1" -Sol */
4413 if ((i = parse_server_index(arg)) != -1)
4414 {
4415 if (port_num == -1) /* Could be "/serv +1:6664" -Sol */
4416 port_num = server_get_port(i);
4417 if (nick == NULL)
4418 nick = server_get_nickname(i);
4419 }
4420 else if ((i = find_in_server_list(arg, port_num, nick)) != -1)
4421 port_num = server_get_port(i);
4422 }
4423 else
4424 {
4425 i = narg;
4426 port_num = server_get_port(i);
4427 arg = server_get_name(i);
4428 if (!proxy_name)
4429 proxy_name = server_get_proxy_name(i, 0);
4430 if (proxy_port == 0)
4431 proxy_port = server_get_proxy_port(i, 0);
4432 }
4433
4434 if (!(new_server_flags & WIN_ALL))
4435 { /* Test if last window -Sol */
4436 Win_Trav wt;
4437 Window *ptr, *new_win = NULL;
4438
4439 wt.init = 1;
4440 while ((ptr = window_traverse(&wt)) != NULL)
4441 if ((ptr != window) &&
4442 (!ptr->server_group ||
4443 (ptr->server_group != window->server_group)) &&
4444 (ptr->server == window->server))
4445 {
4446 new_win = ptr;
4447 break;
4448 }
4449 if (!new_win)
4450 new_server_flags |= WIN_ALL;
4451 }
4452
4453 if (-1 == i)
4454 {
4455 if (!nick)
4456 nick = my_nickname();
4457 if (port_num == -1)
4458 port_num = CHOOSE_PORT(type);
4459
4460 add_to_server_list(arg, port_num, proxy_name, proxy_port,
4461 password, nick, -1, type,
4462 ssl_level_to_sa_flags(level));
4463
4464 if (group && *group)
4465 server_set_server_group(get_from_server(),
4466 find_server_group(group, 1));
4467
4468 if (extra && type == ServerICB)
4469 {
4470 u_char *newmode;
4471
4472 if ((newmode = my_index(extra, ':')))
4473 {
4474 *newmode++ = 0;
4475 server_set_icbmode(get_from_server(), newmode);
4476 }
4477 server_set_icbgroup(get_from_server(), extra);
4478 }
4479 }
4480 else
4481 {
4482 if (nick && *nick)
4483 server_set_nickname(i, nick);
4484 if (password && *password)
4485 server_set_password(i, password);
4486 if (extra && *extra)
4487 server_set_icbgroup(i, extra);
4488 if (icbmode && *icbmode)
4489 server_set_icbmode(i, icbmode);
4490 if (group && *group)
4491 server_set_server_group(i, find_server_group(group, 1));
4492 /* proxy_name & proxy_port? */
4493
4494 i = find_in_server_list(server_get_name(i), port_num, nick);
4495 if ((i != -1) && is_server_connected(i))
4496 new_server_flags &= ~WIN_TRANSFER;
4497
4498 arg = server_get_name(i);
4499 port_num = server_get_port(i);
4500 }
4501
4502 if (!connect_to_server(arg, port_num, nick,
4503 (new_server_flags & WIN_ALL) ? window->server : -1))
4504 {
4505 window_set_server((int)window->refnum, get_from_server(),
4506 new_server_flags);
4507 update_all_status();
4508 }
4509 window_check_servers();
4510 }
4511
4512 void
window_copy_prev_server(int server)4513 window_copy_prev_server(int server)
4514 {
4515 Win_Trav wt;
4516 Window *tmp;
4517
4518 wt.init = 1;
4519 while ((tmp = window_traverse(&wt)))
4520 if (tmp->server == server)
4521 tmp->prev_server = server;
4522 }
4523
4524 int
window_get_server(Window * window)4525 window_get_server(Window *window)
4526 {
4527 return window->server;
4528 }
4529
4530 int
window_get_server_group(Window * window)4531 window_get_server_group(Window *window)
4532 {
4533 return window->server_group;
4534 }
4535
4536 void
window_server_delete(int deleted_server)4537 window_server_delete(int deleted_server)
4538 {
4539 Window *tmp;
4540 Win_Trav wt;
4541
4542 wt.init = 1;
4543 while ((tmp = window_traverse(&wt)) != NULL)
4544 if (tmp->server > deleted_server && tmp->server > 0)
4545 tmp->server--;
4546 }
4547
4548 unsigned int
window_get_refnum(Window * window)4549 window_get_refnum(Window *window)
4550 {
4551 return window->refnum;
4552 }
4553
4554 int
window_get_sticky(Window * window)4555 window_get_sticky(Window *window)
4556 {
4557 return window->sticky;
4558 }
4559
4560 void
window_set_sticky(Window * window,int sticky)4561 window_set_sticky(Window *window, int sticky)
4562 {
4563 window->sticky = sticky;
4564 }
4565
4566 Window *
window_get_next(Window * window)4567 window_get_next(Window *window)
4568 {
4569 return window->next;
4570 }
4571
4572 Window *
window_get_prev(Window * window)4573 window_get_prev(Window *window)
4574 {
4575 return window->prev;
4576 }
4577
4578 Screen *
window_get_screen(Window * window)4579 window_get_screen(Window *window)
4580 {
4581 return window->screen;
4582 }
4583
4584 int
window_is_current(Window * window)4585 window_is_current(Window *window)
4586 {
4587 return screen_get_current_window(window->screen) == window ? 1 : 0;
4588 }
4589
4590 u_char *
window_get_name(Window * window)4591 window_get_name(Window *window)
4592 {
4593 return window->name;
4594 }
4595
4596 int
window_get_prev_server(Window * window)4597 window_get_prev_server(Window *window)
4598 {
4599 return window->prev_server;
4600 }
4601
4602 int
window_get_notify_level(Window * window)4603 window_get_notify_level(Window *window)
4604 {
4605 return window->notify_level;
4606 }
4607
4608 void
window_set_notify_level(Window * window,int level)4609 window_set_notify_level(Window *window, int level)
4610 {
4611 window->notify_level = level;
4612 }
4613
4614 u_char *
window_get_query_nick(Window * window)4615 window_get_query_nick(Window *window)
4616 {
4617 return window->query_nick;
4618 }
4619
4620 void
add_to_window_log(Window * window,u_char * str)4621 add_to_window_log(Window *window, u_char *str)
4622 {
4623 add_to_log(window->log_fp, str);
4624 }
4625
4626 LastlogInfo *
window_get_lastlog_info(Window * window)4627 window_get_lastlog_info(Window *window)
4628 {
4629 return window->lastlog_info;
4630 }
4631
4632 int
window_get_lastlog_size(Window * window)4633 window_get_lastlog_size(Window *window)
4634 {
4635 return lastlog_get_size(window->lastlog_info);
4636 }
4637
4638
4639 WindowMenu *
window_get_menu(Window * window)4640 window_get_menu(Window *window)
4641 {
4642 return window->menu;
4643 }
4644
4645 int
window_menu_lines(Window * window)4646 window_menu_lines(Window *window)
4647 {
4648 return menu_lines(window->menu);
4649 }
4650
4651 int
window_get_window_level(Window * window)4652 window_get_window_level(Window *window)
4653 {
4654 return window->window_level;
4655 }
4656
4657 u_char *
window_get_current_channel(Window * window)4658 window_get_current_channel(Window *window)
4659 {
4660 return window->current_channel;
4661 }
4662
4663 void
window_set_current_channel(Window * window,u_char * channel)4664 window_set_current_channel(Window *window, u_char *channel)
4665 {
4666 if (channel)
4667 malloc_strcpy(&window->current_channel, channel);
4668 else
4669 new_free(&window->current_channel);
4670 }
4671
4672 unsigned
window_get_miscflags(Window * window)4673 window_get_miscflags(Window *window)
4674 {
4675 return window->miscflags;
4676 }
4677
4678 void
window_set_miscflags(Window * window,unsigned setflags,unsigned unsetflags)4679 window_set_miscflags(Window *window, unsigned setflags, unsigned unsetflags)
4680 {
4681 window->miscflags &= ~unsetflags;
4682 window->miscflags |= setflags;
4683 }
4684
4685 int
window_get_all_scrolled_lines(Window * window)4686 window_get_all_scrolled_lines(Window *window)
4687 {
4688 return window->scrolled_lines + window->new_scrolled_lines;
4689 }
4690
4691 int
window_get_scrolled_lines(Window * window)4692 window_get_scrolled_lines(Window *window)
4693 {
4694 return window->scrolled_lines;
4695 }
4696
4697 int
window_held_lines(Window * window)4698 window_held_lines(Window *window)
4699 {
4700 return held_lines(window->hold_info);
4701 }
4702
4703 void
window_remove_from_hold_list(Window * window)4704 window_remove_from_hold_list(Window *window)
4705 {
4706 remove_from_hold_list(window->hold_info);
4707 }
4708
4709 void
window_hold_mode(Window * window,int flag,int update)4710 window_hold_mode(Window *window, int flag, int update)
4711 {
4712 if (window == NULL)
4713 window = curr_scr_win;
4714 hold_mode(window, window->hold_info, flag, update);
4715 }
4716
4717 int
window_hold_output(Window * window)4718 window_hold_output(Window *window)
4719 {
4720 if (!window)
4721 window = curr_scr_win;
4722 return hold_output(window, window->hold_info);
4723 }
4724
4725 int
window_held(Window * window)4726 window_held(Window *window)
4727 {
4728 return hold_is_held(window->hold_info);
4729 }
4730
4731 void
window_add_new_scrolled_line(Window * window)4732 window_add_new_scrolled_line(Window *window)
4733 {
4734 window->new_scrolled_lines++;
4735 }
4736
4737 int
window_get_hold_mode(Window * window)4738 window_get_hold_mode(Window *window)
4739 {
4740 return window->hold_mode;
4741 }
4742
4743 void
window_set_hold_mode(Window * window,int val)4744 window_set_hold_mode(Window *window, int val)
4745 {
4746 window->hold_mode = val;
4747 }
4748
4749 int
window_get_hold_on_next_rite(Window * window)4750 window_get_hold_on_next_rite(Window *window)
4751 {
4752 return window->hold_on_next_rite;
4753 }
4754
4755 void
window_set_hold_on_next_rite(Window * window,int val)4756 window_set_hold_on_next_rite(Window *window, int val)
4757 {
4758 window->hold_on_next_rite = val;
4759 }
4760
4761 int
window_get_double_status(Window * window)4762 window_get_double_status(Window *window)
4763 {
4764 return window->double_status;
4765 }
4766
4767 void
window_set_status_line(Window * window,int line,u_char * str)4768 window_set_status_line(Window *window, int line, u_char *str)
4769 {
4770 if (line < ARRAY_SIZE(window->status_line) || line < 0)
4771 {
4772 if (str)
4773 malloc_strcpy(&window->status_line[line], str);
4774 else
4775 new_free(&window->status_line[line]);
4776 }
4777 else
4778 yell("-- window_set_status_line() called with line = %d", line);
4779 }
4780
4781 void
window_set_update(Window * window,unsigned setflags,unsigned unsetflags)4782 window_set_update(Window *window, unsigned setflags, unsigned unsetflags)
4783 {
4784 window->update &= ~unsetflags;
4785 window->update |= setflags;
4786 }
4787
4788 int
window_get_visible(Window * window)4789 window_get_visible(Window *window)
4790 {
4791 return window->visible;
4792 }
4793
4794 int
window_get_scroll(Window * window)4795 window_get_scroll(Window *window)
4796 {
4797 return window->scroll;
4798 }
4799
4800 int
window_get_display_size(Window * window)4801 window_get_display_size(Window *window)
4802 {
4803 return window->display_size;
4804 }
4805
4806 int
window_get_line_cnt(Window * window)4807 window_get_line_cnt(Window *window)
4808 {
4809 return window->line_cnt;
4810 }
4811
4812 void
window_set_line_cnt(Window * window,int line_cnt)4813 window_set_line_cnt(Window *window, int line_cnt)
4814 {
4815 window->line_cnt = line_cnt;
4816 }
4817
4818 int
window_get_cursor(Window * window)4819 window_get_cursor(Window *window)
4820 {
4821 return window->cursor;
4822 }
4823
4824 void
window_set_cursor(Window * window,int cursor)4825 window_set_cursor(Window *window, int cursor)
4826 {
4827 window->cursor = cursor;
4828 }
4829
4830 int
window_get_top(Window * window)4831 window_get_top(Window *window)
4832 {
4833 return window->top;
4834 }
4835
4836 int
window_get_bottom(Window * window)4837 window_get_bottom(Window *window)
4838 {
4839 return window->bottom;
4840 }
4841
4842 NickList **
window_get_nicks(Window * window)4843 window_get_nicks(Window *window)
4844 {
4845 return &window->nicks;
4846 }
4847
4848 HoldInfo *
window_get_hold_info(Window * window)4849 window_get_hold_info(Window *window)
4850 {
4851 return window->hold_info;
4852 }
4853
4854 int
window_has_who_from(Window * window)4855 window_has_who_from(Window *window)
4856 {
4857 return nicks_has_who_from(&window->nicks);
4858 }
4859
4860 int
current_who_level(void)4861 current_who_level(void)
4862 {
4863 return who_level;
4864 }
4865
4866 u_char *
current_who_from(void)4867 current_who_from(void)
4868 {
4869 return who_from;
4870 }
4871