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