1/* TUI window generic functions. 2 3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software 4 Foundation, Inc. 5 6 Contributed by Hewlett-Packard Company. 7 8 This file is part of GDB. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, 23 Boston, MA 02111-1307, USA. */ 24 25/* This module contains procedures for handling tui window functions 26 like resize, scrolling, scrolling, changing focus, etc. 27 28 Author: Susan B. Macchia */ 29 30#include "defs.h" 31#include "command.h" 32#include "symtab.h" 33#include "breakpoint.h" 34#include "frame.h" 35#include "cli/cli-cmds.h" 36#include "top.h" 37#include "source.h" 38 39#include "tui/tui.h" 40#include "tui/tui-data.h" 41#include "tui/tui-wingeneral.h" 42#include "tui/tui-stack.h" 43#include "tui/tui-regs.h" 44#include "tui/tui-disasm.h" 45#include "tui/tui-source.h" 46#include "tui/tui-winsource.h" 47#include "tui/tui-windata.h" 48 49#include "gdb_curses.h" 50 51#include "gdb_string.h" 52#include <ctype.h> 53#include "readline/readline.h" 54 55/******************************* 56** Static Local Decls 57********************************/ 58static void make_visible_with_new_height (struct tui_win_info *); 59static void make_invisible_and_set_new_height (struct tui_win_info *, int); 60static enum tui_status tui_adjust_win_heights (struct tui_win_info *, int); 61static int new_height_ok (struct tui_win_info *, int); 62static void tui_set_tab_width_command (char *, int); 63static void tui_refresh_all_command (char *, int); 64static void tui_set_win_height_command (char *, int); 65static void tui_xdb_set_win_height_command (char *, int); 66static void tui_all_windows_info (char *, int); 67static void tui_set_focus_command (char *, int); 68static void tui_scroll_forward_command (char *, int); 69static void tui_scroll_backward_command (char *, int); 70static void tui_scroll_left_command (char *, int); 71static void tui_scroll_right_command (char *, int); 72static void parse_scrolling_args (char *, struct tui_win_info * *, int *); 73 74 75/*************************************** 76** DEFINITIONS 77***************************************/ 78#define WIN_HEIGHT_USAGE "Usage: winheight <win_name> [+ | -] <#lines>\n" 79#define XDBWIN_HEIGHT_USAGE "Usage: w <#lines>\n" 80#define FOCUS_USAGE "Usage: focus {<win> | next | prev}\n" 81 82/*************************************** 83** PUBLIC FUNCTIONS 84***************************************/ 85 86#ifndef ACS_LRCORNER 87# define ACS_LRCORNER '+' 88#endif 89#ifndef ACS_LLCORNER 90# define ACS_LLCORNER '+' 91#endif 92#ifndef ACS_ULCORNER 93# define ACS_ULCORNER '+' 94#endif 95#ifndef ACS_URCORNER 96# define ACS_URCORNER '+' 97#endif 98#ifndef ACS_HLINE 99# define ACS_HLINE '-' 100#endif 101#ifndef ACS_VLINE 102# define ACS_VLINE '|' 103#endif 104 105/* Possible values for tui-border-kind variable. */ 106static const char *tui_border_kind_enums[] = { 107 "space", 108 "ascii", 109 "acs", 110 NULL 111}; 112 113/* Possible values for tui-border-mode and tui-active-border-mode. */ 114static const char *tui_border_mode_enums[] = { 115 "normal", 116 "standout", 117 "reverse", 118 "half", 119 "half-standout", 120 "bold", 121 "bold-standout", 122 NULL 123}; 124 125struct tui_translate 126{ 127 const char *name; 128 int value; 129}; 130 131/* Translation table for border-mode variables. 132 The list of values must be terminated by a NULL. 133 After the NULL value, an entry defines the default. */ 134struct tui_translate tui_border_mode_translate[] = { 135 { "normal", A_NORMAL }, 136 { "standout", A_STANDOUT }, 137 { "reverse", A_REVERSE }, 138 { "half", A_DIM }, 139 { "half-standout", A_DIM | A_STANDOUT }, 140 { "bold", A_BOLD }, 141 { "bold-standout", A_BOLD | A_STANDOUT }, 142 { 0, 0 }, 143 { "normal", A_NORMAL } 144}; 145 146/* Translation tables for border-kind, one for each border 147 character (see wborder, border curses operations). 148 -1 is used to indicate the ACS because ACS characters 149 are determined at run time by curses (depends on terminal). */ 150struct tui_translate tui_border_kind_translate_vline[] = { 151 { "space", ' ' }, 152 { "ascii", '|' }, 153 { "acs", -1 }, 154 { 0, 0 }, 155 { "ascii", '|' } 156}; 157 158struct tui_translate tui_border_kind_translate_hline[] = { 159 { "space", ' ' }, 160 { "ascii", '-' }, 161 { "acs", -1 }, 162 { 0, 0 }, 163 { "ascii", '-' } 164}; 165 166struct tui_translate tui_border_kind_translate_ulcorner[] = { 167 { "space", ' ' }, 168 { "ascii", '+' }, 169 { "acs", -1 }, 170 { 0, 0 }, 171 { "ascii", '+' } 172}; 173 174struct tui_translate tui_border_kind_translate_urcorner[] = { 175 { "space", ' ' }, 176 { "ascii", '+' }, 177 { "acs", -1 }, 178 { 0, 0 }, 179 { "ascii", '+' } 180}; 181 182struct tui_translate tui_border_kind_translate_llcorner[] = { 183 { "space", ' ' }, 184 { "ascii", '+' }, 185 { "acs", -1 }, 186 { 0, 0 }, 187 { "ascii", '+' } 188}; 189 190struct tui_translate tui_border_kind_translate_lrcorner[] = { 191 { "space", ' ' }, 192 { "ascii", '+' }, 193 { "acs", -1 }, 194 { 0, 0 }, 195 { "ascii", '+' } 196}; 197 198 199/* Tui configuration variables controlled with set/show command. */ 200const char *tui_active_border_mode = "bold-standout"; 201const char *tui_border_mode = "normal"; 202const char *tui_border_kind = "acs"; 203 204/* Tui internal configuration variables. These variables are 205 updated by tui_update_variables to reflect the tui configuration 206 variables. */ 207chtype tui_border_vline; 208chtype tui_border_hline; 209chtype tui_border_ulcorner; 210chtype tui_border_urcorner; 211chtype tui_border_llcorner; 212chtype tui_border_lrcorner; 213 214int tui_border_attrs; 215int tui_active_border_attrs; 216 217/* Identify the item in the translation table. 218 When the item is not recognized, use the default entry. */ 219static struct tui_translate * 220translate (const char *name, struct tui_translate *table) 221{ 222 while (table->name) 223 { 224 if (name && strcmp (table->name, name) == 0) 225 return table; 226 table++; 227 } 228 229 /* Not found, return default entry. */ 230 table++; 231 return table; 232} 233 234/* Update the tui internal configuration according to gdb settings. 235 Returns 1 if the configuration has changed and the screen should 236 be redrawn. */ 237int 238tui_update_variables (void) 239{ 240 int need_redraw = 0; 241 struct tui_translate *entry; 242 243 entry = translate (tui_border_mode, tui_border_mode_translate); 244 if (tui_border_attrs != entry->value) 245 { 246 tui_border_attrs = entry->value; 247 need_redraw = 1; 248 } 249 entry = translate (tui_active_border_mode, tui_border_mode_translate); 250 if (tui_active_border_attrs != entry->value) 251 { 252 tui_active_border_attrs = entry->value; 253 need_redraw = 1; 254 } 255 256 /* If one corner changes, all characters are changed. 257 Only check the first one. The ACS characters are determined at 258 run time by curses terminal management. */ 259 entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner); 260 if (tui_border_lrcorner != (chtype) entry->value) 261 { 262 tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value; 263 need_redraw = 1; 264 } 265 entry = translate (tui_border_kind, tui_border_kind_translate_llcorner); 266 tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value; 267 268 entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner); 269 tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value; 270 271 entry = translate (tui_border_kind, tui_border_kind_translate_urcorner); 272 tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value; 273 274 entry = translate (tui_border_kind, tui_border_kind_translate_hline); 275 tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value; 276 277 entry = translate (tui_border_kind, tui_border_kind_translate_vline); 278 tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value; 279 280 return need_redraw; 281} 282 283static void 284set_tui_cmd (char *args, int from_tty) 285{ 286} 287 288static void 289show_tui_cmd (char *args, int from_tty) 290{ 291} 292 293static struct cmd_list_element *tuilist; 294 295static void 296tui_command (char *args, int from_tty) 297{ 298 printf_unfiltered ("\"tui\" must be followed by the name of a " 299 "tui command.\n"); 300 help_list (tuilist, "tui ", -1, gdb_stdout); 301} 302 303struct cmd_list_element ** 304tui_get_cmd_list () 305{ 306 if (tuilist == 0) 307 add_prefix_cmd ("tui", class_tui, tui_command, 308 "Text User Interface commands.", 309 &tuilist, "tui ", 0, &cmdlist); 310 return &tuilist; 311} 312 313/* Function to initialize gdb commands, for tui window manipulation. */ 314void 315_initialize_tui_win (void) 316{ 317 struct cmd_list_element *c; 318 static struct cmd_list_element *tui_setlist; 319 static struct cmd_list_element *tui_showlist; 320 321 /* Define the classes of commands. 322 They will appear in the help list in the reverse of this order. */ 323 add_prefix_cmd ("tui", class_tui, set_tui_cmd, 324 "TUI configuration variables", 325 &tui_setlist, "set tui ", 326 0/*allow-unknown*/, &setlist); 327 add_prefix_cmd ("tui", class_tui, show_tui_cmd, 328 "TUI configuration variables", 329 &tui_showlist, "show tui ", 330 0/*allow-unknown*/, &showlist); 331 332 add_com ("refresh", class_tui, tui_refresh_all_command, 333 "Refresh the terminal display.\n"); 334 if (xdb_commands) 335 add_com_alias ("U", "refresh", class_tui, 0); 336 add_com ("tabset", class_tui, tui_set_tab_width_command, 337 "Set the width (in characters) of tab stops.\n\ 338Usage: tabset <n>\n"); 339 add_com ("winheight", class_tui, tui_set_win_height_command, 340 "Set the height of a specified window.\n\ 341Usage: winheight <win_name> [+ | -] <#lines>\n\ 342Window names are:\n\ 343src : the source window\n\ 344cmd : the command window\n\ 345asm : the disassembly window\n\ 346regs : the register display\n"); 347 add_com_alias ("wh", "winheight", class_tui, 0); 348 add_info ("win", tui_all_windows_info, 349 "List of all displayed windows.\n"); 350 add_com ("focus", class_tui, tui_set_focus_command, 351 "Set focus to named window or next/prev window.\n\ 352Usage: focus {<win> | next | prev}\n\ 353Valid Window names are:\n\ 354src : the source window\n\ 355asm : the disassembly window\n\ 356regs : the register display\n\ 357cmd : the command window\n"); 358 add_com_alias ("fs", "focus", class_tui, 0); 359 add_com ("+", class_tui, tui_scroll_forward_command, 360 "Scroll window forward.\nUsage: + [win] [n]\n"); 361 add_com ("-", class_tui, tui_scroll_backward_command, 362 "Scroll window backward.\nUsage: - [win] [n]\n"); 363 add_com ("<", class_tui, tui_scroll_left_command, 364 "Scroll window forward.\nUsage: < [win] [n]\n"); 365 add_com (">", class_tui, tui_scroll_right_command, 366 "Scroll window backward.\nUsage: > [win] [n]\n"); 367 if (xdb_commands) 368 add_com ("w", class_xdb, tui_xdb_set_win_height_command, 369 "XDB compatibility command for setting the height of a command window.\n\ 370Usage: w <#lines>\n"); 371 372 /* Define the tui control variables. */ 373 c = add_set_enum_cmd 374 ("border-kind", no_class, 375 tui_border_kind_enums, &tui_border_kind, 376 "Set the kind of border for TUI windows.\n" 377 "This variable controls the border of TUI windows:\n" 378 "space use a white space\n" 379 "ascii use ascii characters + - | for the border\n" 380 "acs use the Alternate Character Set\n", 381 &tui_setlist); 382 add_show_from_set (c, &tui_showlist); 383 384 c = add_set_enum_cmd 385 ("border-mode", no_class, 386 tui_border_mode_enums, &tui_border_mode, 387 "Set the attribute mode to use for the TUI window borders.\n" 388 "This variable controls the attributes to use for the window borders:\n" 389 "normal normal display\n" 390 "standout use highlight mode of terminal\n" 391 "reverse use reverse video mode\n" 392 "half use half bright\n" 393 "half-standout use half bright and standout mode\n" 394 "bold use extra bright or bold\n" 395 "bold-standout use extra bright or bold with standout mode\n", 396 &tui_setlist); 397 add_show_from_set (c, &tui_showlist); 398 399 c = add_set_enum_cmd 400 ("active-border-mode", no_class, 401 tui_border_mode_enums, &tui_active_border_mode, 402 "Set the attribute mode to use for the active TUI window border.\n" 403 "This variable controls the attributes to use for the active window border:\n" 404 "normal normal display\n" 405 "standout use highlight mode of terminal\n" 406 "reverse use reverse video mode\n" 407 "half use half bright\n" 408 "half-standout use half bright and standout mode\n" 409 "bold use extra bright or bold\n" 410 "bold-standout use extra bright or bold with standout mode\n", 411 &tui_setlist); 412 add_show_from_set (c, &tui_showlist); 413} 414 415/* Update gdb's knowledge of the terminal size. */ 416void 417tui_update_gdb_sizes (void) 418{ 419 char cmd[50]; 420 int screenheight, screenwidth; 421 422 rl_get_screen_size (&screenheight, &screenwidth); 423 /* Set to TUI command window dimension or use readline values. */ 424 sprintf (cmd, "set width %d", 425 tui_active ? TUI_CMD_WIN->generic.width : screenwidth); 426 execute_command (cmd, 0); 427 sprintf (cmd, "set height %d", 428 tui_active ? TUI_CMD_WIN->generic.height : screenheight); 429 execute_command (cmd, 0); 430} 431 432 433/* Set the logical focus to win_info. */ 434void 435tui_set_win_focus_to (struct tui_win_info * win_info) 436{ 437 if (win_info != NULL) 438 { 439 struct tui_win_info * win_with_focus = tui_win_with_focus (); 440 441 if (win_with_focus != NULL 442 && win_with_focus->generic.type != CMD_WIN) 443 tui_unhighlight_win (win_with_focus); 444 tui_set_win_with_focus (win_info); 445 if (win_info->generic.type != CMD_WIN) 446 tui_highlight_win (win_info); 447 } 448} 449 450 451void 452tui_scroll_forward (struct tui_win_info * win_to_scroll, int num_to_scroll) 453{ 454 if (win_to_scroll != TUI_CMD_WIN) 455 { 456 int _num_to_scroll = num_to_scroll; 457 458 if (num_to_scroll == 0) 459 _num_to_scroll = win_to_scroll->generic.height - 3; 460 /* 461 ** If we are scrolling the source or disassembly window, do a 462 ** "psuedo" scroll since not all of the source is in memory, 463 ** only what is in the viewport. If win_to_scroll is the 464 ** command window do nothing since the term should handle it. 465 */ 466 if (win_to_scroll == TUI_SRC_WIN) 467 tui_vertical_source_scroll (FORWARD_SCROLL, _num_to_scroll); 468 else if (win_to_scroll == TUI_DISASM_WIN) 469 tui_vertical_disassem_scroll (FORWARD_SCROLL, _num_to_scroll); 470 else if (win_to_scroll == TUI_DATA_WIN) 471 tui_vertical_data_scroll (FORWARD_SCROLL, _num_to_scroll); 472 } 473} 474 475void 476tui_scroll_backward (struct tui_win_info * win_to_scroll, int num_to_scroll) 477{ 478 if (win_to_scroll != TUI_CMD_WIN) 479 { 480 int _num_to_scroll = num_to_scroll; 481 482 if (num_to_scroll == 0) 483 _num_to_scroll = win_to_scroll->generic.height - 3; 484 /* 485 ** If we are scrolling the source or disassembly window, do a 486 ** "psuedo" scroll since not all of the source is in memory, 487 ** only what is in the viewport. If win_to_scroll is the 488 ** command window do nothing since the term should handle it. 489 */ 490 if (win_to_scroll == TUI_SRC_WIN) 491 tui_vertical_source_scroll (BACKWARD_SCROLL, _num_to_scroll); 492 else if (win_to_scroll == TUI_DISASM_WIN) 493 tui_vertical_disassem_scroll (BACKWARD_SCROLL, _num_to_scroll); 494 else if (win_to_scroll == TUI_DATA_WIN) 495 tui_vertical_data_scroll (BACKWARD_SCROLL, _num_to_scroll); 496 } 497} 498 499 500void 501tui_scroll_left (struct tui_win_info * win_to_scroll, int num_to_scroll) 502{ 503 if (win_to_scroll != TUI_CMD_WIN) 504 { 505 int _num_to_scroll = num_to_scroll; 506 507 if (_num_to_scroll == 0) 508 _num_to_scroll = 1; 509 /* 510 ** If we are scrolling the source or disassembly window, do a 511 ** "psuedo" scroll since not all of the source is in memory, 512 ** only what is in the viewport. If win_to_scroll is the 513 ** command window do nothing since the term should handle it. 514 */ 515 if (win_to_scroll == TUI_SRC_WIN || win_to_scroll == TUI_DISASM_WIN) 516 tui_horizontal_source_scroll (win_to_scroll, LEFT_SCROLL, _num_to_scroll); 517 } 518} 519 520 521void 522tui_scroll_right (struct tui_win_info * win_to_scroll, int num_to_scroll) 523{ 524 if (win_to_scroll != TUI_CMD_WIN) 525 { 526 int _num_to_scroll = num_to_scroll; 527 528 if (_num_to_scroll == 0) 529 _num_to_scroll = 1; 530 /* 531 ** If we are scrolling the source or disassembly window, do a 532 ** "psuedo" scroll since not all of the source is in memory, 533 ** only what is in the viewport. If win_to_scroll is the 534 ** command window do nothing since the term should handle it. 535 */ 536 if (win_to_scroll == TUI_SRC_WIN || win_to_scroll == TUI_DISASM_WIN) 537 tui_horizontal_source_scroll (win_to_scroll, RIGHT_SCROLL, _num_to_scroll); 538 } 539} 540 541 542/* Scroll a window. Arguments are passed through a va_list. */ 543void 544tui_scroll (enum tui_scroll_direction direction, 545 struct tui_win_info * win_to_scroll, 546 int num_to_scroll) 547{ 548 switch (direction) 549 { 550 case FORWARD_SCROLL: 551 tui_scroll_forward (win_to_scroll, num_to_scroll); 552 break; 553 case BACKWARD_SCROLL: 554 tui_scroll_backward (win_to_scroll, num_to_scroll); 555 break; 556 case LEFT_SCROLL: 557 tui_scroll_left (win_to_scroll, num_to_scroll); 558 break; 559 case RIGHT_SCROLL: 560 tui_scroll_right (win_to_scroll, num_to_scroll); 561 break; 562 default: 563 break; 564 } 565} 566 567 568void 569tui_refresh_all_win (void) 570{ 571 enum tui_win_type type; 572 573 clearok (curscr, TRUE); 574 tui_refresh_all (tui_win_list); 575 for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++) 576 { 577 if (tui_win_list[type] && tui_win_list[type]->generic.is_visible) 578 { 579 switch (type) 580 { 581 case SRC_WIN: 582 case DISASSEM_WIN: 583 tui_show_source_content (tui_win_list[type]); 584 tui_check_and_display_highlight_if_needed (tui_win_list[type]); 585 tui_erase_exec_info_content (tui_win_list[type]); 586 tui_update_exec_info (tui_win_list[type]); 587 break; 588 case DATA_WIN: 589 tui_refresh_data_win (); 590 break; 591 default: 592 break; 593 } 594 } 595 } 596 tui_show_locator_content (); 597} 598 599 600/* Resize all the windows based on the the terminal size. This 601 function gets called from within the readline sinwinch handler. */ 602void 603tui_resize_all (void) 604{ 605 int height_diff, width_diff; 606 int screenheight, screenwidth; 607 608 rl_get_screen_size (&screenheight, &screenwidth); 609 width_diff = screenwidth - tui_term_width (); 610 height_diff = screenheight - tui_term_height (); 611 if (height_diff || width_diff) 612 { 613 enum tui_layout_type cur_layout = tui_current_layout (); 614 struct tui_win_info * win_with_focus = tui_win_with_focus (); 615 struct tui_win_info *first_win; 616 struct tui_win_info *second_win; 617 struct tui_gen_win_info * locator = tui_locator_win_info_ptr (); 618 enum tui_win_type win_type; 619 int new_height, split_diff, cmd_split_diff, num_wins_displayed = 2; 620 621#ifdef HAVE_RESIZE_TERM 622 resize_term (screenheight, screenwidth); 623#endif 624 /* turn keypad off while we resize */ 625 if (win_with_focus != TUI_CMD_WIN) 626 keypad (TUI_CMD_WIN->generic.handle, FALSE); 627 tui_update_gdb_sizes (); 628 tui_set_term_height_to (screenheight); 629 tui_set_term_width_to (screenwidth); 630 if (cur_layout == SRC_DISASSEM_COMMAND || 631 cur_layout == SRC_DATA_COMMAND || cur_layout == DISASSEM_DATA_COMMAND) 632 num_wins_displayed++; 633 split_diff = height_diff / num_wins_displayed; 634 cmd_split_diff = split_diff; 635 if (height_diff % num_wins_displayed) 636 { 637 if (height_diff < 0) 638 cmd_split_diff--; 639 else 640 cmd_split_diff++; 641 } 642 /* now adjust each window */ 643 clear (); 644 refresh (); 645 switch (cur_layout) 646 { 647 case SRC_COMMAND: 648 case DISASSEM_COMMAND: 649 first_win = (struct tui_win_info *) (tui_source_windows ())->list[0]; 650 first_win->generic.width += width_diff; 651 locator->width += width_diff; 652 /* check for invalid heights */ 653 if (height_diff == 0) 654 new_height = first_win->generic.height; 655 else if ((first_win->generic.height + split_diff) >= 656 (screenheight - MIN_CMD_WIN_HEIGHT - 1)) 657 new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1; 658 else if ((first_win->generic.height + split_diff) <= 0) 659 new_height = MIN_WIN_HEIGHT; 660 else 661 new_height = first_win->generic.height + split_diff; 662 663 make_invisible_and_set_new_height (first_win, new_height); 664 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1; 665 TUI_CMD_WIN->generic.width += width_diff; 666 new_height = screenheight - TUI_CMD_WIN->generic.origin.y; 667 make_invisible_and_set_new_height (TUI_CMD_WIN, new_height); 668 make_visible_with_new_height (first_win); 669 make_visible_with_new_height (TUI_CMD_WIN); 670 if (first_win->generic.content_size <= 0) 671 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT); 672 break; 673 default: 674 if (cur_layout == SRC_DISASSEM_COMMAND) 675 { 676 first_win = TUI_SRC_WIN; 677 first_win->generic.width += width_diff; 678 second_win = TUI_DISASM_WIN; 679 second_win->generic.width += width_diff; 680 } 681 else 682 { 683 first_win = TUI_DATA_WIN; 684 first_win->generic.width += width_diff; 685 second_win = (struct tui_win_info *) (tui_source_windows ())->list[0]; 686 second_win->generic.width += width_diff; 687 } 688 /* Change the first window's height/width */ 689 /* check for invalid heights */ 690 if (height_diff == 0) 691 new_height = first_win->generic.height; 692 else if ((first_win->generic.height + 693 second_win->generic.height + (split_diff * 2)) >= 694 (screenheight - MIN_CMD_WIN_HEIGHT - 1)) 695 new_height = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2; 696 else if ((first_win->generic.height + split_diff) <= 0) 697 new_height = MIN_WIN_HEIGHT; 698 else 699 new_height = first_win->generic.height + split_diff; 700 make_invisible_and_set_new_height (first_win, new_height); 701 702 locator->width += width_diff; 703 704 /* Change the second window's height/width */ 705 /* check for invalid heights */ 706 if (height_diff == 0) 707 new_height = second_win->generic.height; 708 else if ((first_win->generic.height + 709 second_win->generic.height + (split_diff * 2)) >= 710 (screenheight - MIN_CMD_WIN_HEIGHT - 1)) 711 { 712 new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1; 713 if (new_height % 2) 714 new_height = (new_height / 2) + 1; 715 else 716 new_height /= 2; 717 } 718 else if ((second_win->generic.height + split_diff) <= 0) 719 new_height = MIN_WIN_HEIGHT; 720 else 721 new_height = second_win->generic.height + split_diff; 722 second_win->generic.origin.y = first_win->generic.height - 1; 723 make_invisible_and_set_new_height (second_win, new_height); 724 725 /* Change the command window's height/width */ 726 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1; 727 make_invisible_and_set_new_height ( 728 TUI_CMD_WIN, TUI_CMD_WIN->generic.height + cmd_split_diff); 729 make_visible_with_new_height (first_win); 730 make_visible_with_new_height (second_win); 731 make_visible_with_new_height (TUI_CMD_WIN); 732 if (first_win->generic.content_size <= 0) 733 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT); 734 if (second_win->generic.content_size <= 0) 735 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT); 736 break; 737 } 738 /* 739 ** Now remove all invisible windows, and their content so that they get 740 ** created again when called for with the new size 741 */ 742 for (win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++) 743 { 744 if (win_type != CMD_WIN && (tui_win_list[win_type] != NULL) 745 && !tui_win_list[win_type]->generic.is_visible) 746 { 747 tui_free_window (tui_win_list[win_type]); 748 tui_win_list[win_type] = (struct tui_win_info *) NULL; 749 } 750 } 751 tui_set_win_resized_to (TRUE); 752 /* turn keypad back on, unless focus is in the command window */ 753 if (win_with_focus != TUI_CMD_WIN) 754 keypad (TUI_CMD_WIN->generic.handle, TRUE); 755 } 756} 757 758 759/* SIGWINCH signal handler for the tui. This signal handler is always 760 called, even when the readline package clears signals because it is 761 set as the old_sigwinch() (TUI only). */ 762void 763tui_sigwinch_handler (int signal) 764{ 765 /* 766 ** Say that a resize was done so that the readline can do it 767 ** later when appropriate. 768 */ 769 tui_set_win_resized_to (TRUE); 770} 771 772 773 774/************************* 775** STATIC LOCAL FUNCTIONS 776**************************/ 777 778 779static void 780tui_scroll_forward_command (char *arg, int from_tty) 781{ 782 int num_to_scroll = 1; 783 struct tui_win_info * win_to_scroll; 784 785 /* Make sure the curses mode is enabled. */ 786 tui_enable (); 787 if (arg == (char *) NULL) 788 parse_scrolling_args (arg, &win_to_scroll, (int *) NULL); 789 else 790 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll); 791 tui_scroll (FORWARD_SCROLL, win_to_scroll, num_to_scroll); 792} 793 794 795static void 796tui_scroll_backward_command (char *arg, int from_tty) 797{ 798 int num_to_scroll = 1; 799 struct tui_win_info * win_to_scroll; 800 801 /* Make sure the curses mode is enabled. */ 802 tui_enable (); 803 if (arg == (char *) NULL) 804 parse_scrolling_args (arg, &win_to_scroll, (int *) NULL); 805 else 806 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll); 807 tui_scroll (BACKWARD_SCROLL, win_to_scroll, num_to_scroll); 808} 809 810 811static void 812tui_scroll_left_command (char *arg, int from_tty) 813{ 814 int num_to_scroll; 815 struct tui_win_info * win_to_scroll; 816 817 /* Make sure the curses mode is enabled. */ 818 tui_enable (); 819 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll); 820 tui_scroll (LEFT_SCROLL, win_to_scroll, num_to_scroll); 821} 822 823 824static void 825tui_scroll_right_command (char *arg, int from_tty) 826{ 827 int num_to_scroll; 828 struct tui_win_info * win_to_scroll; 829 830 /* Make sure the curses mode is enabled. */ 831 tui_enable (); 832 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll); 833 tui_scroll (RIGHT_SCROLL, win_to_scroll, num_to_scroll); 834} 835 836 837/* Set focus to the window named by 'arg'. */ 838static void 839tui_set_focus (char *arg, int from_tty) 840{ 841 if (arg != (char *) NULL) 842 { 843 char *buf_ptr = (char *) xstrdup (arg); 844 int i; 845 struct tui_win_info * win_info = (struct tui_win_info *) NULL; 846 847 for (i = 0; (i < strlen (buf_ptr)); i++) 848 buf_ptr[i] = toupper (arg[i]); 849 850 if (subset_compare (buf_ptr, "NEXT")) 851 win_info = tui_next_win (tui_win_with_focus ()); 852 else if (subset_compare (buf_ptr, "PREV")) 853 win_info = tui_prev_win (tui_win_with_focus ()); 854 else 855 win_info = tui_partial_win_by_name (buf_ptr); 856 857 if (win_info == (struct tui_win_info *) NULL || !win_info->generic.is_visible) 858 warning ("Invalid window specified. \n\ 859The window name specified must be valid and visible.\n"); 860 else 861 { 862 tui_set_win_focus_to (win_info); 863 keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN)); 864 } 865 866 if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible) 867 tui_refresh_data_win (); 868 xfree (buf_ptr); 869 printf_filtered ("Focus set to %s window.\n", 870 tui_win_name ((struct tui_gen_win_info *) tui_win_with_focus ())); 871 } 872 else 873 warning ("Incorrect Number of Arguments.\n%s", FOCUS_USAGE); 874} 875 876static void 877tui_set_focus_command (char *arg, int from_tty) 878{ 879 /* Make sure the curses mode is enabled. */ 880 tui_enable (); 881 tui_set_focus (arg, from_tty); 882} 883 884 885static void 886tui_all_windows_info (char *arg, int from_tty) 887{ 888 enum tui_win_type type; 889 struct tui_win_info * win_with_focus = tui_win_with_focus (); 890 891 for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++) 892 if (tui_win_list[type] && tui_win_list[type]->generic.is_visible) 893 { 894 if (win_with_focus == tui_win_list[type]) 895 printf_filtered (" %s\t(%d lines) <has focus>\n", 896 tui_win_name (&tui_win_list[type]->generic), 897 tui_win_list[type]->generic.height); 898 else 899 printf_filtered (" %s\t(%d lines)\n", 900 tui_win_name (&tui_win_list[type]->generic), 901 tui_win_list[type]->generic.height); 902 } 903} 904 905 906static void 907tui_refresh_all_command (char *arg, int from_tty) 908{ 909 /* Make sure the curses mode is enabled. */ 910 tui_enable (); 911 912 tui_refresh_all_win (); 913} 914 915 916/* Set the height of the specified window. */ 917static void 918tui_set_tab_width_command (char *arg, int from_tty) 919{ 920 /* Make sure the curses mode is enabled. */ 921 tui_enable (); 922 if (arg != (char *) NULL) 923 { 924 int ts; 925 926 ts = atoi (arg); 927 if (ts > 0) 928 tui_set_default_tab_len (ts); 929 else 930 warning ("Tab widths greater than 0 must be specified.\n"); 931 } 932} 933 934 935/* Set the height of the specified window. */ 936static void 937tui_set_win_height (char *arg, int from_tty) 938{ 939 /* Make sure the curses mode is enabled. */ 940 tui_enable (); 941 if (arg != (char *) NULL) 942 { 943 char *buf = xstrdup (arg); 944 char *buf_ptr = buf; 945 char *wname = (char *) NULL; 946 int new_height, i; 947 struct tui_win_info * win_info; 948 949 wname = buf_ptr; 950 buf_ptr = strchr (buf_ptr, ' '); 951 if (buf_ptr != (char *) NULL) 952 { 953 *buf_ptr = (char) 0; 954 955 /* 956 ** Validate the window name 957 */ 958 for (i = 0; i < strlen (wname); i++) 959 wname[i] = toupper (wname[i]); 960 win_info = tui_partial_win_by_name (wname); 961 962 if (win_info == (struct tui_win_info *) NULL || !win_info->generic.is_visible) 963 warning ("Invalid window specified. \n\ 964The window name specified must be valid and visible.\n"); 965 else 966 { 967 /* Process the size */ 968 while (*(++buf_ptr) == ' ') 969 ; 970 971 if (*buf_ptr != (char) 0) 972 { 973 int negate = FALSE; 974 int fixed_size = TRUE; 975 int input_no;; 976 977 if (*buf_ptr == '+' || *buf_ptr == '-') 978 { 979 if (*buf_ptr == '-') 980 negate = TRUE; 981 fixed_size = FALSE; 982 buf_ptr++; 983 } 984 input_no = atoi (buf_ptr); 985 if (input_no > 0) 986 { 987 if (negate) 988 input_no *= (-1); 989 if (fixed_size) 990 new_height = input_no; 991 else 992 new_height = win_info->generic.height + input_no; 993 /* 994 ** Now change the window's height, and adjust all 995 ** other windows around it 996 */ 997 if (tui_adjust_win_heights (win_info, 998 new_height) == TUI_FAILURE) 999 warning ("Invalid window height specified.\n%s", 1000 WIN_HEIGHT_USAGE); 1001 else 1002 tui_update_gdb_sizes (); 1003 } 1004 else 1005 warning ("Invalid window height specified.\n%s", 1006 WIN_HEIGHT_USAGE); 1007 } 1008 } 1009 } 1010 else 1011 printf_filtered (WIN_HEIGHT_USAGE); 1012 1013 if (buf != (char *) NULL) 1014 xfree (buf); 1015 } 1016 else 1017 printf_filtered (WIN_HEIGHT_USAGE); 1018} 1019 1020/* Set the height of the specified window, with va_list. */ 1021static void 1022tui_set_win_height_command (char *arg, int from_tty) 1023{ 1024 /* Make sure the curses mode is enabled. */ 1025 tui_enable (); 1026 tui_set_win_height (arg, from_tty); 1027} 1028 1029 1030/* XDB Compatibility command for setting the window height. This will 1031 increase or decrease the command window by the specified amount. */ 1032static void 1033tui_xdb_set_win_height (char *arg, int from_tty) 1034{ 1035 /* Make sure the curses mode is enabled. */ 1036 tui_enable (); 1037 if (arg != (char *) NULL) 1038 { 1039 int input_no = atoi (arg); 1040 1041 if (input_no > 0) 1042 { /* Add 1 for the locator */ 1043 int new_height = tui_term_height () - (input_no + 1); 1044 1045 if (!new_height_ok (tui_win_list[CMD_WIN], new_height) || 1046 tui_adjust_win_heights (tui_win_list[CMD_WIN], 1047 new_height) == TUI_FAILURE) 1048 warning ("Invalid window height specified.\n%s", 1049 XDBWIN_HEIGHT_USAGE); 1050 } 1051 else 1052 warning ("Invalid window height specified.\n%s", 1053 XDBWIN_HEIGHT_USAGE); 1054 } 1055 else 1056 warning ("Invalid window height specified.\n%s", XDBWIN_HEIGHT_USAGE); 1057} 1058 1059/* Set the height of the specified window, with va_list. */ 1060static void 1061tui_xdb_set_win_height_command (char *arg, int from_tty) 1062{ 1063 tui_xdb_set_win_height (arg, from_tty); 1064} 1065 1066 1067/* Function to adjust all window heights around the primary. */ 1068static enum tui_status 1069tui_adjust_win_heights (struct tui_win_info * primary_win_info, int new_height) 1070{ 1071 enum tui_status status = TUI_FAILURE; 1072 1073 if (new_height_ok (primary_win_info, new_height)) 1074 { 1075 status = TUI_SUCCESS; 1076 if (new_height != primary_win_info->generic.height) 1077 { 1078 int diff; 1079 struct tui_win_info * win_info; 1080 struct tui_gen_win_info * locator = tui_locator_win_info_ptr (); 1081 enum tui_layout_type cur_layout = tui_current_layout (); 1082 1083 diff = (new_height - primary_win_info->generic.height) * (-1); 1084 if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND) 1085 { 1086 struct tui_win_info * src_win_info; 1087 1088 make_invisible_and_set_new_height (primary_win_info, new_height); 1089 if (primary_win_info->generic.type == CMD_WIN) 1090 { 1091 win_info = (struct tui_win_info *) (tui_source_windows ())->list[0]; 1092 src_win_info = win_info; 1093 } 1094 else 1095 { 1096 win_info = tui_win_list[CMD_WIN]; 1097 src_win_info = primary_win_info; 1098 } 1099 make_invisible_and_set_new_height (win_info, 1100 win_info->generic.height + diff); 1101 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1; 1102 make_visible_with_new_height (win_info); 1103 make_visible_with_new_height (primary_win_info); 1104 if (src_win_info->generic.content_size <= 0) 1105 tui_erase_source_content (src_win_info, EMPTY_SOURCE_PROMPT); 1106 } 1107 else 1108 { 1109 struct tui_win_info *first_win; 1110 struct tui_win_info *second_win; 1111 1112 if (cur_layout == SRC_DISASSEM_COMMAND) 1113 { 1114 first_win = TUI_SRC_WIN; 1115 second_win = TUI_DISASM_WIN; 1116 } 1117 else 1118 { 1119 first_win = TUI_DATA_WIN; 1120 second_win = (struct tui_win_info *) (tui_source_windows ())->list[0]; 1121 } 1122 if (primary_win_info == TUI_CMD_WIN) 1123 { /* 1124 ** Split the change in height accross the 1st & 2nd windows 1125 ** adjusting them as well. 1126 */ 1127 int first_split_diff = diff / 2; /* subtract the locator */ 1128 int second_split_diff = first_split_diff; 1129 1130 if (diff % 2) 1131 { 1132 if (first_win->generic.height > 1133 second_win->generic.height) 1134 if (diff < 0) 1135 first_split_diff--; 1136 else 1137 first_split_diff++; 1138 else 1139 { 1140 if (diff < 0) 1141 second_split_diff--; 1142 else 1143 second_split_diff++; 1144 } 1145 } 1146 /* make sure that the minimum hieghts are honored */ 1147 while ((first_win->generic.height + first_split_diff) < 3) 1148 { 1149 first_split_diff++; 1150 second_split_diff--; 1151 } 1152 while ((second_win->generic.height + second_split_diff) < 3) 1153 { 1154 second_split_diff++; 1155 first_split_diff--; 1156 } 1157 make_invisible_and_set_new_height ( 1158 first_win, 1159 first_win->generic.height + first_split_diff); 1160 second_win->generic.origin.y = first_win->generic.height - 1; 1161 make_invisible_and_set_new_height ( 1162 second_win, second_win->generic.height + second_split_diff); 1163 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1; 1164 make_invisible_and_set_new_height (TUI_CMD_WIN, new_height); 1165 } 1166 else 1167 { 1168 if ((TUI_CMD_WIN->generic.height + diff) < 1) 1169 { /* 1170 ** If there is no way to increase the command window 1171 ** take real estate from the 1st or 2nd window. 1172 */ 1173 if ((TUI_CMD_WIN->generic.height + diff) < 1) 1174 { 1175 int i; 1176 for (i = TUI_CMD_WIN->generic.height + diff; 1177 (i < 1); i++) 1178 if (primary_win_info == first_win) 1179 second_win->generic.height--; 1180 else 1181 first_win->generic.height--; 1182 } 1183 } 1184 if (primary_win_info == first_win) 1185 make_invisible_and_set_new_height (first_win, new_height); 1186 else 1187 make_invisible_and_set_new_height ( 1188 first_win, 1189 first_win->generic.height); 1190 second_win->generic.origin.y = first_win->generic.height - 1; 1191 if (primary_win_info == second_win) 1192 make_invisible_and_set_new_height (second_win, new_height); 1193 else 1194 make_invisible_and_set_new_height ( 1195 second_win, second_win->generic.height); 1196 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1; 1197 if ((TUI_CMD_WIN->generic.height + diff) < 1) 1198 make_invisible_and_set_new_height (TUI_CMD_WIN, 1); 1199 else 1200 make_invisible_and_set_new_height ( 1201 TUI_CMD_WIN, TUI_CMD_WIN->generic.height + diff); 1202 } 1203 make_visible_with_new_height (TUI_CMD_WIN); 1204 make_visible_with_new_height (second_win); 1205 make_visible_with_new_height (first_win); 1206 if (first_win->generic.content_size <= 0) 1207 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT); 1208 if (second_win->generic.content_size <= 0) 1209 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT); 1210 } 1211 } 1212 } 1213 1214 return status; 1215} 1216 1217 1218/* Function make the target window (and auxillary windows associated 1219 with the targer) invisible, and set the new height and location. */ 1220static void 1221make_invisible_and_set_new_height (struct tui_win_info * win_info, int height) 1222{ 1223 int i; 1224 struct tui_gen_win_info * gen_win_info; 1225 1226 tui_make_invisible (&win_info->generic); 1227 win_info->generic.height = height; 1228 if (height > 1) 1229 win_info->generic.viewport_height = height - 1; 1230 else 1231 win_info->generic.viewport_height = height; 1232 if (win_info != TUI_CMD_WIN) 1233 win_info->generic.viewport_height--; 1234 1235 /* Now deal with the auxillary windows associated with win_info */ 1236 switch (win_info->generic.type) 1237 { 1238 case SRC_WIN: 1239 case DISASSEM_WIN: 1240 gen_win_info = win_info->detail.source_info.execution_info; 1241 tui_make_invisible (gen_win_info); 1242 gen_win_info->height = height; 1243 gen_win_info->origin.y = win_info->generic.origin.y; 1244 if (height > 1) 1245 gen_win_info->viewport_height = height - 1; 1246 else 1247 gen_win_info->viewport_height = height; 1248 if (win_info != TUI_CMD_WIN) 1249 gen_win_info->viewport_height--; 1250 1251 if (tui_win_has_locator (win_info)) 1252 { 1253 gen_win_info = tui_locator_win_info_ptr (); 1254 tui_make_invisible (gen_win_info); 1255 gen_win_info->origin.y = win_info->generic.origin.y + height; 1256 } 1257 break; 1258 case DATA_WIN: 1259 /* delete all data item windows */ 1260 for (i = 0; i < win_info->generic.content_size; i++) 1261 { 1262 gen_win_info = (struct tui_gen_win_info *) & ((struct tui_win_element *) 1263 win_info->generic.content[i])->which_element.data_window; 1264 tui_delete_win (gen_win_info->handle); 1265 gen_win_info->handle = (WINDOW *) NULL; 1266 } 1267 break; 1268 default: 1269 break; 1270 } 1271} 1272 1273 1274/* Function to make the windows with new heights visible. This means 1275 re-creating the windows' content since the window had to be 1276 destroyed to be made invisible. */ 1277static void 1278make_visible_with_new_height (struct tui_win_info * win_info) 1279{ 1280 struct symtab *s; 1281 1282 tui_make_visible (&win_info->generic); 1283 tui_check_and_display_highlight_if_needed (win_info); 1284 switch (win_info->generic.type) 1285 { 1286 case SRC_WIN: 1287 case DISASSEM_WIN: 1288 tui_free_win_content (win_info->detail.source_info.execution_info); 1289 tui_make_visible (win_info->detail.source_info.execution_info); 1290 if (win_info->generic.content != NULL) 1291 { 1292 union tui_line_or_address line_or_addr; 1293 struct symtab_and_line cursal 1294 = get_current_source_symtab_and_line (); 1295 1296 if (win_info->generic.type == SRC_WIN) 1297 line_or_addr.line_no = 1298 win_info->detail.source_info.start_line_or_addr.line_no; 1299 else 1300 line_or_addr.addr = 1301 win_info->detail.source_info.start_line_or_addr.addr; 1302 tui_free_win_content (&win_info->generic); 1303 tui_update_source_window (win_info, cursal.symtab, line_or_addr, TRUE); 1304 } 1305 else if (deprecated_selected_frame != (struct frame_info *) NULL) 1306 { 1307 union tui_line_or_address line; 1308 struct symtab_and_line cursal = get_current_source_symtab_and_line (); 1309 1310 1311 s = find_pc_symtab (get_frame_pc (deprecated_selected_frame)); 1312 if (win_info->generic.type == SRC_WIN) 1313 line.line_no = cursal.line; 1314 else 1315 { 1316 find_line_pc (s, cursal.line, &line.addr); 1317 } 1318 tui_update_source_window (win_info, s, line, TRUE); 1319 } 1320 if (tui_win_has_locator (win_info)) 1321 { 1322 tui_make_visible (tui_locator_win_info_ptr ()); 1323 tui_show_locator_content (); 1324 } 1325 break; 1326 case DATA_WIN: 1327 tui_display_all_data (); 1328 break; 1329 case CMD_WIN: 1330 win_info->detail.command_info.cur_line = 0; 1331 win_info->detail.command_info.curch = 0; 1332 wmove (win_info->generic.handle, 1333 win_info->detail.command_info.cur_line, 1334 win_info->detail.command_info.curch); 1335 break; 1336 default: 1337 break; 1338 } 1339} 1340 1341 1342static int 1343new_height_ok (struct tui_win_info * primary_win_info, int new_height) 1344{ 1345 int ok = (new_height < tui_term_height ()); 1346 1347 if (ok) 1348 { 1349 int diff; 1350 enum tui_layout_type cur_layout = tui_current_layout (); 1351 1352 diff = (new_height - primary_win_info->generic.height) * (-1); 1353 if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND) 1354 { 1355 ok = ((primary_win_info->generic.type == CMD_WIN && 1356 new_height <= (tui_term_height () - 4) && 1357 new_height >= MIN_CMD_WIN_HEIGHT) || 1358 (primary_win_info->generic.type != CMD_WIN && 1359 new_height <= (tui_term_height () - 2) && 1360 new_height >= MIN_WIN_HEIGHT)); 1361 if (ok) 1362 { /* check the total height */ 1363 struct tui_win_info * win_info; 1364 1365 if (primary_win_info == TUI_CMD_WIN) 1366 win_info = (struct tui_win_info *) (tui_source_windows ())->list[0]; 1367 else 1368 win_info = TUI_CMD_WIN; 1369 ok = ((new_height + 1370 (win_info->generic.height + diff)) <= tui_term_height ()); 1371 } 1372 } 1373 else 1374 { 1375 int cur_total_height, total_height, min_height = 0; 1376 struct tui_win_info *first_win; 1377 struct tui_win_info *second_win; 1378 1379 if (cur_layout == SRC_DISASSEM_COMMAND) 1380 { 1381 first_win = TUI_SRC_WIN; 1382 second_win = TUI_DISASM_WIN; 1383 } 1384 else 1385 { 1386 first_win = TUI_DATA_WIN; 1387 second_win = (struct tui_win_info *) (tui_source_windows ())->list[0]; 1388 } 1389 /* 1390 ** We could simply add all the heights to obtain the same result 1391 ** but below is more explicit since we subtract 1 for the 1392 ** line that the first and second windows share, and add one 1393 ** for the locator. 1394 */ 1395 total_height = cur_total_height = 1396 (first_win->generic.height + second_win->generic.height - 1) 1397 + TUI_CMD_WIN->generic.height + 1 /*locator */ ; 1398 if (primary_win_info == TUI_CMD_WIN) 1399 { 1400 /* locator included since first & second win share a line */ 1401 ok = ((first_win->generic.height + 1402 second_win->generic.height + diff) >= 1403 (MIN_WIN_HEIGHT * 2) && 1404 new_height >= MIN_CMD_WIN_HEIGHT); 1405 if (ok) 1406 { 1407 total_height = new_height + (first_win->generic.height + 1408 second_win->generic.height + diff); 1409 min_height = MIN_CMD_WIN_HEIGHT; 1410 } 1411 } 1412 else 1413 { 1414 min_height = MIN_WIN_HEIGHT; 1415 /* 1416 ** First see if we can increase/decrease the command 1417 ** window. And make sure that the command window is 1418 ** at least 1 line 1419 */ 1420 ok = ((TUI_CMD_WIN->generic.height + diff) > 0); 1421 if (!ok) 1422 { /* 1423 ** Looks like we have to increase/decrease one of 1424 ** the other windows 1425 */ 1426 if (primary_win_info == first_win) 1427 ok = (second_win->generic.height + diff) >= min_height; 1428 else 1429 ok = (first_win->generic.height + diff) >= min_height; 1430 } 1431 if (ok) 1432 { 1433 if (primary_win_info == first_win) 1434 total_height = new_height + 1435 second_win->generic.height + 1436 TUI_CMD_WIN->generic.height + diff; 1437 else 1438 total_height = new_height + 1439 first_win->generic.height + 1440 TUI_CMD_WIN->generic.height + diff; 1441 } 1442 } 1443 /* 1444 ** Now make sure that the proposed total height doesn't exceed 1445 ** the old total height. 1446 */ 1447 if (ok) 1448 ok = (new_height >= min_height && total_height <= cur_total_height); 1449 } 1450 } 1451 1452 return ok; 1453} 1454 1455 1456static void 1457parse_scrolling_args (char *arg, struct tui_win_info * * win_to_scroll, 1458 int *num_to_scroll) 1459{ 1460 if (num_to_scroll) 1461 *num_to_scroll = 0; 1462 *win_to_scroll = tui_win_with_focus (); 1463 1464 /* 1465 ** First set up the default window to scroll, in case there is no 1466 ** window name arg 1467 */ 1468 if (arg != (char *) NULL) 1469 { 1470 char *buf, *buf_ptr; 1471 1472 /* process the number of lines to scroll */ 1473 buf = buf_ptr = xstrdup (arg); 1474 if (isdigit (*buf_ptr)) 1475 { 1476 char *num_str; 1477 1478 num_str = buf_ptr; 1479 buf_ptr = strchr (buf_ptr, ' '); 1480 if (buf_ptr != (char *) NULL) 1481 { 1482 *buf_ptr = (char) 0; 1483 if (num_to_scroll) 1484 *num_to_scroll = atoi (num_str); 1485 buf_ptr++; 1486 } 1487 else if (num_to_scroll) 1488 *num_to_scroll = atoi (num_str); 1489 } 1490 1491 /* process the window name if one is specified */ 1492 if (buf_ptr != (char *) NULL) 1493 { 1494 char *wname; 1495 int i; 1496 1497 if (*buf_ptr == ' ') 1498 while (*(++buf_ptr) == ' ') 1499 ; 1500 1501 if (*buf_ptr != (char) 0) 1502 wname = buf_ptr; 1503 else 1504 wname = "?"; 1505 1506 /* Validate the window name */ 1507 for (i = 0; i < strlen (wname); i++) 1508 wname[i] = toupper (wname[i]); 1509 *win_to_scroll = tui_partial_win_by_name (wname); 1510 1511 if (*win_to_scroll == (struct tui_win_info *) NULL || 1512 !(*win_to_scroll)->generic.is_visible) 1513 warning ("Invalid window specified. \n\ 1514The window name specified must be valid and visible.\n"); 1515 else if (*win_to_scroll == TUI_CMD_WIN) 1516 *win_to_scroll = (struct tui_win_info *) (tui_source_windows ())->list[0]; 1517 } 1518 xfree (buf); 1519 } 1520} 1521