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