| File: | fe-text/mainwindows-layout.c |
| Location: | line 181, column 23 |
| Description: | Dereference of null pointer. |
| 1 | /* |
| 2 | mainwindows-layout.c : irssi |
| 3 | |
| 4 | Copyright (C) 2001 Timo Sirainen |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 2 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License along |
| 17 | with this program; if not, write to the Free Software Foundation, Inc., |
| 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 19 | */ |
| 20 | |
| 21 | #include "module.h" |
| 22 | #include "signals.h" |
| 23 | #include "misc.h" |
| 24 | #include "lib-config/iconfig.h" |
| 25 | #include "settings.h" |
| 26 | |
| 27 | #include "mainwindows.h" |
| 28 | #include "gui-windows.h" |
| 29 | #include "textbuffer-view.h" |
| 30 | |
| 31 | static void sig_layout_window_save(WINDOW_REC *window, CONFIG_NODE *node) |
| 32 | { |
| 33 | WINDOW_REC *active; |
| 34 | GUI_WINDOW_REC *gui; |
| 35 | |
| 36 | gui = WINDOW_GUI(window)((GUI_WINDOW_REC *) ((window)->gui_data)); |
| 37 | if (gui->sticky) { |
| 38 | iconfig_node_set_bool(node, "sticky", TRUE)config_node_set_bool(mainconfig, node, "sticky", (!(0))); |
| 39 | active = gui->parent->active; |
| 40 | if (window != active) |
| 41 | iconfig_node_set_int(node, "parent", active->refnum)config_node_set_int(mainconfig, node, "parent", active->refnum ); |
| 42 | } |
| 43 | |
| 44 | if (gui->use_scroll) |
| 45 | iconfig_node_set_bool(node, "scroll", gui->scroll)config_node_set_bool(mainconfig, node, "scroll", gui->scroll ); |
| 46 | } |
| 47 | |
| 48 | static void sig_layout_window_restore(WINDOW_REC *window, CONFIG_NODE *node) |
| 49 | { |
| 50 | WINDOW_REC *parent; |
| 51 | GUI_WINDOW_REC *gui; |
| 52 | |
| 53 | gui = WINDOW_GUI(window)((GUI_WINDOW_REC *) ((window)->gui_data)); |
| 54 | |
| 55 | parent = window_find_refnum(config_node_get_int(node, "parent", -1)); |
| 56 | if (parent != NULL((void *)0)) |
| 57 | gui_window_reparent(window, WINDOW_MAIN(parent)(((GUI_WINDOW_REC *) ((parent)->gui_data))->parent)); |
| 58 | |
| 59 | if (config_node_get_bool(node, "sticky", FALSE(0))) |
| 60 | gui_window_set_sticky(window); |
| 61 | if (config_node_get_str(node, "scroll", NULL((void *)0)) != NULL((void *)0)) { |
| 62 | gui->use_scroll = TRUE(!(0)); |
| 63 | gui->scroll = config_node_get_bool(node, "scroll", TRUE(!(0))); |
| 64 | textbuffer_view_set_scroll(gui->view, gui->scroll); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | static void main_window_save(MAIN_WINDOW_REC *window, CONFIG_NODE *node) |
| 69 | { |
| 70 | char num[MAX_INT_STRLEN((sizeof(int) * 8 + 2) / 3 + 1)]; |
| 71 | |
| 72 | ltoa(num, window->active->refnum)g_snprintf(num, sizeof(num), "%d", window->active->refnum ); |
| 73 | node = config_node_section(node, num, NODE_TYPE_BLOCK); |
| 74 | |
| 75 | iconfig_node_set_int(node, "first_line", window->first_line)config_node_set_int(mainconfig, node, "first_line", window-> first_line); |
| 76 | iconfig_node_set_int(node, "lines", window->height)config_node_set_int(mainconfig, node, "lines", window->height ); |
| 77 | } |
| 78 | |
| 79 | static void sig_layout_save(void) |
| 80 | { |
| 81 | CONFIG_NODE *node; |
| 82 | |
| 83 | iconfig_set_str(NULL, "mainwindows", NULL)config_set_str(mainconfig, ((void *)0), "mainwindows", ((void *)0)); |
| 84 | node = iconfig_node_traverse("mainwindows", TRUE)config_node_traverse(mainconfig, "mainwindows", (!(0))); |
| 85 | |
| 86 | g_slist_foreach(mainwindows, (GFunc) main_window_save, node); |
| 87 | } |
| 88 | |
| 89 | static int window_node_cmp(CONFIG_NODE *n1, CONFIG_NODE *n2) |
| 90 | { |
| 91 | return config_node_get_int(n1, "first_line", 0) > |
| 92 | config_node_get_int(n2, "first_line", 0) ? -1 : 1; |
| 93 | } |
| 94 | |
| 95 | /* Returns list of mainwindow nodes sorted by first_line |
| 96 | (lowest in screen first) */ |
| 97 | static GSList *get_sorted_windows_config(CONFIG_NODE *node) |
| 98 | { |
| 99 | GSList *tmp, *output; |
| 100 | |
| 101 | output = NULL((void *)0); |
| 102 | tmp = config_node_first(node->value); |
| 103 | for (; tmp != NULL((void *)0); tmp = config_node_next(tmp)) { |
| 104 | output = g_slist_insert_sorted(output, tmp->data, |
| 105 | (GCompareFunc) window_node_cmp); |
| 106 | } |
| 107 | |
| 108 | return output; |
| 109 | } |
| 110 | |
| 111 | static void sig_layout_restore(void) |
| 112 | { |
| 113 | MAIN_WINDOW_REC *lower_window; |
| 114 | WINDOW_REC *window; |
| 115 | CONFIG_NODE *node; |
| 116 | GSList *tmp, *sorted_config; |
| 117 | int avail_height, height, *heights; |
| 118 | int i, lower_size, windows_count, diff; |
| 119 | |
| 120 | node = iconfig_node_traverse("mainwindows", FALSE)config_node_traverse(mainconfig, "mainwindows", (0)); |
| 121 | if (node == NULL((void *)0)) return; |
[1] Taking false branch | |
| 122 | |
| 123 | sorted_config = get_sorted_windows_config(node); |
| 124 | windows_count = g_slist_length(sorted_config); |
| 125 | |
| 126 | /* calculate the saved terminal height */ |
| 127 | avail_height = term_height - |
| 128 | screen_reserved_top - screen_reserved_bottom; |
| 129 | height = 0; |
| 130 | heights = g_new0(int, windows_count)((int *) g_malloc0 (((gsize) sizeof (int)) * ((gsize) (windows_count )))); |
| 131 | for (i = 0, tmp = sorted_config; tmp != NULL((void *)0); tmp = tmp->next, i++) { |
[2] Loop condition is false. Execution continues on line 138 | |
| 132 | CONFIG_NODE *node = tmp->data; |
| 133 | |
| 134 | heights[i] = config_node_get_int(node, "lines", 0); |
| 135 | height += heights[i]; |
| 136 | } |
| 137 | |
| 138 | if (avail_height <= (WINDOW_MIN_SIZE2*2)+1) { |
[3] Taking true branch | |
| 139 | /* we can fit only one window to screen - |
| 140 | give it all the height we can */ |
| 141 | windows_count = 1; |
| 142 | heights[0] = avail_height; |
| 143 | } else if (height != avail_height) { |
| 144 | /* Terminal's height is different from the saved one. |
| 145 | Resize the windows so they fit to screen. */ |
| 146 | while (height > avail_height && |
| 147 | windows_count*(WINDOW_MIN_SIZE2+1) > avail_height) { |
| 148 | /* all windows can't fit into screen, |
| 149 | remove the lowest ones */ |
| 150 | windows_count--; |
| 151 | } |
| 152 | |
| 153 | /* try to keep the windows' size about the same in percents */ |
| 154 | for (i = 0; i < windows_count; i++) { |
| 155 | int size = avail_height*heights[i]/height; |
| 156 | if (size < WINDOW_MIN_SIZE2+1) |
| 157 | size = WINDOW_MIN_SIZE2+1; |
| 158 | heights[i] = size; |
| 159 | } |
| 160 | |
| 161 | /* give/remove the last bits */ |
| 162 | height = 0; |
| 163 | for (i = 0; i < windows_count; i++) |
| 164 | height += heights[i]; |
| 165 | |
| 166 | diff = height < avail_height ? 1 : -1; |
| 167 | for (i = 0; height != avail_height; i++) { |
| 168 | if (i == windows_count) |
| 169 | i = 0; |
| 170 | |
| 171 | if (heights[i] > WINDOW_MIN_SIZE2+1) { |
| 172 | height += diff; |
| 173 | heights[i] += diff; |
| 174 | } |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | /* create all the visible windows with correct size */ |
| 179 | lower_window = NULL((void *)0); lower_size = 0; |
| 180 | for (i = 0, tmp = sorted_config; i < windows_count; tmp = tmp->next, i++) { |
[4] Loop condition is true. Entering loop body | |
| 181 | CONFIG_NODE *node = tmp->data; |
[5] Dereference of null pointer | |
| 182 | |
| 183 | /* create a new window + mainwindow */ |
| 184 | signal_emit("gui window create override", 1, |
| 185 | GINT_TO_POINTER(0)((gpointer) (0))); |
| 186 | |
| 187 | window = window_create(NULL((void *)0), TRUE(!(0))); |
| 188 | window_set_refnum(window, atoi(node->key)); |
| 189 | |
| 190 | if (lower_size > 0) |
| 191 | mainwindow_set_size(lower_window, lower_size, FALSE(0)); |
| 192 | |
| 193 | window_set_active(window); |
| 194 | active_mainwin = WINDOW_MAIN(window)(((GUI_WINDOW_REC *) ((window)->gui_data))->parent); |
| 195 | |
| 196 | lower_window = WINDOW_MAIN(window)(((GUI_WINDOW_REC *) ((window)->gui_data))->parent); |
| 197 | lower_size = heights[i]; |
| 198 | if (lower_size < WINDOW_MIN_SIZE2+1) |
| 199 | lower_size = WINDOW_MIN_SIZE2+1; |
| 200 | } |
| 201 | g_slist_free(sorted_config); |
| 202 | g_free(heights); |
| 203 | |
| 204 | if (lower_size > 0) |
| 205 | mainwindow_set_size(lower_window, lower_size, FALSE(0)); |
| 206 | } |
| 207 | |
| 208 | static void sig_layout_reset(void) |
| 209 | { |
| 210 | iconfig_set_str(NULL, "mainwindows", NULL)config_set_str(mainconfig, ((void *)0), "mainwindows", ((void *)0)); |
| 211 | } |
| 212 | |
| 213 | void mainwindows_layout_init(void) |
| 214 | { |
| 215 | signal_add("layout save window", (SIGNAL_FUNC) sig_layout_window_save)signal_add_full("fe-text", 0, ("layout save window"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) sig_layout_window_save), ((void *)0)); |
| 216 | signal_add("layout restore window", (SIGNAL_FUNC) sig_layout_window_restore)signal_add_full("fe-text", 0, ("layout restore window"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) sig_layout_window_restore), ((void *)0)); |
| 217 | signal_add("layout save", (SIGNAL_FUNC) sig_layout_save)signal_add_full("fe-text", 0, ("layout save"), (SIGNAL_FUNC) ( (SIGNAL_FUNC) sig_layout_save), ((void *)0)); |
| 218 | signal_add_first("layout restore", (SIGNAL_FUNC) sig_layout_restore)signal_add_full("fe-text", -100, ("layout restore"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) sig_layout_restore), ((void *)0)); |
| 219 | signal_add("layout reset", (SIGNAL_FUNC) sig_layout_reset)signal_add_full("fe-text", 0, ("layout reset"), (SIGNAL_FUNC) ((SIGNAL_FUNC) sig_layout_reset), ((void *)0)); |
| 220 | } |
| 221 | |
| 222 | void mainwindows_layout_deinit(void) |
| 223 | { |
| 224 | signal_remove("layout save window", (SIGNAL_FUNC) sig_layout_window_save)signal_remove_full(("layout save window"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) sig_layout_window_save), ((void *)0)); |
| 225 | signal_remove("layout restore window", (SIGNAL_FUNC) sig_layout_window_restore)signal_remove_full(("layout restore window"), (SIGNAL_FUNC) ( (SIGNAL_FUNC) sig_layout_window_restore), ((void *)0)); |
| 226 | signal_remove("layout save", (SIGNAL_FUNC) sig_layout_save)signal_remove_full(("layout save"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) sig_layout_save), ((void *)0)); |
| 227 | signal_remove("layout restore", (SIGNAL_FUNC) sig_layout_restore)signal_remove_full(("layout restore"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) sig_layout_restore), ((void *)0)); |
| 228 | signal_remove("layout reset", (SIGNAL_FUNC) sig_layout_reset)signal_remove_full(("layout reset"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) sig_layout_reset), ((void *)0)); |
| 229 | } |