/* * window.c: Handles the Main Window stuff for irc. This includes proper * scrolling, saving of screen memory, refreshing, clearing, etc. * * Written By Michael Sandrof * * Copyright (c) 1990 Michael Sandrof. * Copyright (c) 1991, 1992 Troy Rollo. * Copyright (c) 1992-2003 Matthew R. Green. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: window.c,v 1.45 2005/08/08 18:50:47 f Exp $ */ #include "irc.h" #include "screen.h" #include "menu.h" #include "window.h" #include "vars.h" #include "server.h" #include "list.h" #include "ircterm.h" #include "names.h" #include "ircaux.h" #include "input.h" #include "status.h" #include "output.h" #include "log.h" #include "hook.h" #include "dcc.h" #include "translat.h" #include "parse.h" /**************************** PATCHED by Flier ******************************/ #include "myvars.h" #ifdef SZ32 #include #endif /****************************************************************************/ /* value for underline mode, is 0 when on! -lynx */ int underline = 1; /* * The following should synthesize MAXINT on any machine with an 8 bit * word. */ #define MAXINT (-1&~(1<<(sizeof(int)*8-1))) Window *invisible_list = (Window *) 0; /* list of hidden windows */ char *who_from = (char *) 0; /* nick of person who's message * is being displayed */ int who_level = LOG_CRAP; /* Log level of message being displayed */ int in_window_command = 0; /* set to true if we are in window(). This * is used if a put_it() is called within the * window() command. We make sure all * windows are fully updated before doing the * put_it(). */ extern char *redirect_nick; /**************************** PATCHED by Flier ******************************/ extern NickList *tabnickcompl; #ifdef HAVE_SSL extern int SSLconnect; #endif /****************************************************************************/ /* * window_display: this controls the display, 1 being ON, 0 being OFF. The * DISPLAY var sets this. */ unsigned int window_display = 1; /* * status_update_flag: if 1, the status is updated as normal. If 0, then all * status updating is suppressed */ int status_update_flag = 1; #ifdef lines #undef lines #endif /* lines */ static void realloc_channels _((Window *)); static void remove_from_window_list _((Window *)); static void hide_window _((Window *)); static void hide_other_windows _((void)); static void free_hold _((Window *)); static void free_lastlog _((Window *)); static void free_display _((Window *)); static void free_nicks _((Window *)); static void remove_from_invisible_list _((Window *)); static void revamp_window_levels _((Window *)); static void swap_channels_win_ptr _((Window *, Window *)); /**************************** PATCHED by Flier ******************************/ /*static void swap_window _((Window *, Window *));*/ void swap_window _((Window *, Window *)); /****************************************************************************/ static void move_window _((Window *, int)); static void grow_window _((Window *, int)); /**************************** Patched by Flier ******************************/ static void size_window _((Window *, int)); /****************************************************************************/ static Window *get_next_window _((void)); static Window *get_previous_window _((void)); static void delete_other_windows _((void)); static void bind_channel _((char *, Window *)); static void unbind_channel _((char *, Window *)); /**************************** PATCHED by Flier ******************************/ /*static void irc_goto_window _((int));*/ void irc_goto_window _((int)); /****************************************************************************/ static void list_a_window _((Window *, int, int)); static void list_windows _((void)); static void show_window _((Window *)); #ifndef LITE static void push_window_by_refnum _((u_int)); static void pop_window _((void)); static void show_stack _((void)); #endif static int is_window_name_unique _((char *)); static void add_nicks_by_refnum _((u_int, char *, int)); static Window *get_window _((char *, char **)); static Window *get_invisible_window _((char *, char **)); static int get_number _((char *, char **)); static int get_boolean _((char *, char **, int *)); static void win_list_channels _((Window *)); /**************************** PATCHED by Flier ******************************/ extern int AddLast _((List *, List *)); /****************************************************************************/ /* * traverse_all_windows: This will do as the name implies, traverse every * window (visible and invisible) and return a pointer to each window on * subsequent calls. If flag points to a non-zero value, then the traversal * in started from the beginning again, and flag is set to point to 0. This * returns all visible windows first, then all invisible windows. It returns * null after all windows have been returned. It should generally be used as * follows: * * flag = 1; while(tmp = traverse_all_windows(&flag)) { code here } * * Major revamp by phone (phone@coombs.anu.edu.au), December 1992. */ Window * traverse_all_windows(flag) int *flag; { static Window *which; static Screen *screen; static char visible = 1; int foo = 1; /* First call, return the current window basically */ if (*flag) { *flag = 0; visible = 1; if (!screen_list) return (Window *) 0; screen = screen_list; which = screen->window_list; if (which) return (which); else foo = 0; } /* * foo is used to indicate the the current screen has no windows. * This happens when we create a new screen.. either way, we want * to go on to the next screen, so if foo isn't set, then if which * is already null, return it again (this should never happen, if * traverse_all_windows()'s is called properly), else move on to * the next window */ if (foo) { if (!which) return (Window *) 0; else which = which->next; } if (!which) { while (screen) { screen = screen->next; if (screen && screen->alive) break; } if (screen) which = screen->window_list; } if (which) return (which); /* * Got to the end of the visible list.. so we do the invisible list.. * Should also mean, that we've got to the end of all the visible * screen.. */ if (visible) { visible = 0; which = invisible_list; return (which); } return ((Window *) 0); } /* * window_traverse: This will do as the name implies, traverse every * window (visible and invisible) and return a pointer to each window on * subsequent calls. If flag points to a non-zero value, then the traversal * in started from the beginning again, and flag is set to point to 0. This * returns all visible windows first, then all invisible windows. It returns * null after all windows have been returned. It should generally be used as * follows: * * Win_Trav stuff; * Window *tmp; * * stuff.flag = 1; * while ((tmp = window_traverse(&stuff))) * { code here } * * this version is recursive. */ Window * window_traverse(stuff) Win_Trav *stuff; { int foo = 1; /* First call, return the current window basically */ if (stuff->flag) { stuff->flag = 0; stuff->visible = 1; if (!screen_list) return (Window *) 0; stuff->screen = screen_list; stuff->which = stuff->screen->window_list; if (stuff->which) return (stuff->which); else foo = 0; } /* * foo is used to indicate the the current screen has no windows. * This happens when we create a new screen.. either way, we want * to go on to the next screen, so if foo isn't set, then if which * is already null, return it again (this should never happen, if * traverse_all_windows()'s is called properly), else move on to * the next window */ if (foo) { if (!stuff->which) return (Window *) 0; else stuff->which = stuff->which->next; } if (!stuff->which) { while (stuff->screen) { stuff->screen = stuff->screen->next; if (stuff->screen && stuff->screen->alive) break; } if (stuff->screen) stuff->which = stuff->screen->window_list; } if (stuff->which) return (stuff->which); /* * Got to the end of the visible list.. so we do the invisible list.. * Should also mean, that we've got to the end of all the visible * screen.. */ if (stuff->visible) { stuff->visible = 0; stuff->which = invisible_list; return (stuff->which); } return ((Window *) 0); } void add_window_to_server_group(window, group) Window *window; char *group; { int i = find_server_group(group, 1); int flag = 1; Window *tmp; while ((tmp = traverse_all_windows(&flag)) != (Window *) 0) if ((tmp->server_group == i) && (tmp->server != window->server)) { say("Group %s already contains a different server", group); return; } window->server_group = i; say("Window's server group is now %s", group); update_window_status(window, 1); } /* * set_scroll_lines: called by /SET SCROLL_LINES to check the scroll lines * value */ void set_scroll_lines(size) int size; { if (size == 0) { set_var_value(SCROLL_VAR, var_settings[0]); if (curr_scr_win) curr_scr_win->scroll = 0; } else if (size > curr_scr_win->display_size) { say("Maximum lines that may be scrolled is %d", curr_scr_win->display_size); set_int_var(SCROLL_LINES_VAR, (u_int)curr_scr_win->display_size); } } /* * set_scroll: called by /SET SCROLL to make sure the SCROLL_LINES variable * is set correctly */ void set_scroll(value) int value; { if (value && (get_int_var(SCROLL_LINES_VAR) == 0)) { put_it("You must set SCROLL_LINES to a positive value first!"); if (curr_scr_win) curr_scr_win->scroll = 0; } else { if (curr_scr_win) { int old_value = curr_scr_win->scroll; old_value = curr_scr_win->scroll; curr_scr_win->scroll = value; if (old_value != value) scroll_window(curr_scr_win); } } } /* * reset_line_cnt: called by /SET HOLD_MODE to reset the line counter so we * always get a held screen after the proper number of lines */ void reset_line_cnt(value) int value; { curr_scr_win->hold_mode = value; curr_scr_win->hold_on_next_rite = 0; curr_scr_win->line_cnt = 0; } /* * set_continued_line: checks the value of CONTINUED_LINE for validity, * altering it if its no good */ void set_continued_line(value) char *value; { if (value && ((int) strlen(value) > (current_screen->co / 2))) value[current_screen->co / 2] = '\0'; } /* * free_hold: This frees all the data and structures associated with the hold * list for the given window */ static void free_hold(window) Window *window; { Hold *tmp, *next; for (tmp = window->hold_head; tmp; tmp = next) { next = tmp->next; new_free(&(tmp->str)); new_free(&tmp); } } /* * free_lastlog: This frees all data and structures associated with the * lastlog of the given window */ static void free_lastlog(window) Window *window; { Lastlog *tmp, *next; for (tmp = window->lastlog_head; tmp; tmp = next) { next = tmp->next; new_free(&(tmp->msg)); new_free(&tmp); } } /* * free_display: This frees all memory for the display list for a given * window. It resets all of the structures related to the display list * appropriately as well */ static void free_display(window) Window *window; { Display *tmp, *next; int i; if (window == (Window *) 0) window = curr_scr_win; for (tmp = window->top_of_display, i = 0; i < window->display_size - window->double_status; i++, tmp = next) { next = tmp->next; new_free(&(tmp->line)); new_free(&tmp); } window->top_of_display = (Display *) 0; window->display_ip = (Display *) 0; window->display_size = 0; } static void free_nicks(window) Window *window; { NickList *tmp, *next; for (tmp = window->nicks; tmp; tmp = next) { next = tmp->next; new_free(&(tmp->nick)); /**************************** PATCHED by Flier ******************************/ new_free(&(tmp->userhost)); /****************************************************************************/ new_free(&tmp); } } /* * erase_display: This effectively causes all members of the display list for * a window to be set to empty strings, thus "clearing" a window. It sets * the cursor to the top of the window, and the display insertion point to * the top of the display. Note, this doesn't actually refresh the screen, * just cleans out the display list */ void erase_display(window) Window *window; { int i; Display *tmp; if (dumb) return; if (window == (Window *) 0) window = curr_scr_win; for (tmp = window->top_of_display, i = 0; i < window->display_size; i++, tmp = tmp->next) new_free(&(tmp->line)); window->cursor = 0; window->line_cnt = 0; window->hold_on_next_rite = 0; window->display_ip = window->top_of_display; } static void remove_from_invisible_list(window) Window *window; { window->visible = 1; window->screen = current_screen; window->miscflags &= ~WINDOW_NOTIFIED; if (window->prev) window->prev->next = window->next; else invisible_list = window->next; if (window->next) window->next->prev = window->prev; } extern void add_to_invisible_list(window) Window *window; { if ((window->next = invisible_list) != NULL) invisible_list->prev = window; invisible_list = window; window->prev = (Window *) 0; window->visible = 0; window->screen = (Screen *) 0; } /* swap_channels_win_ptr: must be called because swap_window modifies the * content of *v_window and *window instead of swapping pointers */ static void swap_channels_win_ptr(v_window, window) Window *v_window, *window; { ChannelList *chan; if (v_window->server != -1) { for (chan = server_list[v_window->server].chan_list; chan; chan = chan->next) if (chan->window == v_window) chan->window = window; else if (chan->window == window) chan->window = v_window; } if (window->server == v_window->server) return; if (window->server != -1) for (chan = server_list[window->server].chan_list; chan; chan = chan->next) if (chan->window == window) chan->window = v_window; } /* * swap_window: This swaps the given window with the current window. The * window passed must be invisible. Swapping retains the positions of both * windows in their respective window lists, and retains the dimensions of * the windows as well, but update them depending on the number of status * lines displayed */ /**************************** PATCHED by Flier ******************************/ /*static void*/ void /****************************************************************************/ swap_window(v_window, window) Window *v_window; Window *window; { Window tmp, *prev, *next; int top, bottom, size; if (window->visible || !v_window->visible) { say("You can only SWAP a hidden window with a visible window."); return; } /**************************** Patched by Flier ******************************/ /* fix terminal resize bug with hidden windows */ if (window->display_size != v_window->display_size) window->display_size = v_window->display_size; /****************************************************************************/ swap_channels_win_ptr(v_window, window); prev = v_window->prev; next = v_window->next; current_screen->last_window_refnum = v_window->refnum; current_screen->last_window_refnum = v_window->refnum; remove_from_invisible_list(window); tmp = *v_window; *v_window = *window; v_window->top = tmp.top; v_window->bottom = tmp.bottom + tmp.double_status - v_window->double_status; v_window->display_size = tmp.display_size + tmp.menu.lines + tmp.double_status - #ifdef SCROLL_AFTER_DISPLAY v_window->menu.lines - v_window->double_status - 1; #else v_window->menu.lines - v_window->double_status; #endif /* SCROLL_AFTER_DISPLAY */ v_window->prev = prev; v_window->next = next; /* I don't understand the use of the following, I'll ignore it * If double status screws window sizes, I should look here * again - krys */ top = window->top; bottom = window->bottom; size = window->display_size; *window = tmp; window->top = top; window->bottom = bottom - tmp.double_status; #ifdef SCROLL_AFTER_DISPLAY window->display_size = size - 1; #else window->display_size = size; #endif /* SCROLL_AFTER_DISPLAY */ add_to_invisible_list(window); v_window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS; window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS; /**************************** PATCHED by Flier ******************************/ if (v_window && window && v_window->server!=window->server) tabnickcompl=NULL; /****************************************************************************/ do_hook(WINDOW_SWAP_LIST, "%d %d", v_window->refnum, window->refnum); } /* * move_window: This moves a window offset positions in the window list. This * means, of course, that the window will move on the screen as well */ static void move_window(window, offset) Window *window; int offset; { Window *tmp, *last; int win_pos, pos; if (offset == 0) return; last = (Window *) 0; for (win_pos = 0, tmp = current_screen->window_list; tmp; tmp = tmp->next, win_pos++) { if (window == tmp) break; last = tmp; } if (tmp == (Window *) 0) return; if (last == (Window *) 0) current_screen->window_list = tmp->next; else last->next = tmp->next; if (tmp->next) tmp->next->prev = last; else current_screen->window_list_end = last; win_pos = (offset + win_pos) % window->screen->visible_windows; if (win_pos < 0) win_pos = window->screen->visible_windows + win_pos; last = (Window *) 0; for (pos = 0, tmp = current_screen->window_list; pos != win_pos; tmp = tmp->next, pos++) last = tmp; if (last == (Window *) 0) current_screen->window_list = window; else last->next = window; if (tmp) tmp->prev = window; else current_screen->window_list_end = window; window->prev = last; window->next = tmp; recalculate_window_positions(); } /* * grow_window: This will increase or descrease the size of the given window * by offset lines (positive offset increases, negative decreases). * Obviously, with a fixed terminal size, this means that some other window * is going to have to change size as well. Normally, this is the next * window in the window list (the window below the one being changed) unless * the window is the last in the window list, then the previous window is * changed as well */ static void grow_window(window, offset) Window *window; int offset; { Window *other, *tmp; int after, window_size, other_size; if (window == (Window *) 0) window = curr_scr_win; if (!window->visible) { say("You cannot change the size of hidden windows!"); return; } if (window->next) { other = window->next; after = 1; } else { other = (Window *) 0; for (tmp = current_screen->window_list; tmp; tmp = tmp->next) { if (tmp == window) break; other = tmp; } if (other == (Window *) 0) { say("Can't change the size of this window!"); return; } after = 0; } window_size = window->display_size + offset; other_size = other->display_size - offset; if ((window_size < 4) || (other_size < 4)) { say("Not enough room to resize this window!"); return; } if (after) { window->bottom += offset; other->top += offset; } else { window->top -= offset; other->bottom -= offset; } #ifdef SCROLL_AFTER_DISPLAY window->display_size = window_size - 1; other->display_size = other_size - 1; #else window->display_size = window_size; other->display_size = other_size; #endif /* SCROLL_AFTER_DISPLAY */ window->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS; other->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS; term_flush(); } /**************************** Patched by Flier ******************************/ /* * size_window: Set window size. See grow_window() for details. */ static void size_window(window,newsize) Window *window; int newsize; { if (!window) window=curr_scr_win; grow_window(window,newsize-window->display_size); } /****************************************************************************/ /* * the message_from stack structure. */ struct mfstack { char *who_from; /* saved from */ int who_level; /* saved level */ struct mfstack *next; /* next in the list */ } mfstack_head = { NULL, 0, NULL }; /* * save_message_from: this is used to save (for later restoration) the * who_from variable. This comes in handy very often when a routine might * call another routine that might change who_from. Note that if you * call this routine, you *must* call restore_message_from(). */ void save_message_from() { struct mfstack *mfs; mfs = (struct mfstack *)new_malloc(sizeof *mfs); mfs->who_from = NULL; malloc_strcpy(&(mfs->who_from), who_from); mfs->who_level = who_level; mfs->next = mfstack_head.next; mfstack_head.next = mfs; } /* restore_message_from: restores a previously saved who_from variable */ void restore_message_from() { struct mfstack *mfs = mfstack_head.next; if (mfs == NULL) { /*yell("--- restore_message_from: NULL next pointer, fudging..");*/ malloc_strcpy(&who_from, NULL); who_level = 0; } else { malloc_strcpy(&who_from, mfs->who_from); who_level = mfs->who_level; mfstack_head.next = mfs->next; new_free(&mfs->who_from); new_free(&mfs); } } /* * message_from: With this you can the who_from variable and the who_level * variable, used by the display routines to decide which window messages * should go to. */ void message_from(who, level) char *who; int level; { malloc_strcpy(&who_from, who); who_level = level; } /* * message_from_level: Like set_lastlog_msg_level, except for message_from. * this is needed by XECHO, because we could want to output things in more * than one level. */ int message_from_level(level) int level; { int temp; temp = who_level; who_level = level; return temp; } /* * get_window_by_refnum: Given a reference number to a window, this returns a * pointer to that window if a window exists with that refnum, null is * returned otherwise. The "safe" way to reference a window is throught the * refnum, since a window might be delete behind your back and and Window * pointers might become invalid. */ Window * get_window_by_refnum(refnum) u_int refnum; { Window *tmp; int flag = 1; if (refnum) { while ((tmp = traverse_all_windows(&flag)) != NULL) { if (tmp->refnum == refnum) return (tmp); } } else return (curr_scr_win); return ((Window *) 0); } /* * get_window_by_level: Given a level, this returns a pointer to that * window if a window exists with that level, null is returned otherwise. */ Window * get_window_by_level(level) u_int level; { Window *tmp; int flag=1; while ((tmp=traverse_all_windows(&flag))!=NULL) { if (((tmp->window_level)&level)==level) return(tmp); } return((Window *) 0); } /* * clear_window_by_refnum: just like clear_window(), but it uses a refnum. If * the refnum is invalid, the current window is cleared. */ void clear_window_by_refnum(refnum) u_int refnum; { Window *tmp; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; clear_window(tmp); } /* * revamp_window_levels: Given a level setting for the current window, this * makes sure that that level setting is unused by any other window. Thus * only one window in the system can be set to a given level. This only * revamps levels for windows with servers matching the given window * it also makes sure that only one window has the level `DCC', as this is * not dependant on a server. */ static void revamp_window_levels(window) Window *window; { Window *tmp; int flag = 1; int got_dcc; got_dcc = (LOG_DCC & window->window_level) ? 1 : 0; while ((tmp = traverse_all_windows(&flag)) != NULL) { if (tmp == window) continue; if (LOG_DCC & tmp->window_level) { if (0 != got_dcc) tmp->window_level &= ~LOG_DCC; got_dcc = 1; } if (window->server == tmp->server) tmp->window_level ^= (tmp->window_level & window->window_level); } } /* * set_level_by_refnum: This sets the window level given a refnum. It * revamps the windows levels as well using revamp_window_levels() */ void set_level_by_refnum(refnum, level) u_int refnum; int level; { Window *tmp; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; tmp->window_level = level; revamp_window_levels(tmp); } /* * set_prompt_by_refnum: changes the prompt for the given window. A window * prompt will be used as the target in place of the query user or current * channel if it is set */ void set_prompt_by_refnum(refnum, prompt) u_int refnum; char *prompt; { Window *tmp; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; malloc_strcpy(&(tmp->prompt), prompt); } /* * message_to: This allows you to specify a window (by refnum) as a * destination for messages. Used by EXEC routines quite nicely */ void message_to(refnum) u_int refnum; { if (refnum) to_window = get_window_by_refnum(refnum); else to_window = (Window *) NULL; } /* * get_next_window: This returns a pointer to the next *visible* window in * the window list. It automatically wraps at the end of the list back to * the beginning of the list */ static Window * get_next_window() { if (curr_scr_win && curr_scr_win->next) return (curr_scr_win->next); else return (current_screen->window_list); } /* * get_previous_window: this returns the previous *visible* window in the * window list. This automatically wraps to the last window in the window * list */ static Window * get_previous_window() { if (curr_scr_win && curr_scr_win->prev) return (curr_scr_win->prev); else return (current_screen->window_list_end); } /* * set_current_window: This sets the "current" window to window. It also * keeps track of the last_current_screen->current_window by setting it to the * previous current window. This assures you that the new current window is * visible. * If not, a new current window is chosen from the window list */ void set_current_window(window) Window *window; { Window *tmp; unsigned int refnum; /**************************** PATCHED by Flier ******************************/ Window *oldcurw=curr_scr_win; /****************************************************************************/ refnum = current_screen->last_window_refnum; if (curr_scr_win) { curr_scr_win->update |= UPDATE_STATUS; current_screen->last_window_refnum = curr_scr_win->refnum; } if ((window == (Window *) 0) || (!window->visible)) { if ((tmp = get_window_by_refnum(refnum)) && (tmp->visible)) curr_scr_win = tmp; else curr_scr_win = get_next_window(); } else curr_scr_win = window; curr_scr_win->update |= UPDATE_STATUS; /**************************** PATCHED by Flier ******************************/ if (curr_scr_win && oldcurw && curr_scr_win->server!=oldcurw->server) tabnickcompl=NULL; /****************************************************************************/ } /* * swap_last_window: This swaps the current window with the last window * that was hidden. */ void swap_last_window(key, ptr) u_int key; char * ptr; { if (invisible_list == (Window *) 0) { /* say("There are no hidden windows"); */ /* Not sure if we need to warn - phone. */ return; } swap_window(curr_scr_win, invisible_list); update_all_windows(); cursor_to_input(); } /* * next_window: This switches the current window to the next visible window */ void next_window(key, ptr) u_int key; char * ptr; { if (current_screen->visible_windows == 1) return; set_current_window(get_next_window()); update_all_windows(); } /* * swap_next_window: This swaps the current window with the next hidden * window. */ void swap_next_window(key, ptr) u_int key; char * ptr; { int flag; Window *tmp; u_int next = MAXINT; int smallest; if (invisible_list == (Window *) 0) { say("There are no hidden windows"); return; } flag = 1; smallest = curr_scr_win->refnum; while ((tmp = traverse_all_windows(&flag)) != NULL) { if (!tmp->visible) { if (tmp->refnum < smallest) smallest = tmp->refnum; if ((tmp->refnum > curr_scr_win->refnum) && (next > tmp->refnum)) next = tmp->refnum; } } if (next != MAXINT) tmp = get_window_by_refnum(next); else tmp = get_window_by_refnum((u_int)smallest); swap_window(curr_scr_win, tmp); update_all_windows(); update_all_status(); cursor_to_input(); } /* * previous_window: This switches the current window to the previous visible * window */ void previous_window(key, ptr) u_int key; char * ptr; { if (current_screen->visible_windows == 1) return; set_current_window(get_previous_window()); update_all_windows(); } /* * swap_previous_window: This swaps the current window with the next * hidden window. */ void swap_previous_window(key, ptr) u_int key; char * ptr; { int flag; Window *tmp; int previous = 0; int largest; if (invisible_list == (Window *) 0) { say("There are no hidden windows"); return; } flag = 1; largest = curr_scr_win->refnum; while ((tmp = traverse_all_windows(&flag)) != NULL) { if (!tmp->visible) { if (tmp->refnum > largest) largest = tmp->refnum; if ((tmp->refnum < curr_scr_win->refnum) && (previous < tmp->refnum)) previous = tmp->refnum; } } if (previous) tmp = get_window_by_refnum((u_int)previous); else tmp = get_window_by_refnum((u_int)largest); swap_window(curr_scr_win,tmp); update_all_windows(); update_all_status(); cursor_to_input(); } /* * back_window: goes to the last window that was current. Swapping the * current window if the last window was hidden. */ void back_window(key, ptr) u_int key; char * ptr; { Window *tmp; tmp = get_window_by_refnum(current_screen->last_window_refnum); /**************************** PATCHED by Flier ******************************/ /* tmp is NULL after we do /WINDOW KILL */ if (!tmp) return; /****************************************************************************/ if (tmp->visible) set_current_window(tmp); else { swap_window(curr_scr_win, tmp); update_all_windows(); update_all_status(); cursor_to_input(); } } /* * add_to_window_list: This inserts the given window into the visible window * list (and thus adds it to the displayed windows on the screen). The * window is added by splitting the current window. If the current window is * too small, the next largest window is used. The added window is returned * as the function value or null is returned if the window couldn't be added */ extern Window * add_to_window_list(new) Window *new; { Window *biggest = (Window *) 0, *tmp; current_screen->visible_windows++; if (curr_scr_win == (Window *) 0) { current_screen->window_list_end = current_screen->window_list = new; if (dumb) { #ifdef SCROLL_AFTER_DISPLAY new->display_size = 24 - 1; #else new->display_size = 24; /* what the hell */ #endif /* SCROLL_AFTER_DISPLAY */ set_current_window(new); return (new); } recalculate_windows(); } else { /* split current window, or find a better window to split */ if ((curr_scr_win->display_size < 4) || get_int_var(ALWAYS_SPLIT_BIGGEST_VAR)) { int size = 0; for (tmp = current_screen->window_list; tmp; tmp = tmp->next) { if (tmp->display_size > size) { size = tmp->display_size; biggest = tmp; } } if ((biggest == (Window *) 0) || (size < 4)) { say("Not enough room for another window!"); /* Probably a source of memory leaks */ new_free(&new); current_screen->visible_windows--; return ((Window *) 0); } } else biggest = curr_scr_win; if ((new->prev = biggest->prev) != NULL) new->prev->next = new; else current_screen->window_list = new; new->next = biggest; biggest->prev = new; new->top = biggest->top; new->bottom = (biggest->top + biggest->bottom) / 2 - new->double_status; biggest->top = new->bottom + new->double_status + 1; #ifdef SCROLL_AFTER_DISPLAY new->display_size = new->bottom - new->top - 1; biggest->display_size = biggest->bottom - biggest->top - biggest->menu.lines - 1; #else new->display_size = new->bottom - new->top; biggest->display_size = biggest->bottom - biggest->top - biggest->menu.lines; #endif /* SCROLL_AFTER_DISPLAY */ new->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS; biggest->update |= REDRAW_DISPLAY_FULL | REDRAW_STATUS; } return (new); } /* * remove_from_window_list: this removes the given window from the list of * visible windows. It closes up the hole created by the windows absense in * a nice way */ static void remove_from_window_list(window) Window *window; { Window *other; /* find adjacent visible window to close up the screen */ for (other = window->next; other; other = other->next) { if (other->visible) { other->top = window->top; break; } } if (other == (Window *) 0) { for (other = window->prev; other; other = other->prev) { if (other->visible) { other->bottom = window->bottom + window->double_status - other->double_status; break; } } } /* remove window from window list */ if (window->prev) window->prev->next = window->next; else current_screen->window_list = window->next; if (window->next) window->next->prev = window->prev; else current_screen->window_list_end = window->prev; if (window->visible) { current_screen->visible_windows--; #ifdef SCROLL_AFTER_DISPLAY other->display_size = other->bottom - other->top - other->menu.lines - 1; #else other->display_size = other->bottom - other->top - other->menu.lines; #endif /* SCROLL_AFTER_DISPLAY */ if (window == curr_scr_win) set_current_window((Window *) 0); if (window->refnum == current_screen->last_window_refnum) current_screen->last_window_refnum = curr_scr_win->refnum; } } /* * window_check_servers: this checks the validity of the open servers vs the * current window list. Every open server must have at least one window * associated with it. If a window is associated with a server that's no * longer open, that window's server is set to the primary server. If an * open server has no assicatiate windows, that server is closed. If the * primary server is no more, a new primary server is picked from the open * servers */ void window_check_servers() { Window *tmp; int flag, cnt, max, i, not_connected, prime = -1; connected_to_server = 0; max = number_of_servers; for (i = 0; i < max; i++) { not_connected = !is_server_open(i); flag = 1; cnt = 0; while ((tmp = traverse_all_windows(&flag)) != NULL) { if (tmp->server == i) { if (not_connected) { tmp->server = primary_server; if (tmp->current_channel) new_free(&tmp->current_channel); } else { prime = tmp->server; cnt++; } } } if (cnt == 0) { #ifdef NON_BLOCKING_CONNECTS if (!(server_list[i].flags & CLOSE_PENDING)) #endif /* NON_BLOCKING_CONNECTS */ close_server(i, empty_string); } else connected_to_server++; } if (!is_server_open(primary_server)) { flag = 1; while ((tmp = traverse_all_windows(&flag)) != NULL) if (tmp->server == primary_server) { tmp->server = prime; } primary_server = prime; } update_all_status(); cursor_to_input(); } /* * restore_previous_server: Attempts to restore all windows that were * associated with `server', that currently contain nothing, to said * server. */ void window_restore_server(server) int server; { Window *tmp; int max = number_of_servers, i, flag = 1; for (i = 0; i < max; i++) { while ((tmp = traverse_all_windows(&flag)) != NULL) { if (tmp->server == primary_server && tmp->prev_server == server) { int t = tmp->server; tmp->server = tmp->prev_server; tmp->prev_server = t; realloc_channels(tmp); } } } } /* * realloc_channels: Attempts to reallocate a channel to a window of the * same server * * XXX mrg this looks broken to me but i'm not sure. blah. */ static void realloc_channels(window) Window *window; { Window *tmp; int flag = 1; ChannelList *chan; while ((tmp = traverse_all_windows(&flag))) if (window != tmp && tmp->server == window->server) { /**************************** Patched by Flier ******************************/ /* unset IRCSERVER * scrollz * /window new * /window kill * client dies */ if (window->server < 0) continue; /****************************************************************************/ for (chan = server_list[window->server].chan_list; chan; chan = chan->next) if (chan->window == window) { chan->window = tmp; if (!tmp->current_channel) set_channel_by_refnum(tmp->refnum, chan->channel); } return; } /**************************** Patched by Flier ******************************/ if (window->server < 0) return; /****************************************************************************/ for (chan = server_list[window->server].chan_list; chan; chan = chan->next) { chan->window = (Window *) 0; } } /* * delete_window: This deletes the given window. It frees all data and * structures associated with the window, and it adjusts the other windows so * they will display correctly on the screen. */ void delete_window(window) Window *window; { char *tmp = (char *) 0; char buffer[BIG_BUFFER_SIZE+1]; if (window == (Window *) 0) window = curr_scr_win; if (window->visible && (current_screen->visible_windows == 1)) { if (invisible_list) { swap_window(window, invisible_list); window = invisible_list; } else { say("You can't kill the last window!"); return; } } if (window->name) strmcpy(buffer, window->name, BIG_BUFFER_SIZE); else snprintf(buffer, sizeof buffer, "%u", window->refnum); malloc_strcpy(&tmp, buffer); realloc_channels(window); /**************************** PATCHED by Flier ******************************/ #if defined(OPERVISION) && defined(WANTANSI) if (OperV && !strcmp(buffer,"OV")) OperV=0; #endif /****************************************************************************/ new_free(&window->status_line[0]); new_free(&window->status_line[1]); /**************************** PATCHED by Flier ******************************/ new_free(&window->status_line[2]); /****************************************************************************/ new_free(&window->query_nick); new_free(&window->current_channel); new_free(&window->logfile); new_free(&window->name); free_display(window); free_hold(window); free_lastlog(window); free_nicks(window); if (window->visible) remove_from_window_list(window); else remove_from_invisible_list(window); new_free(&window); window_check_servers(); do_hook(WINDOW_KILL_LIST, "%s", tmp); new_free(&tmp); } /**************************** PATCHED by Flier ******************************/ /* * cleanup_window: This deletes the given window. It frees all data and * structures associated with the window. */ void cleanup_window(window) Window *window; { new_free(&window->status_line[0]); new_free(&window->status_line[1]); new_free(&window->status_line[2]); new_free(&window->query_nick); new_free(&window->current_channel); new_free(&window->logfile); new_free(&window->name); if (window->top_of_display) free_display(window); free_hold(window); free_lastlog(window); free_nicks(window); new_free(&window); } /****************************************************************************/ /* delete_other_windows: zaps all visible windows except the current one */ static void delete_other_windows() { Window *tmp, *cur, *next; cur = curr_scr_win; tmp = current_screen->window_list; while (tmp) { next = tmp->next; if (tmp != cur) { delete_window(tmp); update_all_windows(); } tmp = next; } } /* * window_kill_swap: Swaps with the last window that was hidden, then * kills the window that was swapped. Give the effect of replacing the * current window with the last one, and removing it at the same time. */ void window_kill_swap() { if (invisible_list != (Window *) 0) { swap_last_window(0, (char *) 0); delete_window(get_window_by_refnum(current_screen->last_window_refnum)); } else say("There are no hidden windows!"); } /* * unhold_windows: This is used by the main io loop to display held * information at an appropriate time. Each time this is called, each * windows hold list is checked. If there is info in the hold list and the * window is not held, the first line is displayed and removed from the hold * list. Zero is returned if no infomation is displayed */ int unhold_windows() { Window *tmp; char *stuff; int hold_flag = 0, flag = 1; int logged; while ((tmp = traverse_all_windows(&flag)) != NULL) { if (!hold_output(tmp) && (stuff = hold_queue(tmp))) { logged = hold_queue_logged(tmp); if (rite(tmp, stuff, 1, 0, 0, logged) == 0) { remove_from_hold_list(tmp); hold_flag = 1; } } } return (hold_flag); } /* * update_window_status: This updates the status line for the given window. * If the refresh flag is true, the entire status line is redrawn. If not, * only some of the changed portions are redrawn */ void update_window_status(window, refreshit) Window *window; int refreshit; { if (dumb || (!window->visible) || !status_update_flag || never_connected) return; if (window == (Window *) 0) window = curr_scr_win; if (refreshit) { new_free(&window->status_line[0]); new_free(&window->status_line[1]); /**************************** PATCHED by Flier ******************************/ new_free(&window->status_line[2]); /****************************************************************************/ } make_status(window); } /* * redraw_all_status: This redraws all of the status lines for all of the * windows. */ void redraw_all_status() { Window *tmp; if (dumb) return; for (tmp = current_screen->window_list; tmp; tmp = tmp->next) { new_free(&tmp->status_line[0]); new_free(&tmp->status_line[1]); /**************************** PATCHED by Flier ******************************/ new_free(&tmp->status_line[2]); /****************************************************************************/ make_status(tmp); } update_input(UPDATE_JUST_CURSOR); term_flush(); } /* * update_all_status: This updates all of the status lines for all of the * windows. By updating, it only draws from changed portions of the status * line to the right edge of the screen */ /*ARGSUSED*/ void update_all_status() { Window *window; Screen *screen; if (dumb || !status_update_flag || never_connected) return; for (screen = screen_list; screen; screen = screen->next) { if (!screen->alive) continue; for (window = screen->window_list;window; window = window->next) if (window->visible) make_status(window); } update_input(UPDATE_JUST_CURSOR); term_flush(); } /* * status_update: sets the status_update_flag to whatever flag is. This also * calls update_all_status(), which will update the status line if the flag * was true, otherwise it's just ignored */ void status_update(flag) int flag; { status_update_flag = flag; update_all_status(); cursor_to_input(); } /* * is_current_channel: Returns true is channel is a current channel for any * window. If the delete flag is not 0, then unset channel as the current * channel and attempt to replace it by a non-current channel or the * current_channel of window specified by value of delete */ int is_current_channel(channel, server, delete) char *channel; int server; int delete; { Window *tmp, *found_window = (Window *) 0; int found = 0, flag = 1; /**************************** PATCHED by Flier ******************************/ if (!channel) { found=1; found_window=curr_scr_win; delete=curr_scr_win->refnum; channel=""; } else /****************************************************************************/ while ((tmp = traverse_all_windows(&flag)) != NULL) { char * c = tmp->current_channel; if (c && !my_stricmp(channel, c) && tmp->server == server) { found_window = tmp; found = 1; if (delete) { new_free(&(tmp->current_channel)); tmp->update |= UPDATE_STATUS; } } } if (found && delete) { ChannelList *chan; char *delete_channel; ChannelList *possible = (ChannelList *) 0; for (chan = server_list[server].chan_list; chan; chan = chan->next) { if (!my_stricmp(chan->channel, channel)) continue; if (chan->window == found_window) { set_channel_by_refnum(found_window->refnum, chan->channel); return 1; } if (!get_int_var(SAME_WINDOW_ONLY_VAR)) if (!is_bound(chan->channel, server) && (chan->window != found_window)) { int is_current = 0; flag = 1; while ((tmp = traverse_all_windows(&flag))) { if ((tmp->server != server)) continue; if (tmp->current_channel && !my_stricmp(chan->channel, tmp->current_channel)) is_current = 1; } if (!is_current) possible = chan; } } if (!get_int_var(SAME_WINDOW_ONLY_VAR)) { if (possible) { set_channel_by_refnum(found_window->refnum, possible->channel); return 1; } delete_channel = get_channel_by_refnum((u_int)delete); if (delete_channel && !(is_bound(delete_channel, server) && found_window->refnum != delete)) set_channel_by_refnum(found_window->refnum, get_channel_by_refnum((u_int)delete)); } } return (found); } extern Window * is_bound(channel, server) char *channel; int server; { Win_Trav stuff; Window *tmp; stuff.flag = 1; while ((tmp = window_traverse(&stuff))) { /**************************** PATCHED by Flier ******************************/ /*if (tmp->server == server && tmp->bound_channel && !my_stricmp(channel, tmp->bound_channel)) return tmp;*/ if (tmp->server==server) { if (find_in_list((List **) &(tmp->bound_chans), channel, 0)) return(tmp); } /****************************************************************************/ } return (Window *) 0; } static void bind_channel(channel, window) char *channel; Window *window; { Win_Trav stuff; Window *tmp; /**************************** PATCHED by Flier ******************************/ char tmpbuf[mybufsize / 2 + 1]; struct channels *chan; /****************************************************************************/ /* check it isn't bound on this server elsewhere */ stuff.flag = 1; while ((tmp = window_traverse(&stuff))) { if (tmp->server != window->server && tmp == window) continue; /**************************** PATCHED by Flier ******************************/ /*if (!my_stricmp(tmp->bound_channel, channel))*/ chan=(struct channels *) find_in_list((List **) &(tmp->bound_chans), channel, 0); if (chan) /****************************************************************************/ { /**************************** PATCHED by Flier ******************************/ /*say("Channel %s is already bound to window %d", channel, window->refnum);*/ if (window->name) strmcpy(tmpbuf, window->name, sizeof(tmpbuf) - 1); else snprintf(tmpbuf, sizeof(tmpbuf), "%d", window->refnum); say("Channel %s is already bound to window %s", channel, tmpbuf); /****************************************************************************/ return; } } if (is_on_channel(channel, window->server, get_server_nickname(window->server))) { is_current_channel(channel, window->server, (int)window->refnum); set_channel_by_refnum(0, channel); } /* XXX fix this */ #if 0 else { int server, sg = -1, fsg = -2; /* different */ server = from_server; from_server = window->server; if (server_list[server].server_group) sg = find_server_group(server_list[server].server_group, 0); if (server_list[from_server].server_group) fsg = find_server_group(server_list[server].server_group, 0); if (sg == 0 || fsg == 0) yell("--- huh. coudn't find server groups"); if (sg == fsg) { switch (get_server_version(window->server)) { case ServerICB: icb_put_group(channel); break; /* XXX make this use a key? */ /* XXX by factoring out the "JOIN/CHANNEL" code to a module */ case Server2_5: send_to_server("CHANNEL %s", channel); break; default: send_to_server("JOIN %s", channel); } add_channel(channel, from_server, CHAN_JOINING, (ChannelList *) 0); from_server = server; } } #endif /**************************** PATCHED by Flier ******************************/ /*malloc_strcpy(&window->bound_channel, channel); say("Channel %s bound to window %d", channel, window->refnum);*/ chan = (struct channels *) new_malloc(sizeof(struct channels)); chan->channel = NULL; malloc_strcpy(&(chan->channel),channel); chan->next = NULL; add_to_list_ext((List **) &(window->bound_chans), (List *) chan, (int (*) _((List *, List *))) AddLast); if (window->name) strmcpy(tmpbuf, window->name, sizeof(tmpbuf) - 1); else snprintf(tmpbuf, sizeof(tmpbuf), "%d", window->refnum); say("Channel %s bound to window %s", channel, tmpbuf); /****************************************************************************/ } static void unbind_channel(channel, window) char *channel; Window *window; { /**************************** PATCHED by Flier ******************************/ struct channels *chan; /****************************************************************************/ window = is_bound(channel, window->server); if (!window) return; /**************************** PATCHED by Flier ******************************/ /*new_free(&window->bound_channel);*/ chan=(struct channels *) remove_from_list((List **) &(window->bound_chans), channel); if (chan) { new_free(&(chan->channel)); new_free(&chan); } /****************************************************************************/ } /* * get_window_server: returns the server index for the window with the given * refnum */ int get_window_server(refnum) unsigned int refnum; { Window *tmp; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; return (tmp->server); } /* * window_set_server: This sets the server of the given window to server. * If refnum is -1 then we are setting the primary server and all windows * that are set to the current primary server are changed to server. The misc * flag is ignored in this case. If refnum is not -1, then that window is * set to the given server. If WIN_ALL is set in misc, then all windows * with the same server as refnum are set to the new server as well. * If the window is in a group, all the group is set to the new server. * WIN_TRANSFER will move the channels to the new server, WIN_FORCE will * force a 'sticky' behaviour of the window. -Sol */ void window_set_server(refnum, server, misc) int refnum; int server; int misc; { int old_serv; Window *window = 0, *ptr, *new_win = (Window *) 0; ChannelList *tmp; int moved = 0; int flag = 1; if (refnum == -1) { old_serv = primary_server; primary_server = server; misc |= WIN_ALL; } else { window = get_window_by_refnum((u_int)refnum); old_serv = window->server; } if (server == old_serv) return; /* Moving all windows associated with old_serv -Sol */ if (misc & WIN_ALL) { if ((misc & WIN_TRANSFER) && (old_serv >= 0)) { /**************************** PATCHED by Flier ******************************/ /* Don't transfer channels if WIN_OLDCONN is set here * because it means connection to old server failed * and if we transfer channels we lose information * on nicks in channels! */ if (misc&WIN_OLDCONN) /****************************************************************************/ for (tmp = server_list[old_serv].chan_list; tmp; tmp = tmp->next) { /* XXX: moved is always 0 at this point */ if (!moved) /* If we're here, it means we're going to transfer channels to the new server, so we dump old channels first, but only once -Sol */ { moved++; clear_channel_list(server); } /**************************** Patched by Flier ******************************/ /*add_channel(tmp->channel, server, CHAN_LIMBO, tmp);*/ add_channel(tmp->channel, server, CHAN_LIMBO, tmp, NULL, 0); /****************************************************************************/ } #ifdef NON_BLOCKING_CONNECTS if (server_list[old_serv].flags & CLOSE_PENDING) server_list[old_serv].flags |= CLEAR_PENDING; else #endif /* NON_BLOCKING_CONNECTS */ clear_channel_list(old_serv); } while ((ptr = traverse_all_windows(&flag)) != (Window *) 0) if (ptr->server == old_serv) { ptr->prev_server = ptr->server; ptr->server = server; /* * XXX we could save this to old_current_channel and use * that after other checks to decide where a channel should * go, maybe?? */ if (ptr->current_channel) new_free(&ptr->current_channel); } window_check_servers(); return; } /* * We are setting only some windows of the old server : let's look * for a window of that server that is not being moved. * refnum == -1 has been dealt with above so window is defined. -Sol */ flag = 1; while ((ptr = traverse_all_windows(&flag)) != (Window *) 0) if ((ptr != window) && (!ptr->server_group || (ptr->server_group != window->server_group)) && (ptr->server == old_serv)) { /* Possible relocation -Sol */ new_win = ptr; /* Immediately retain window if no group -Sol */ if (!ptr->server_group) break; } /* No relocation : we're closing last windows for old_serv -Sol */ if (!new_win) { window_set_server(refnum, server, misc | WIN_ALL); return; } /* * Now that we know that server still has at least one window open, * move what we're supposed to -Sol */ if ((misc & WIN_TRANSFER) && (old_serv >= 0)) for (tmp = server_list[old_serv].chan_list; tmp; tmp = tmp->next) if ((tmp->window == window) || (window->server_group && (tmp->window->server_group == window->server_group))) { /* Found a channel to be relocated -Sol */ if (tmp->window->sticky || (misc & WIN_FORCE)) { /* This channel moves -Sol */ int old = from_server; if (!moved) { moved++; clear_channel_list(server); } /**************************** Patched by Flier ******************************/ /*add_channel(tmp->channel, server, CHAN_LIMBO, tmp);*/ /* Copy it -Sol */ add_channel(tmp->channel, server, CHAN_LIMBO, tmp, NULL, 0); /****************************************************************************/ from_server = old_serv; /* On old_serv, leave it -Sol */ send_to_server("PART %s", tmp->channel); from_server = old; remove_channel(tmp->channel, old_serv); } else tmp->window = new_win; } flag = 1; while ((ptr = traverse_all_windows(&flag)) != (Window *) 0) if ((ptr == window) || (ptr->server_group && (ptr->server_group == window->server_group))) { ptr->server = server; if (ptr->current_channel) new_free(&ptr->current_channel); } window_check_servers(); } /* * set_channel_by_refnum: This sets the current channel for the current * window. It returns the current channel as it's value. If channel is null, * the * current channel is not changed, but simply reported by the function * result. This treats as a special case setting the current channel to * channel "0". This frees the current_channel for the * current_screen->current_window, * setting it to null */ char * set_channel_by_refnum(refnum, channel) unsigned int refnum; char *channel; { Window *tmp; Window *tmp2; Win_Trav stuff; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; if (channel && strcmp(channel, irczero) == 0) channel = (char *) 0; stuff.flag = 1; while ((tmp2 = window_traverse(&stuff))) if (tmp2->server == tmp->server && my_stricmp(tmp2->current_channel, channel) == 0) new_free(&tmp2->current_channel); malloc_strcpy(&tmp->current_channel, channel); tmp->update |= UPDATE_STATUS; set_channel_window(tmp, channel, tmp->server); return (channel); } /* get_channel_by_refnum: returns the current channel for window refnum */ char * get_channel_by_refnum(refnum) u_int refnum; { Window *tmp; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; return (tmp->current_channel); } /* current_refnum: returns the reference number for the current window */ unsigned int current_refnum() { return (curr_scr_win->refnum); } /* query_nick: Returns the query nick for the current channel */ char * query_nick() { return (curr_scr_win->query_nick); } /* get_prompt_by_refnum: returns the prompt for the given window refnum */ char * get_prompt_by_refnum(refnum) u_int refnum; { Window *tmp; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; if (tmp->prompt) return (tmp->prompt); else return (empty_string); } /* * get_target_by_refnum: returns the target for the window with the given * refnum (or for the current window). The target is either the query nick * or current channel for the window */ char * get_target_by_refnum(refnum) u_int refnum; { Window *tmp; if ((tmp = get_window_by_refnum(refnum)) == (Window *) 0) tmp = curr_scr_win; if (tmp->query_nick) return (tmp->query_nick); else if (tmp->current_channel) return (tmp->current_channel); else return ((char *) 0); } /* set_query_nick: sets the query nick for the current channel to nick */ void set_query_nick(nick) char *nick; { char *ptr; NickList *tmp; if (curr_scr_win->query_nick) { char *oldnick; oldnick = curr_scr_win->query_nick; while (oldnick) { if ((ptr = (char *) index(oldnick,',')) != NULL) *(ptr++) = '\0'; if ((tmp = (NickList *) remove_from_list((List **) &(curr_scr_win->nicks), oldnick)) != NULL) { new_free(&tmp->nick); /**************************** PATCHED by Flier ******************************/ new_free(&tmp->userhost); /****************************************************************************/ new_free(&tmp); } oldnick = ptr; } new_free(&curr_scr_win->query_nick); } if (nick) { malloc_strcpy(&(curr_scr_win->query_nick), nick); curr_scr_win->update |= UPDATE_STATUS; while (nick) { if ((ptr = (char *) index(nick,',')) != NULL) *(ptr++) = '\0'; tmp = (NickList *) new_malloc(sizeof(NickList)); tmp->nick = (char *) 0; /**************************** PATCHED by Flier ******************************/ tmp->userhost=(char *) 0; /****************************************************************************/ malloc_strcpy(&tmp->nick, nick); add_to_list((List **) &(curr_scr_win->nicks), (List *) tmp); nick = ptr; } } update_window_status(curr_scr_win,0); } /* * irc_goto_window: This will switch the current window to the window numbered * "which", where which is 0 through the number of visible windows on the * screen. The which has nothing to do with the windows refnum. */ /**************************** PATCHED by Flier ******************************/ /*static void*/ void /****************************************************************************/ irc_goto_window(which) int which; { Window *tmp; int i; if (which == 0) return; if ((which < 0) || (which > current_screen->visible_windows)) { say("GOTO: Illegal value"); return; } tmp = current_screen->window_list; for (i = 1; tmp && (i != which); tmp = tmp->next, i++) ; set_current_window(tmp); } /* * hide_window: sets the given window to invisible and recalculates remaing * windows to fill the entire screen */ static void hide_window(window) Window *window; { if (current_screen->visible_windows == 1) { say("You can't hide the last window."); return; } if (window->visible) { remove_from_window_list(window); add_to_invisible_list(window); #ifdef SCROLL_AFTER_DISPLAY /**************************** PATCHED by Flier ******************************/ /*#ifdef SCROLL_AFTER_DISPLAY window->display_size = current_screen->li - 3; #else window->display_size = current_screen->li - 2;*/ window->display_size = current_screen->li - 3 - window->double_status; #else window->display_size = current_screen->li - 2 - window->double_status; /****************************************************************************/ #endif /* SCROLL_AFTER_DISPLAY */ set_current_window((Window *) 0); } } /* hide_other_windows: makes all visible windows but the current one hidden */ static void hide_other_windows() { Window *tmp, *cur, *next; cur = curr_scr_win; tmp = current_screen->window_list; while (tmp) { next = tmp->next; if (tmp != cur) hide_window(tmp); tmp = next; } } #define WIN_FORM "%%-4s %%-%u.%us %%-%u.%us %%-%u.%us %%-9.9s %%-10.10s %%s%%s" static void list_a_window(window, len, clen) Window *window; int len; int clen; { char tmp[10]; char buffer[BIG_BUFFER_SIZE+1]; snprintf(tmp, sizeof tmp, "%-4u", window->refnum); snprintf(buffer, sizeof buffer, WIN_FORM, 9, 9, len, /* XXX: 9 is old NICKNAME_LEN */ len, clen, clen); /**************************** PATCHED by Flier ******************************/ /*say(buffer, tmp, get_server_nickname(window->server), window->name?window->name:"", window->current_channel ? window->current_channel : "", window->query_nick ? window->query_nick : "", window->server != -1 ? get_server_itsname(window->server) : "", bits_to_lastlog_level(window->window_level), (window->visible) ? "" : " Hidden");*/ say(buffer, tmp, get_server_nickname(window->server), window->name?window->name:"None", window->current_channel ? window->current_channel : "None", window->query_nick ? window->query_nick : "None", window->server != -1 ? get_server_itsname(window->server) : "None", bits_to_lastlog_level(window->window_level), (window->visible) ? "" : " Hidden"); /****************************************************************************/ } /* * list_windows: This Gives a terse list of all the windows, visible or not, * by displaying their refnums, current channel, and current nick */ static void list_windows() { Window *tmp; char buffer[BIG_BUFFER_SIZE+1]; int flag = 1; int len = 4; int clen = get_int_var(CHANNEL_NAME_WIDTH_VAR); int check_clen = clen == 0; while ((tmp = traverse_all_windows(&flag)) != NULL) { if (tmp->name && ((int) strlen(tmp->name) > len)) len = strlen(tmp->name); if (check_clen == 0) continue; if (tmp->current_channel && ((int) strlen(tmp->current_channel) > clen)) clen = strlen(tmp->current_channel); } snprintf(buffer, sizeof buffer, WIN_FORM, 9, 9, len, len, /* XXX: 9 is old NICKNAME_LEN */ clen, clen); say(buffer, "Ref", "Nick", "Name", "Channel", "Query", "Server", "Level", empty_string); flag = 1; while ((tmp = traverse_all_windows(&flag)) != NULL) list_a_window(tmp, len, clen); } /* show_window: This makes the given window visible. */ static void show_window(window) Window *window; { if (window->visible) { set_current_window(window); return; } remove_from_invisible_list(window); if (add_to_window_list(window)) set_current_window(window); else add_to_invisible_list(window); } /* push_window_by_refnum: This pushes the given refnum onto the window stack */ #ifndef LITE static void push_window_by_refnum(refnum) u_int refnum; { WindowStack *new; new = (WindowStack *) new_malloc(sizeof(WindowStack)); new->refnum = refnum; new->next = current_screen->window_stack; current_screen->window_stack = new; } /* * pop_window: this pops the top entry off the window stack and sets the * current window to that window. If the top of the window stack is no * longer a valid window, then that entry is discarded and the next entry * down is tried (as so on). If the stack is empty, the current window is * left unchanged */ static void pop_window() { int refnum; WindowStack *tmp; Window *win; while (1) { if (current_screen->window_stack) { refnum = current_screen->window_stack->refnum; tmp = current_screen->window_stack->next; new_free(¤t_screen->window_stack); current_screen->window_stack = tmp; if ((win = get_window_by_refnum((u_int)refnum)) != NULL) { if (!win->visible) show_window(win); else set_current_window(win); break; } } else { say("The window stack is empty!"); break; } } } /* * show_stack: displays the current window stack. This also purges out of * the stack any window refnums that are no longer valid */ static void show_stack() { WindowStack *last = (WindowStack *) 0, *tmp, *crap; Window *win; int flag = 1; int len = 4; int clen = get_int_var(CHANNEL_NAME_WIDTH_VAR); int check_clen = clen == 0; while ((win = traverse_all_windows(&flag)) != NULL) { if (win->name && ((int) strlen(win->name) > len)) len = strlen(win->name); if (check_clen == 0) continue; if (win->current_channel && ((int) strlen(win->current_channel) > clen)) clen = strlen(win->current_channel); } say("Window stack:"); tmp = current_screen->window_stack; while (tmp) { if ((win = get_window_by_refnum(tmp->refnum)) != NULL) { list_a_window(win, len, clen); tmp = tmp->next; } else { crap = tmp->next; new_free(&tmp); if (last) last->next = crap; else current_screen->window_stack = crap; tmp = crap; } } } #endif /* * is_window_name_unique: checks the given name vs the names of all the * windows and returns true if the given name is unique, false otherwise */ static int is_window_name_unique(name) char *name; { Window *tmp; int flag = 1; if (name) { while ((tmp = traverse_all_windows(&flag)) != NULL) { if (tmp->name && (my_stricmp(tmp->name, name) == 0)) return (0); } } return (1); } /* * add_nicks_by_refnum: This adds the given str to the nicklist of the * window refnum. Only unique names are added to the list. If add is zero * or the name is preceeded by a ^ it is removed from the list. The str * may be a comma separated list of nicks, channels, etc . */ static void add_nicks_by_refnum(refnum, str, add) u_int refnum; char *str; int add; { Window *tmp; char *ptr; NickList *new; if ((tmp = get_window_by_refnum(refnum)) != NULL) { while (str) { if ((ptr = (char *) index(str, ',')) != NULL) *(ptr++) = '\0'; if (add == 0 || *str == '^') { if (add == 0 && *str == '^') str++; if ((new = (NickList *) remove_from_list((List **) &(tmp->nicks), str)) != NULL) { say("%s removed from window name list", new->nick); new_free(&new->nick); /**************************** PATCHED by Flier ******************************/ new_free(&new->userhost); /****************************************************************************/ new_free(&new); } else say("%s is not on the list for this window!", str); } else { if (!find_in_list((List **) &(tmp->nicks), str, !USE_WILDCARDS)) { /**************************** PATCHED by Flier ******************************/ /*say("%s add to window name list", str);*/ say("%s added to window name list", str); /****************************************************************************/ new = (NickList *) new_malloc(sizeof(NickList)); new->nick = (char *) 0; malloc_strcpy(&new->nick, str); /**************************** PATCHED by Flier ******************************/ new->userhost = NULL; /****************************************************************************/ add_to_list((List **) &(tmp->nicks), (List *) new); } else say("%s already on window name list", str); } str = ptr; } } else say("No such window!"); } /* below is stuff used for parsing of WINDOW command */ /* * get_window_by_name: returns a pointer to a window with a matching logical * name or null if no window matches */ Window * get_window_by_name(name) char *name; { Window *tmp; int flag = 1; while ((tmp = traverse_all_windows(&flag)) != NULL) { if (tmp->name && (my_stricmp(tmp->name, name) == 0)) return (tmp); } return ((Window *) 0); } /* * get_window: this parses out any window (visible or not) and returns a * pointer to it */ static Window * get_window(name, args) char *name; char **args; { char *arg; Window *tmp; if ((arg = next_arg(*args, args)) != NULL) { if (is_number(arg)) { if ((tmp = get_window_by_refnum((u_int)atoi(arg))) != NULL) return (tmp); } if ((tmp = get_window_by_name(arg)) != NULL) return (tmp); say("%s: No such window: %s", name, arg); } else say("%s: Please specify a window refnum or name", name); return ((Window *) 0); } /* * get_invisible_window: parses out an invisible window by reference number. * Returns the pointer to the window, or null. The args can also be "LAST" * indicating the top of the invisible window list (and thus the last window * made invisible) */ static Window * get_invisible_window(name, args) char *name; char **args; { char *arg; Window *tmp; if ((arg = next_arg(*args, args)) != NULL) { if (my_strnicmp(arg, "LAST", strlen(arg)) == 0) { if (invisible_list == (Window *) 0) say("%s: There are no hidden windows", name); return (invisible_list); } if ((tmp = get_window(name, &arg)) != NULL) { if (!tmp->visible) return (tmp); else { if (tmp->name) say("%s: Window %s is not hidden!", name, tmp->name); else say("%s: Window %d is not hidden!", name, tmp->refnum); } } } else say("%s: Please specify a window refnum or LAST", name); return ((Window *) 0); } /* get_number: parses out an integer number and returns it */ static int get_number(name, args) char *name; char **args; { char *arg; if ((arg = next_arg(*args, args)) != NULL) return (atoi(arg)); else say("%s: You must specify the number of lines", name); return (0); } /* * get_boolean: parses either ON, OFF, or TOGGLE and sets the var * accordingly. Returns 0 if all went well, -1 if a bogus or missing value * was specified */ static int get_boolean(name, args, var) char *name; char **args; int *var; { char *arg; if (((arg = next_arg(*args, args)) == (char *) 0) || do_boolean(arg, var)) { say("Value for %s must be ON, OFF, or TOGGLE", name); return (-1); } else { say("Window %s is %s", name, var_settings[*var]); return (0); } } /*ARGSUSED*/ void windowcmd(command, args, subargs) char *command, *args, *subargs; { size_t len; char *arg, *cmd = (char *) 0; char buffer[BIG_BUFFER_SIZE+1]; int no_args = 1; Window *window, *tmp; in_window_command = 1; save_message_from(); message_from((char *) 0, LOG_CURRENT); /* XXX should remove this */ window = curr_scr_win; while ((arg = next_arg(args, &args)) != NULL) { no_args = 0; len = strlen(arg); malloc_strcpy(&cmd, arg); upper(cmd); if (strncmp("NEW", cmd, len) == 0) { if ((tmp = new_window()) != NULL) window = tmp; } #ifdef WINDOW_CREATE else if (strncmp("CREATE", cmd, len) == 0) { if ((tmp = create_additional_screen()) != NULL) window = tmp; else say("Cannot create new screen!"); } else if (!strncmp("DELETE", cmd, len)) kill_screen(current_screen); #endif /* WINODW_CREATE */ else if (strncmp("REFNUM", cmd, len) == 0) { if ((tmp = get_window("REFNUM", &args)) != NULL) { if (tmp->screen && tmp->screen !=window->screen) say("Window in another screen!"); else if (tmp->visible) { set_current_window(tmp); window = tmp; } else say("Window not visible!"); } else { say("No such window!"); new_free(&cmd); goto out; } } else if (strncmp("KILL", cmd, len) == 0) delete_window(window); else if (strncmp("SHRINK", cmd, len) == 0) grow_window(window, -get_number("SHRINK", &args)); else if (strncmp("GROW", cmd, len) == 0) /**************************** Patched by Flier ******************************/ /*grow_window(window, get_number("SHRINK", &args));*/ grow_window(window, get_number("GROW", &args)); else if (strncmp("SIZE", cmd, len) == 0) size_window(window, get_number("SIZE", &args)); #ifdef HAVE_SSL else if (strncmp("SSL", cmd, len) == 0 || strncmp("-SSL", cmd, len) == 0) SSLconnect = 1; #endif /****************************************************************************/ else if (strncmp("SCROLL", cmd, len) == 0) get_boolean("SCROLL", &args, &(window->scroll)); else if (strncmp("STICKY", cmd, len) == 0) get_boolean("STICKY", &args, &(window->sticky)); else if (strncmp("LOG", cmd, len) == 0) { if (get_boolean("LOG", &args, &(window->log))) break; else { char *logfile; int add_ext = 1; if ((logfile = window->logfile) != NULL) add_ext = 0; else if (!(logfile = get_string_var(LOGFILE_VAR))) logfile = empty_string; if (!add_ext) snprintf(buffer, sizeof buffer, "%s", logfile); else if (window->current_channel) snprintf(buffer, sizeof buffer, "%s.%s", logfile, window->current_channel); else if (window->query_nick) snprintf(buffer, sizeof buffer, "%s.%s", logfile, window->query_nick); else snprintf(buffer, sizeof buffer, "%s.Window_%d", logfile, window->refnum); /**************************** PATCHED by Flier ******************************/ /*window->log_fp = do_log(window->log, buffer, window->log_fp);*/ do_log(window->log, buffer, &(window->log_fp)); /****************************************************************************/ if (window->log_fp == (FILE *) 0) window->log = 0; } } else if (strncmp("HOLD_MODE", cmd, len) == 0) get_boolean("HOLD_MODE", &args, &(window->hold_mode)); else if (strncmp("LASTLOG_LEVEL", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) { window->lastlog_level = parse_lastlog_level(arg); say("Lastlog level is %s", bits_to_lastlog_level(window->lastlog_level)); } else say("Level required"); } else if (strncmp("LEVEL", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) { /**************************** PATCHED by Flier ******************************/ /*window->window_level = parse_lastlog_level(arg);*/ int new_level = parse_lastlog_level(arg); if (*arg == '+') window->window_level |= new_level; else window->window_level = new_level; /****************************************************************************/ say("Window level is %s", bits_to_lastlog_level(window->window_level)); revamp_window_levels(window); } else say("LEVEL: Level required"); } else if (strncmp("BALANCE", cmd, len) == 0) recalculate_windows(); /**************************** PATCHED by Flier ******************************/ /*#if defined(_Windows)*/ /****************************************************************************/ #ifndef LITE else if (strncmp("TITLE", cmd, len) == 0) { /**************************** PATCHED by Flier ******************************/ /*if ((arg = next_arg(args, &args)) != NULL)*/ if ((arg = new_next_arg(args, &args)) != NULL) /****************************************************************************/ { /**************************** PATCHED by Flier ******************************/ #ifdef SZ32 SetConsoleTitle(arg); #elif defined(_Windows) /****************************************************************************/ if (window->visible && window->screen) { SetWindowText(window->screen->hwnd, arg); } else { say("The current window is not attached to a screen"); } /**************************** PATCHED by Flier ******************************/ #else fprintf(stderr, "]0;%s", arg); fflush(stderr); #endif /****************************************************************************/ } else { say("You must specify a name for the window!"); } } #endif /**************************** PATCHED by Flier ******************************/ /*#endif*/ /* _Windows */ /****************************************************************************/ else if (strncmp("NAME", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) { if (is_window_name_unique(arg)) { malloc_strcpy(&(window->name), arg); window->update |= UPDATE_STATUS; } else say("%s is not unique!", arg); } else say("You must specify a name for the window!"); } else if (strncmp("PROMPT", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) { malloc_strcpy(&(window->prompt), arg); window->update |= UPDATE_STATUS; } else say("You must specify a prompt for the window!"); } else if (strncmp("GOTO", cmd, len) == 0) { irc_goto_window(get_number("GOTO", &args)); window = curr_scr_win; } else if (strncmp("LAST", cmd, len) == 0) set_current_window((Window *) 0); else if (strncmp("MOVE", cmd, len) == 0) { move_window(window, get_number("MOVE", &args)); window = curr_scr_win; } else if (strncmp("SWAP", cmd, len) == 0) { if ((tmp = get_invisible_window("SWAP", &args)) != NULL) swap_window(window, tmp); } else if (strncmp("HIDE", cmd, len) == 0) hide_window(window); #ifndef LITE else if (strncmp("PUSH", cmd, len) == 0) push_window_by_refnum(window->refnum); else if (strncmp("POP", cmd, len) == 0) pop_window(); #endif else if (strncmp("ADD", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) add_nicks_by_refnum(window->refnum, arg, 1); else say("ADD: Do something! Geez!"); } else if (strncmp("REMOVE", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) add_nicks_by_refnum(window->refnum, arg, 0); else say("REMOVE: Do something! Geez!"); } #ifndef LITE else if (strncmp("STACK", cmd, len) == 0) show_stack(); #endif else if (strncmp("LIST", cmd, len) == 0) list_windows(); else if (strncmp("SERVER", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) window_get_connected(window, arg, -1, args); else say("SERVER: You must specify a server"); } else if (strncmp("SHOW", cmd, len) == 0) { if ((tmp = get_window("SHOW", &args)) != NULL) { show_window(tmp); window = curr_scr_win; } } else if (strncmp("HIDE_OTHERS", cmd, len) == 0) hide_other_windows(); else if (strncmp("KILL_OTHERS", cmd, len) == 0) delete_other_windows(); else if (strncmp("NOTIFY", cmd, len) == 0) { window->miscflags ^= WINDOW_NOTIFY; say("Notification when hidden set to %s", (window->miscflags & WINDOW_NOTIFY)? "ON" : "OFF"); } else if (strncmp("WHERE", cmd, len) == 0) win_list_channels(curr_scr_win); else if (strncmp("QUERY", cmd, len) == 0) { char *a = 0; a = next_arg(args, &args); query(cmd, a, 0); } else if (strncmp("CHANNEL", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) { char *key; arg = strtok(arg, ","); if ((key = strtok(0, ", ")) == 0) key = empty_string; if (is_bound(arg, window->server)) { say("Channel %s is bound", arg); } else { if (is_on_channel(arg, window->server, get_server_nickname(window->server))) { is_current_channel(arg, window->server, (int)window->refnum); say("You are now talking to channel %s", arg); set_channel_by_refnum(0, arg); } else if (*arg == '0' && !*(args + 1)) set_channel_by_refnum(0, NULL); else { int server; server = from_server; from_server = window->server; switch (get_server_version(window->server)) { case Server2_5: send_to_server("CHANNEL %s%s%s", arg, key ? " " : empty_string, key); break; default: send_to_server("JOIN %s%s%s", arg, key ? " " : empty_string, key); } /**************************** PATCHED by Flier ******************************/ /* from_server can be -1 here add_channel(arg, from_server, CHAN_JOINING, (ChannelList *) 0,);*/ if (from_server >= 0) add_channel(arg, from_server, CHAN_JOINING, NULL, key, 0); /****************************************************************************/ from_server = server; } } } else set_channel_by_refnum(0, irczero); } else if (strncmp("PREVIOUS", cmd, len) == 0) { swap_previous_window(0, (char *) 0); } else if (strncmp("NEXT", cmd, len) == 0) { swap_next_window(0, (char *) 0); } else if (strncmp("BACK", cmd, len) == 0) { back_window(0, (char *) 0); } else if (strncmp("KILLSWAP", cmd, len) == 0) { window_kill_swap(); } else if (strncmp("LOGFILE", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) { malloc_strcpy(&window->logfile, arg); say("Window LOGFILE set to %s", arg); } else say("No LOGFILE given"); } else if (strncmp("NOTIFY_LEVEL", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != NULL) { window->notify_level = parse_lastlog_level(arg); say("Window notify level is %s", bits_to_lastlog_level(window->notify_level)); } else say("Level missing"); } else if (strncmp("NUMBER", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != (char *) 0) { int i; Window *wtmp; i = atoi(arg); if (i > 0) { /* check if window number exists */ wtmp = get_window_by_refnum((u_int)i); if (!wtmp) window->refnum = i; else { wtmp->refnum = window->refnum; window->refnum = i; } update_all_status(); } else say("Window number must be greater than 1"); } else say("Window number missing"); } else if (strncmp("BIND", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != (char *) 0) { if (!is_channel(arg)) say("BIND: %s is not a valid channel name", arg); else { /**************************** PATCHED by Flier ******************************/ char *origarg = arg; while ((arg = strtok(origarg, ","))) { origarg = (char *) 0; /****************************************************************************/ bind_channel(arg, window); /**************************** PATCHED by Flier ******************************/ } /****************************************************************************/ } } else /**************************** PATCHED by Flier ******************************/ { /*if (window->bound_channel) say("Channel %s is bound to window %d", window->bound_channel, window->refnum);*/ int count = 0; char *tmpbuf = NULL; struct channels *chan; for (chan = window->bound_chans; chan; chan = chan->next){ malloc_strcat(&tmpbuf, chan->channel); if (chan->next) malloc_strcat(&tmpbuf, ","); count++; } if (count) { say("Channel%s %s %s bound to window %d", count == 1 ? "" : "s", tmpbuf, count == 1 ? "is" : "are", window->refnum); new_free(&tmpbuf); } } /****************************************************************************/ } else if (strncmp("UNBIND", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != (char *) 0) { if (is_bound(arg, window->server)) { say("Channel %s is no longer bound", arg); unbind_channel(arg, window); } else say("Channel %s is not bound", arg); } else say("UNBIND: You must specify a channel name"); } else if (strncmp("ADDGROUP", cmd, len) == 0) { if ((arg = next_arg(args, &args)) != (char *) 0) add_window_to_server_group(window, arg); else say("WINDOW ADDGROUP requires a group name"); } else if (strncmp("DELGROUP", cmd, len) == 0) { window->server_group = 0; say("Window no longer has a server group"); update_window_status(window, 1); } else if (strncmp("DOUBLE", cmd, len) == 0) { /**************************** PATCHED by Flier ******************************/ /*int current = window->double_status; if (get_boolean("DOUBLE", &args, &(window->double_status)) == 0) { window->display_size += current - window->double_status; recalculate_window_positions(); update_all_windows(); build_status((char *) NULL); }*/ if ((arg = next_arg(args, &args))) { int errcmd = -1; int current = window->double_status; upper(arg); if (!strcmp(arg, "ON")) { errcmd = 0; window->double_status = 1; } else if (!strcmp(arg, "OFF")) { errcmd = 0; window->double_status = 0; } else if (!strcmp(arg, "TOGGLE")) { errcmd = 0; if (window->double_status == 1) window->double_status = 0; else if (window->double_status == 0) window->double_status = 1; else errcmd = -1; } else { int i; i = atoi(arg); if (i > 1 && i < 4) { errcmd = 0; window->double_status = i - 1; } } if (errcmd == -1) say("Value for DOUBLE must be ON, OFF, TOGGLE, 2 or 3"); else { window->display_size += current-window->double_status; recalculate_window_positions(); update_all_windows(); build_status(NULL); } } /****************************************************************************/ } else if (strncmp("NOSTATUS", cmd, len) == 0) { int current = window->double_status; window->double_status = -1; window->display_size += current - window->double_status; recalculate_window_positions(); update_all_windows(); build_status((u_char *) NULL); } else say("Unknown WINDOW command: %s", arg); new_free(&cmd); } if (no_args) { if (window->name) say("Window %s (%u)", window->name, window->refnum); else say("Window %u", window->refnum); if (window->server == -1) say("\tServer: "); else say("\tServer: %s", get_server_name(window->server)); say("\tCurrent channel: %s", window->current_channel ? window->current_channel : ""); say("\tQuery User: %s", (window->query_nick ? window->query_nick : "")); say("\tPrompt: %s", window->prompt ? window->prompt : ""); /**************************** PATCHED by Flier ******************************/ /*say("\tSecond status line is %s", var_settings[window->double_status]);*/ say("\tNumber of status lines: %d",1+window->double_status); /****************************************************************************/ say("\tScrolling is %s", var_settings[window->scroll]); say("\tLogging is %s", var_settings[window->log]); if (window->logfile) say("\tLogfile is %s", window->logfile); else say("\tNo logfile given"); say("\tNotification is %s", var_settings[window->miscflags & WINDOW_NOTIFY]); say("\tHold mode is %s", var_settings[window->hold_mode]); say("\tSticky behaviour is %s", var_settings[window->sticky]); say("\tWindow level is %s", bits_to_lastlog_level(window->window_level)); say("\tLastlog level is %s", bits_to_lastlog_level(window->lastlog_level)); say("\tNotify level is %s", bits_to_lastlog_level(window->notify_level)); if (window->server_group) say("\tServer Group is (%d) %s", window->server_group, find_server_group_name(window->server_group)); /**************************** PATCHED by Flier ******************************/ /*if (window->bound_channel) say("\tBound Channel is %s", window->bound_channel);*/ if (window->bound_chans) { int count=0; char *tmpbuf=(char *) 0; struct channels *chan; for (chan=window->bound_chans;chan;chan=chan->next) { malloc_strcat(&tmpbuf,chan->channel); if (chan->next) malloc_strcat(&tmpbuf,","); count++; } say("\tBound Channel%s %s %s", count==1?"":"s",count==1?"is":"are",tmpbuf); new_free(&tmpbuf); } /****************************************************************************/ if (window->nicks) { NickList *ntmp; say("\tName list:"); for (ntmp = window->nicks; ntmp; ntmp = ntmp->next) say("\t %s", ntmp->nick); } } out: restore_message_from(); in_window_command = 0; update_all_windows(); cursor_to_input(); /**************************** Patched by Flier ******************************/ #ifdef HAVE_SSL SSLconnect = 0; #endif /****************************************************************************/ } int number_of_windows() { return (current_screen->visible_windows); } void unstop_all_windows(key, ptr) u_int key; char * ptr; { Window *tmp; for (tmp = current_screen->window_list; tmp; tmp = tmp->next) hold_mode(tmp, OFF, 1); } /* this will make underline toggle between 2 and -1 and never let it get to 0 */ void set_underline_video(value) int value; { if (value == OFF) underline = -1; else underline = 1; } void window_get_connected(window, arg, narg, args) Window *window; char *arg; int narg; char *args; { int i, port_num, new_server_flags = WIN_TRANSFER; char *port, *password = NULL, *nick = NULL, *extra = NULL; if (arg) { if (*arg == '=') { new_server_flags |= WIN_ALL; arg++; } else if (*arg == '~') { new_server_flags |= WIN_FORCE; arg++; } parse_server_info(&arg, &port, &password, &nick, &extra); if (port) { port_num = atoi(port); if (!port_num) port_num = -1; } else port_num = -1; if (extra) { /* nothing yet */ ; } /* relies on parse_server_info putting a null in */ /* This comes first for "/serv +1" -Sol */ if ((i = parse_server_index(arg)) != -1) { if (port_num == -1) /* Could be "/serv +1:6664" -Sol */ port_num = server_list[i].port; if (nick == NULL) nick = server_list[i].nickname; } else if ((i = find_in_server_list(arg, port_num, nick)) != -1) port_num = server_list[i].port; } else { i = narg; port_num = server_list[i].port; arg = server_list[i].name; } if (!(new_server_flags & WIN_ALL)) { /* Test if last window -Sol */ int flag = 1; Window *ptr, *new_win = (Window *) 0; while ((ptr = traverse_all_windows(&flag)) != (Window *) 0) if ((ptr != window) && (!ptr->server_group || (ptr->server_group != window->server_group)) && (ptr->server == window->server)) { new_win = ptr; break; } if (!new_win) new_server_flags |= WIN_ALL; } if (-1 == i) { if (nick && *nick) malloc_strcpy(&connect_next_nick, nick); if (password && *password) malloc_strcpy(&connect_next_password, password); } else { if (nick && *nick) set_server_nickname(i, nick); if (password && *password) set_server_password(i, password); if (((i = find_in_server_list(get_server_name(i), port_num, nick)) != -1) && is_server_connected(i)) new_server_flags &= ~WIN_TRANSFER; arg = get_server_name(i); port_num = server_list[i].port; } if (!connect_to_server(arg, port_num, nick, (new_server_flags & WIN_ALL) ? window->server : -1)) { window_set_server((int)window->refnum, from_server, new_server_flags); update_all_status(); } window_check_servers(); /**************************** PATCHED by Flier ******************************/ if (curr_scr_win->server >= 0) is_current_channel(NULL, curr_scr_win->server, 0); /****************************************************************************/ } static void win_list_channels(window) Window *window; { ChannelList *tmp; int print_one = 0; if (!window) return; for (tmp = server_list[window->server].chan_list; tmp; tmp = tmp->next) if (tmp->window == window) { if (!print_one) { say("Channels currently in this window :"); print_one++; } say("\t%s", tmp->channel); } if (!print_one) say("There are no channels in this window"); } /**************************** PATCHED by Flier ******************************/ /* Try to find given window in window list */ Window *FindWindowByPtr(wind) Window *wind; { Window *tmp; if (!wind) return((Window *) 0); for (tmp=curr_scr_win->screen->window_list;tmp;tmp=tmp->next) if (tmp->server==wind->server && tmp==wind) return(tmp); for (tmp=invisible_list;tmp;tmp=tmp->next) if (tmp->server==wind->server && tmp==wind) break; return(tmp); } /* Clean up all memory related to window */ void CleanUpWindows() { Screen *tmpscreen; Screen *tmpscreenfree; Window *tmpwindow; Window *tmpwindowfree; for (tmpscreen=screen_list;tmpscreen;) { tmpscreenfree=tmpscreen; tmpscreen=tmpscreen->next; for (tmpwindow=tmpscreenfree->window_list;tmpwindow;) { tmpwindowfree=tmpwindow; tmpwindow=tmpwindow->next; cleanup_window(tmpwindowfree); } new_free(&(tmpscreenfree->redirect_name)); new_free(&(tmpscreenfree->redirect_token)); new_free(&(tmpscreenfree->tty_name)); new_free(&tmpscreenfree); } for (tmpwindow=invisible_list;tmpwindow;) { tmpwindowfree=tmpwindow; tmpwindow=tmpwindow->next; cleanup_window(tmpwindowfree); } } /****************************************************************************/