1 /* TUI data manipulation routines. 2 3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 4 2009 Free Software 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 3 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, see <http://www.gnu.org/licenses/>. */ 22 23 #include "defs.h" 24 #include "symtab.h" 25 #include "tui/tui.h" 26 #include "tui/tui-data.h" 27 #include "tui/tui-wingeneral.h" 28 29 #include "gdb_string.h" 30 #include "gdb_curses.h" 31 32 /**************************** 33 ** GLOBAL DECLARATIONS 34 ****************************/ 35 struct tui_win_info *(tui_win_list[MAX_MAJOR_WINDOWS]); 36 37 /*************************** 38 ** Private data 39 ****************************/ 40 static enum tui_layout_type current_layout = UNDEFINED_LAYOUT; 41 static int term_height, term_width; 42 static struct tui_gen_win_info _locator; 43 static struct tui_gen_win_info exec_info[2]; 44 static struct tui_win_info *src_win_list[2]; 45 static struct tui_list source_windows = {src_win_list, 0}; 46 static int default_tab_len = DEFAULT_TAB_LEN; 47 static struct tui_win_info *win_with_focus = (struct tui_win_info *) NULL; 48 static struct tui_layout_def layout_def = { 49 SRC_WIN, /* DISPLAY_MODE */ 50 FALSE, /* SPLIT */ 51 TUI_UNDEFINED_REGS, /* REGS_DISPLAY_TYPE */ 52 TUI_SFLOAT_REGS}; /* FLOAT_REGS_DISPLAY_TYPE */ 53 54 static int win_resized = FALSE; 55 56 57 /********************************* 58 ** Static function forward decls 59 **********************************/ 60 static void free_content (tui_win_content, 61 int, 62 enum tui_win_type); 63 static void free_content_elements (tui_win_content, 64 int, 65 enum tui_win_type); 66 67 68 69 /********************************* 70 ** PUBLIC FUNCTIONS 71 **********************************/ 72 73 int 74 tui_win_is_source_type (enum tui_win_type win_type) 75 { 76 return (win_type == SRC_WIN || win_type == DISASSEM_WIN); 77 } 78 79 int 80 tui_win_is_auxillary (enum tui_win_type win_type) 81 { 82 return (win_type > MAX_MAJOR_WINDOWS); 83 } 84 85 int 86 tui_win_has_locator (struct tui_win_info *win_info) 87 { 88 return (win_info != NULL 89 && win_info->detail.source_info.has_locator); 90 } 91 92 void 93 tui_set_win_highlight (struct tui_win_info *win_info, 94 int highlight) 95 { 96 if (win_info != NULL) 97 win_info->is_highlighted = highlight; 98 } 99 100 /****************************************** 101 ** ACCESSORS & MUTATORS FOR PRIVATE DATA 102 ******************************************/ 103 104 /* Answer a whether the terminal window has been resized or not. */ 105 int 106 tui_win_resized (void) 107 { 108 return win_resized; 109 } 110 111 112 /* Set a whether the terminal window has been resized or not. */ 113 void 114 tui_set_win_resized_to (int resized) 115 { 116 win_resized = resized; 117 } 118 119 120 /* Answer a pointer to the current layout definition. */ 121 struct tui_layout_def * 122 tui_layout_def (void) 123 { 124 return &layout_def; 125 } 126 127 128 /* Answer the window with the logical focus. */ 129 struct tui_win_info * 130 tui_win_with_focus (void) 131 { 132 return win_with_focus; 133 } 134 135 136 /* Set the window that has the logical focus. */ 137 void 138 tui_set_win_with_focus (struct tui_win_info *win_info) 139 { 140 win_with_focus = win_info; 141 } 142 143 144 /* Answer the length in chars, of tabs. */ 145 int 146 tui_default_tab_len (void) 147 { 148 return default_tab_len; 149 } 150 151 152 /* Set the length in chars, of tabs. */ 153 void 154 tui_set_default_tab_len (int len) 155 { 156 default_tab_len = len; 157 } 158 159 160 /* Accessor for the current source window. Usually there is only one 161 source window (either source or disassembly), but both can be 162 displayed at the same time. */ 163 struct tui_list * 164 tui_source_windows (void) 165 { 166 return &source_windows; 167 } 168 169 170 /* Clear the list of source windows. Usually there is only one source 171 window (either source or disassembly), but both can be displayed at 172 the same time. */ 173 void 174 tui_clear_source_windows (void) 175 { 176 source_windows.list[0] = NULL; 177 source_windows.list[1] = NULL; 178 source_windows.count = 0; 179 } 180 181 182 /* Clear the pertinant detail in the source windows. */ 183 void 184 tui_clear_source_windows_detail (void) 185 { 186 int i; 187 188 for (i = 0; i < (tui_source_windows ())->count; i++) 189 tui_clear_win_detail ((tui_source_windows ())->list[i]); 190 } 191 192 193 /* Add a window to the list of source windows. Usually there is only 194 one source window (either source or disassembly), but both can be 195 displayed at the same time. */ 196 void 197 tui_add_to_source_windows (struct tui_win_info *win_info) 198 { 199 if (source_windows.count < 2) 200 source_windows.list[source_windows.count++] = (void *) win_info; 201 } 202 203 204 /* Clear the pertinant detail in the windows. */ 205 void 206 tui_clear_win_detail (struct tui_win_info *win_info) 207 { 208 if (win_info != NULL) 209 { 210 switch (win_info->generic.type) 211 { 212 case SRC_WIN: 213 case DISASSEM_WIN: 214 win_info->detail.source_info.gdbarch = NULL; 215 win_info->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS; 216 win_info->detail.source_info.start_line_or_addr.u.addr = 0; 217 win_info->detail.source_info.horizontal_offset = 0; 218 break; 219 case CMD_WIN: 220 win_info->detail.command_info.cur_line = 221 win_info->detail.command_info.curch = 0; 222 break; 223 case DATA_WIN: 224 win_info->detail.data_display_info.data_content = 225 (tui_win_content) NULL; 226 win_info->detail.data_display_info.data_content_count = 0; 227 win_info->detail.data_display_info.regs_content = 228 (tui_win_content) NULL; 229 win_info->detail.data_display_info.regs_content_count = 0; 230 win_info->detail.data_display_info.regs_display_type = 231 TUI_UNDEFINED_REGS; 232 win_info->detail.data_display_info.regs_column_count = 1; 233 win_info->detail.data_display_info.display_regs = FALSE; 234 break; 235 default: 236 break; 237 } 238 } 239 } 240 241 242 /* Accessor for the source execution info ptr. */ 243 struct tui_gen_win_info * 244 tui_source_exec_info_win_ptr (void) 245 { 246 return &exec_info[0]; 247 } 248 249 250 /* Accessor for the disassem execution info ptr. */ 251 struct tui_gen_win_info * 252 tui_disassem_exec_info_win_ptr (void) 253 { 254 return &exec_info[1]; 255 } 256 257 258 /* Accessor for the locator win info. Answers a pointer to the static 259 locator win info struct. */ 260 struct tui_gen_win_info * 261 tui_locator_win_info_ptr (void) 262 { 263 return &_locator; 264 } 265 266 267 /* Accessor for the term_height. */ 268 int 269 tui_term_height (void) 270 { 271 return term_height; 272 } 273 274 275 /* Mutator for the term height. */ 276 void 277 tui_set_term_height_to (int h) 278 { 279 term_height = h; 280 } 281 282 283 /* Accessor for the term_width. */ 284 int 285 tui_term_width (void) 286 { 287 return term_width; 288 } 289 290 291 /* Mutator for the term_width. */ 292 void 293 tui_set_term_width_to (int w) 294 { 295 term_width = w; 296 } 297 298 299 /* Accessor for the current layout. */ 300 enum tui_layout_type 301 tui_current_layout (void) 302 { 303 return current_layout; 304 } 305 306 307 /* Mutator for the current layout. */ 308 void 309 tui_set_current_layout_to (enum tui_layout_type new_layout) 310 { 311 current_layout = new_layout; 312 } 313 314 315 /* Set the origin of the window. */ 316 void 317 set_gen_win_origin (struct tui_gen_win_info *win_info, 318 int x, int y) 319 { 320 win_info->origin.x = x; 321 win_info->origin.y = y; 322 } 323 324 325 /***************************** 326 ** OTHER PUBLIC FUNCTIONS 327 *****************************/ 328 329 330 /* Answer the next window in the list, cycling back to the top if 331 necessary. */ 332 struct tui_win_info * 333 tui_next_win (struct tui_win_info *cur_win) 334 { 335 enum tui_win_type type = cur_win->generic.type; 336 struct tui_win_info *next_win = (struct tui_win_info *) NULL; 337 338 if (cur_win->generic.type == CMD_WIN) 339 type = SRC_WIN; 340 else 341 type = cur_win->generic.type + 1; 342 while (type != cur_win->generic.type && (next_win == NULL)) 343 { 344 if (tui_win_list[type] 345 && tui_win_list[type]->generic.is_visible) 346 next_win = tui_win_list[type]; 347 else 348 { 349 if (type == CMD_WIN) 350 type = SRC_WIN; 351 else 352 type++; 353 } 354 } 355 356 return next_win; 357 } 358 359 360 /* Answer the prev window in the list, cycling back to the bottom if 361 necessary. */ 362 struct tui_win_info * 363 tui_prev_win (struct tui_win_info *cur_win) 364 { 365 enum tui_win_type type = cur_win->generic.type; 366 struct tui_win_info *prev = (struct tui_win_info *) NULL; 367 368 if (cur_win->generic.type == SRC_WIN) 369 type = CMD_WIN; 370 else 371 type = cur_win->generic.type - 1; 372 while (type != cur_win->generic.type && (prev == NULL)) 373 { 374 if (tui_win_list[type] 375 && tui_win_list[type]->generic.is_visible) 376 prev = tui_win_list[type]; 377 else 378 { 379 if (type == SRC_WIN) 380 type = CMD_WIN; 381 else 382 type--; 383 } 384 } 385 386 return prev; 387 } 388 389 390 /* Answer the window represented by name. */ 391 struct tui_win_info * 392 tui_partial_win_by_name (char *name) 393 { 394 struct tui_win_info *win_info = (struct tui_win_info *) NULL; 395 396 if (name != (char *) NULL) 397 { 398 int i = 0; 399 400 while (i < MAX_MAJOR_WINDOWS && win_info == NULL) 401 { 402 if (tui_win_list[i] != 0) 403 { 404 char *cur_name = tui_win_name (&tui_win_list[i]->generic); 405 if (strlen (name) <= strlen (cur_name) 406 && strncmp (name, cur_name, strlen (name)) == 0) 407 win_info = tui_win_list[i]; 408 } 409 i++; 410 } 411 } 412 413 return win_info; 414 } 415 416 417 /* Answer the name of the window. */ 418 char * 419 tui_win_name (struct tui_gen_win_info *win_info) 420 { 421 char *name = (char *) NULL; 422 423 switch (win_info->type) 424 { 425 case SRC_WIN: 426 name = SRC_NAME; 427 break; 428 case CMD_WIN: 429 name = CMD_NAME; 430 break; 431 case DISASSEM_WIN: 432 name = DISASSEM_NAME; 433 break; 434 case DATA_WIN: 435 name = DATA_NAME; 436 break; 437 default: 438 name = ""; 439 break; 440 } 441 442 return name; 443 } 444 445 446 void 447 tui_initialize_static_data (void) 448 { 449 tui_init_generic_part (tui_source_exec_info_win_ptr ()); 450 tui_init_generic_part (tui_disassem_exec_info_win_ptr ()); 451 tui_init_generic_part (tui_locator_win_info_ptr ()); 452 } 453 454 455 struct tui_gen_win_info * 456 tui_alloc_generic_win_info (void) 457 { 458 struct tui_gen_win_info *win; 459 460 if ((win = XMALLOC (struct tui_gen_win_info)) != NULL) 461 tui_init_generic_part (win); 462 463 return win; 464 } 465 466 467 void 468 tui_init_generic_part (struct tui_gen_win_info *win) 469 { 470 win->width = 471 win->height = 472 win->origin.x = 473 win->origin.y = 474 win->viewport_height = 475 win->content_size = 476 win->last_visible_line = 0; 477 win->handle = (WINDOW *) NULL; 478 win->content = NULL; 479 win->content_in_use = 480 win->is_visible = FALSE; 481 win->title = 0; 482 } 483 484 485 /* init_content_element(). 486 */ 487 static void 488 init_content_element (struct tui_win_element *element, 489 enum tui_win_type type) 490 { 491 element->highlight = FALSE; 492 switch (type) 493 { 494 case SRC_WIN: 495 case DISASSEM_WIN: 496 element->which_element.source.line = (char *) NULL; 497 element->which_element.source.line_or_addr.loa = LOA_LINE; 498 element->which_element.source.line_or_addr.u.line_no = 0; 499 element->which_element.source.is_exec_point = FALSE; 500 element->which_element.source.has_break = FALSE; 501 break; 502 case DATA_WIN: 503 tui_init_generic_part (&element->which_element.data_window); 504 element->which_element.data_window.type = DATA_ITEM_WIN; 505 ((struct tui_gen_win_info *) & element->which_element.data_window)->content = 506 (void **) tui_alloc_content (1, DATA_ITEM_WIN); 507 ((struct tui_gen_win_info *) 508 & element->which_element.data_window)->content_size = 1; 509 break; 510 case CMD_WIN: 511 element->which_element.command.line = (char *) NULL; 512 break; 513 case DATA_ITEM_WIN: 514 element->which_element.data.name = (char *) NULL; 515 element->which_element.data.type = TUI_REGISTER; 516 element->which_element.data.item_no = UNDEFINED_ITEM; 517 element->which_element.data.value = NULL; 518 element->which_element.data.highlight = FALSE; 519 element->which_element.data.content = (char*) NULL; 520 break; 521 case LOCATOR_WIN: 522 element->which_element.locator.file_name[0] = 523 element->which_element.locator.proc_name[0] = (char) 0; 524 element->which_element.locator.line_no = 0; 525 element->which_element.locator.addr = 0; 526 break; 527 case EXEC_INFO_WIN: 528 memset(element->which_element.simple_string, ' ', 529 sizeof(element->which_element.simple_string)); 530 break; 531 default: 532 break; 533 } 534 } 535 536 static void 537 init_win_info (struct tui_win_info *win_info) 538 { 539 tui_init_generic_part (&win_info->generic); 540 win_info->can_highlight = 541 win_info->is_highlighted = FALSE; 542 switch (win_info->generic.type) 543 { 544 case SRC_WIN: 545 case DISASSEM_WIN: 546 win_info->detail.source_info.execution_info = (struct tui_gen_win_info *) NULL; 547 win_info->detail.source_info.has_locator = FALSE; 548 win_info->detail.source_info.horizontal_offset = 0; 549 win_info->detail.source_info.gdbarch = NULL; 550 win_info->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS; 551 win_info->detail.source_info.start_line_or_addr.u.addr = 0; 552 win_info->detail.source_info.filename = 0; 553 break; 554 case DATA_WIN: 555 win_info->detail.data_display_info.data_content = (tui_win_content) NULL; 556 win_info->detail.data_display_info.data_content_count = 0; 557 win_info->detail.data_display_info.regs_content = (tui_win_content) NULL; 558 win_info->detail.data_display_info.regs_content_count = 0; 559 win_info->detail.data_display_info.regs_display_type = 560 TUI_UNDEFINED_REGS; 561 win_info->detail.data_display_info.regs_column_count = 1; 562 win_info->detail.data_display_info.display_regs = FALSE; 563 win_info->detail.data_display_info.current_group = 0; 564 break; 565 case CMD_WIN: 566 win_info->detail.command_info.cur_line = 0; 567 win_info->detail.command_info.curch = 0; 568 break; 569 default: 570 win_info->detail.opaque = NULL; 571 break; 572 } 573 } 574 575 576 struct tui_win_info * 577 tui_alloc_win_info (enum tui_win_type type) 578 { 579 struct tui_win_info *win_info; 580 581 win_info = XMALLOC (struct tui_win_info); 582 if (win_info != NULL) 583 { 584 win_info->generic.type = type; 585 init_win_info (win_info); 586 } 587 588 return win_info; 589 } 590 591 592 /* Allocates the content and elements in a block. */ 593 tui_win_content 594 tui_alloc_content (int num_elements, enum tui_win_type type) 595 { 596 tui_win_content content; 597 char *element_block_ptr; 598 int i; 599 600 content = xmalloc (sizeof (struct tui_win_element *) *num_elements); 601 if (content != NULL) 602 { 603 /* 604 * All windows, except the data window, can allocate the 605 * elements in a chunk. The data window cannot because items 606 * can be added/removed from the data display by the user at any 607 * time. 608 */ 609 if (type != DATA_WIN) 610 { 611 element_block_ptr = 612 xmalloc (sizeof (struct tui_win_element) * num_elements); 613 if (element_block_ptr != NULL) 614 { 615 for (i = 0; i < num_elements; i++) 616 { 617 content[i] = (struct tui_win_element *) element_block_ptr; 618 init_content_element (content[i], type); 619 element_block_ptr += sizeof (struct tui_win_element); 620 } 621 } 622 else 623 { 624 xfree (content); 625 content = (tui_win_content) NULL; 626 } 627 } 628 } 629 630 return content; 631 } 632 633 634 /* Adds the input number of elements to the windows's content. If no 635 content has been allocated yet, alloc_content() is called to do 636 this. The index of the first element added is returned, unless 637 there is a memory allocation error, in which case, (-1) is 638 returned. */ 639 int 640 tui_add_content_elements (struct tui_gen_win_info *win_info, 641 int num_elements) 642 { 643 struct tui_win_element *element_ptr; 644 int i, index_start; 645 646 if (win_info->content == NULL) 647 { 648 win_info->content = (void **) tui_alloc_content (num_elements, win_info->type); 649 index_start = 0; 650 } 651 else 652 index_start = win_info->content_size; 653 if (win_info->content != NULL) 654 { 655 for (i = index_start; (i < num_elements + index_start); i++) 656 { 657 if ((element_ptr = XMALLOC (struct tui_win_element)) != NULL) 658 { 659 win_info->content[i] = (void *) element_ptr; 660 init_content_element (element_ptr, win_info->type); 661 win_info->content_size++; 662 } 663 else /* Things must be really hosed now! We ran out of 664 memory!? */ 665 return (-1); 666 } 667 } 668 669 return index_start; 670 } 671 672 673 /* Delete all curses windows associated with win_info, leaving 674 everything else intact. */ 675 void 676 tui_del_window (struct tui_win_info *win_info) 677 { 678 struct tui_gen_win_info *generic_win; 679 680 switch (win_info->generic.type) 681 { 682 case SRC_WIN: 683 case DISASSEM_WIN: 684 generic_win = tui_locator_win_info_ptr (); 685 if (generic_win != (struct tui_gen_win_info *) NULL) 686 { 687 tui_delete_win (generic_win->handle); 688 generic_win->handle = (WINDOW *) NULL; 689 generic_win->is_visible = FALSE; 690 } 691 if (win_info->detail.source_info.filename) 692 { 693 xfree (win_info->detail.source_info.filename); 694 win_info->detail.source_info.filename = 0; 695 } 696 generic_win = win_info->detail.source_info.execution_info; 697 if (generic_win != (struct tui_gen_win_info *) NULL) 698 { 699 tui_delete_win (generic_win->handle); 700 generic_win->handle = (WINDOW *) NULL; 701 generic_win->is_visible = FALSE; 702 } 703 break; 704 case DATA_WIN: 705 if (win_info->generic.content != NULL) 706 { 707 tui_del_data_windows (win_info->detail.data_display_info.regs_content, 708 win_info->detail.data_display_info.regs_content_count); 709 tui_del_data_windows (win_info->detail.data_display_info.data_content, 710 win_info->detail.data_display_info.data_content_count); 711 } 712 break; 713 default: 714 break; 715 } 716 if (win_info->generic.handle != (WINDOW *) NULL) 717 { 718 tui_delete_win (win_info->generic.handle); 719 win_info->generic.handle = (WINDOW *) NULL; 720 win_info->generic.is_visible = FALSE; 721 } 722 } 723 724 725 void 726 tui_free_window (struct tui_win_info *win_info) 727 { 728 struct tui_gen_win_info *generic_win; 729 730 switch (win_info->generic.type) 731 { 732 case SRC_WIN: 733 case DISASSEM_WIN: 734 generic_win = tui_locator_win_info_ptr (); 735 if (generic_win != (struct tui_gen_win_info *) NULL) 736 { 737 tui_delete_win (generic_win->handle); 738 generic_win->handle = (WINDOW *) NULL; 739 } 740 tui_free_win_content (generic_win); 741 if (win_info->detail.source_info.filename) 742 { 743 xfree (win_info->detail.source_info.filename); 744 win_info->detail.source_info.filename = 0; 745 } 746 generic_win = win_info->detail.source_info.execution_info; 747 if (generic_win != (struct tui_gen_win_info *) NULL) 748 { 749 tui_delete_win (generic_win->handle); 750 generic_win->handle = (WINDOW *) NULL; 751 tui_free_win_content (generic_win); 752 } 753 break; 754 case DATA_WIN: 755 if (win_info->generic.content != NULL) 756 { 757 tui_free_data_content (win_info->detail.data_display_info.regs_content, 758 win_info->detail.data_display_info.regs_content_count); 759 win_info->detail.data_display_info.regs_content = 760 (tui_win_content) NULL; 761 win_info->detail.data_display_info.regs_content_count = 0; 762 tui_free_data_content (win_info->detail.data_display_info.data_content, 763 win_info->detail.data_display_info.data_content_count); 764 win_info->detail.data_display_info.data_content = 765 (tui_win_content) NULL; 766 win_info->detail.data_display_info.data_content_count = 0; 767 win_info->detail.data_display_info.regs_display_type = 768 TUI_UNDEFINED_REGS; 769 win_info->detail.data_display_info.regs_column_count = 1; 770 win_info->detail.data_display_info.display_regs = FALSE; 771 win_info->generic.content = NULL; 772 win_info->generic.content_size = 0; 773 } 774 break; 775 default: 776 break; 777 } 778 if (win_info->generic.handle != (WINDOW *) NULL) 779 { 780 tui_delete_win (win_info->generic.handle); 781 win_info->generic.handle = (WINDOW *) NULL; 782 tui_free_win_content (&win_info->generic); 783 } 784 if (win_info->generic.title) 785 xfree (win_info->generic.title); 786 xfree (win_info); 787 } 788 789 790 void 791 tui_free_all_source_wins_content (void) 792 { 793 int i; 794 795 for (i = 0; i < (tui_source_windows ())->count; i++) 796 { 797 struct tui_win_info *win_info = (tui_source_windows ())->list[i]; 798 799 if (win_info != NULL) 800 { 801 tui_free_win_content (&(win_info->generic)); 802 tui_free_win_content (win_info->detail.source_info.execution_info); 803 } 804 } 805 } 806 807 808 void 809 tui_free_win_content (struct tui_gen_win_info *win_info) 810 { 811 if (win_info->content != NULL) 812 { 813 free_content ((tui_win_content) win_info->content, 814 win_info->content_size, 815 win_info->type); 816 win_info->content = NULL; 817 } 818 win_info->content_size = 0; 819 } 820 821 822 void 823 tui_del_data_windows (tui_win_content content, 824 int content_size) 825 { 826 int i; 827 828 /* Remember that data window content elements are of type struct 829 tui_gen_win_info *, each of which whose single element is a data 830 element. */ 831 for (i = 0; i < content_size; i++) 832 { 833 struct tui_gen_win_info *generic_win = &content[i]->which_element.data_window; 834 835 if (generic_win != (struct tui_gen_win_info *) NULL) 836 { 837 tui_delete_win (generic_win->handle); 838 generic_win->handle = (WINDOW *) NULL; 839 generic_win->is_visible = FALSE; 840 } 841 } 842 } 843 844 845 void 846 tui_free_data_content (tui_win_content content, 847 int content_size) 848 { 849 int i; 850 851 /* Remember that data window content elements are of type struct 852 tui_gen_win_info *, each of which whose single element is a data 853 element. */ 854 for (i = 0; i < content_size; i++) 855 { 856 struct tui_gen_win_info *generic_win = &content[i]->which_element.data_window; 857 858 if (generic_win != (struct tui_gen_win_info *) NULL) 859 { 860 tui_delete_win (generic_win->handle); 861 generic_win->handle = (WINDOW *) NULL; 862 tui_free_win_content (generic_win); 863 } 864 } 865 free_content (content, 866 content_size, 867 DATA_WIN); 868 } 869 870 871 /********************************** 872 ** LOCAL STATIC FUNCTIONS ** 873 **********************************/ 874 875 876 static void 877 free_content (tui_win_content content, 878 int content_size, 879 enum tui_win_type win_type) 880 { 881 if (content != (tui_win_content) NULL) 882 { 883 free_content_elements (content, content_size, win_type); 884 xfree (content); 885 } 886 } 887 888 889 /* free_content_elements(). 890 */ 891 static void 892 free_content_elements (tui_win_content content, 893 int content_size, 894 enum tui_win_type type) 895 { 896 if (content != (tui_win_content) NULL) 897 { 898 int i; 899 900 if (type == SRC_WIN || type == DISASSEM_WIN) 901 { 902 /* Free whole source block. */ 903 xfree (content[0]->which_element.source.line); 904 } 905 else 906 { 907 for (i = 0; i < content_size; i++) 908 { 909 struct tui_win_element *element; 910 911 element = content[i]; 912 if (element != (struct tui_win_element *) NULL) 913 { 914 switch (type) 915 { 916 case DATA_WIN: 917 xfree (element); 918 break; 919 case DATA_ITEM_WIN: 920 /* Note that data elements are not allocated in 921 a single block, but individually, as 922 needed. */ 923 if (element->which_element.data.type != TUI_REGISTER) 924 xfree ((void *)element->which_element.data.name); 925 xfree (element->which_element.data.value); 926 xfree (element->which_element.data.content); 927 xfree (element); 928 break; 929 case CMD_WIN: 930 xfree (element->which_element.command.line); 931 break; 932 default: 933 break; 934 } 935 } 936 } 937 } 938 if (type != DATA_WIN && type != DATA_ITEM_WIN) 939 xfree (content[0]); /* Free the element block. */ 940 } 941 } 942