* tuiWin.c (tuiStrDup): Remove, replaced by xstrdup.
[binutils-gdb.git] / gdb / tui / tuiWin.c
1 /* TUI window generic functions.
2 Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3 Contributed by Hewlett-Packard Company.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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 <string.h>
28 #include <ctype.h>
29 #include "defs.h"
30 #include "command.h"
31 #include "symtab.h"
32 #include "breakpoint.h"
33 #include "frame.h"
34 #include "cli/cli-cmds.h"
35
36 #include "tui.h"
37 #include "tuiData.h"
38 #include "tuiGeneralWin.h"
39 #include "tuiStack.h"
40 #include "tuiRegs.h"
41 #include "tuiDisassem.h"
42 #include "tuiSource.h"
43 #include "tuiSourceWin.h"
44 #include "tuiDataWin.h"
45
46 /*******************************
47 ** External Declarations
48 ********************************/
49 extern void init_page_info ();
50
51 /*******************************
52 ** Static Local Decls
53 ********************************/
54 static void _makeVisibleWithNewHeight (TuiWinInfoPtr);
55 static void _makeInvisibleAndSetNewHeight (TuiWinInfoPtr, int);
56 static TuiStatus _tuiAdjustWinHeights (TuiWinInfoPtr, int);
57 static int _newHeightOk (TuiWinInfoPtr, int);
58 static void _tuiSetTabWidth_command (char *, int);
59 static void _tuiRefreshAll_command (char *, int);
60 static void _tuiSetWinHeight_command (char *, int);
61 static void _tuiXDBsetWinHeight_command (char *, int);
62 static void _tuiAllWindowsInfo (char *, int);
63 static void _tuiSetFocus_command (char *, int);
64 static void _tuiScrollForward_command (char *, int);
65 static void _tuiScrollBackward_command (char *, int);
66 static void _tuiScrollLeft_command (char *, int);
67 static void _tuiScrollRight_command (char *, int);
68 static void _parseScrollingArgs (char *, TuiWinInfoPtr *, int *);
69
70
71 /***************************************
72 ** DEFINITIONS
73 ***************************************/
74 #define WIN_HEIGHT_USAGE "Usage: winheight <win_name> [+ | -] <#lines>\n"
75 #define XDBWIN_HEIGHT_USAGE "Usage: w <#lines>\n"
76 #define FOCUS_USAGE "Usage: focus {<win> | next | prev}\n"
77
78 /***************************************
79 ** PUBLIC FUNCTIONS
80 ***************************************/
81
82 /*
83 ** _initialize_tuiWin().
84 ** Function to initialize gdb commands, for tui window manipulation.
85 */
86 void
87 _initialize_tuiWin (void)
88 {
89 /* Define the classes of commands.
90 They will appear in the help list in the reverse of this order. */
91
92 add_cmd ("tui", class_tui, NO_FUNCTION,
93 "Text User Interface commands.",
94 &cmdlist);
95
96 add_com ("refresh", class_tui, _tuiRefreshAll_command,
97 "Refresh the terminal display.\n");
98 if (xdb_commands)
99 add_com_alias ("U", "refresh", class_tui, 0);
100 add_com ("tabset", class_tui, _tuiSetTabWidth_command,
101 "Set the width (in characters) of tab stops.\n\
102 Usage: tabset <n>\n");
103 add_com ("winheight", class_tui, _tuiSetWinHeight_command,
104 "Set the height of a specified window.\n\
105 Usage: winheight <win_name> [+ | -] <#lines>\n\
106 Window names are:\n\
107 src : the source window\n\
108 cmd : the command window\n\
109 asm : the disassembly window\n\
110 regs : the register display\n");
111 add_com_alias ("wh", "winheight", class_tui, 0);
112 add_info ("win", _tuiAllWindowsInfo,
113 "List of all displayed windows.\n");
114 add_com ("focus", class_tui, _tuiSetFocus_command,
115 "Set focus to named window or next/prev window.\n\
116 Usage: focus {<win> | next | prev}\n\
117 Valid Window names are:\n\
118 src : the source window\n\
119 asm : the disassembly window\n\
120 regs : the register display\n\
121 cmd : the command window\n");
122 add_com_alias ("fs", "focus", class_tui, 0);
123 add_com ("+", class_tui, _tuiScrollForward_command,
124 "Scroll window forward.\nUsage: + [win] [n]\n");
125 add_com ("-", class_tui, _tuiScrollBackward_command,
126 "Scroll window backward.\nUsage: - [win] [n]\n");
127 add_com ("<", class_tui, _tuiScrollLeft_command,
128 "Scroll window forward.\nUsage: < [win] [n]\n");
129 add_com (">", class_tui, _tuiScrollRight_command,
130 "Scroll window backward.\nUsage: > [win] [n]\n");
131 if (xdb_commands)
132 add_com ("w", class_xdb, _tuiXDBsetWinHeight_command,
133 "XDB compatibility command for setting the height of a command window.\n\
134 Usage: w <#lines>\n");
135 }
136
137
138 /*
139 ** tuiClearWinFocusFrom
140 ** Clear the logical focus from winInfo
141 */
142 void
143 tuiClearWinFocusFrom (TuiWinInfoPtr winInfo)
144 {
145 if (m_winPtrNotNull (winInfo))
146 {
147 if (winInfo->generic.type != CMD_WIN)
148 unhighlightWin (winInfo);
149 tuiSetWinWithFocus ((TuiWinInfoPtr) NULL);
150 }
151
152 return;
153 } /* tuiClearWinFocusFrom */
154
155
156 /*
157 ** tuiClearWinFocus().
158 ** Clear the window that has focus.
159 */
160 void
161 tuiClearWinFocus (void)
162 {
163 tuiClearWinFocusFrom (tuiWinWithFocus ());
164
165 return;
166 } /* tuiClearWinFocus */
167
168
169 /*
170 ** tuiSetWinFocusTo
171 ** Set the logical focus to winInfo
172 */
173 void
174 tuiSetWinFocusTo (TuiWinInfoPtr winInfo)
175 {
176 if (m_winPtrNotNull (winInfo))
177 {
178 TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
179
180 if (m_winPtrNotNull (winWithFocus) &&
181 winWithFocus->generic.type != CMD_WIN)
182 unhighlightWin (winWithFocus);
183 tuiSetWinWithFocus (winInfo);
184 if (winInfo->generic.type != CMD_WIN)
185 highlightWin (winInfo);
186 }
187
188 return;
189 } /* tuiSetWinFocusTo */
190
191
192 /*
193 ** tuiScrollForward().
194 */
195 void
196 tuiScrollForward (TuiWinInfoPtr winToScroll, int numToScroll)
197 {
198 if (winToScroll != cmdWin)
199 {
200 int _numToScroll = numToScroll;
201
202 if (numToScroll == 0)
203 _numToScroll = winToScroll->generic.height - 3;
204 /*
205 ** If we are scrolling the source or disassembly window, do a
206 ** "psuedo" scroll since not all of the source is in memory,
207 ** only what is in the viewport. If winToScroll is the
208 ** command window do nothing since the term should handle it.
209 */
210 if (winToScroll == srcWin)
211 tuiVerticalSourceScroll (FORWARD_SCROLL, _numToScroll);
212 else if (winToScroll == disassemWin)
213 tuiVerticalDisassemScroll (FORWARD_SCROLL, _numToScroll);
214 else if (winToScroll == dataWin)
215 tuiVerticalDataScroll (FORWARD_SCROLL, _numToScroll);
216 }
217
218 return;
219 } /* tuiScrollForward */
220
221
222 /*
223 ** tuiScrollBackward().
224 */
225 void
226 tuiScrollBackward (TuiWinInfoPtr winToScroll, int numToScroll)
227 {
228 if (winToScroll != cmdWin)
229 {
230 int _numToScroll = numToScroll;
231
232 if (numToScroll == 0)
233 _numToScroll = winToScroll->generic.height - 3;
234 /*
235 ** If we are scrolling the source or disassembly window, do a
236 ** "psuedo" scroll since not all of the source is in memory,
237 ** only what is in the viewport. If winToScroll is the
238 ** command window do nothing since the term should handle it.
239 */
240 if (winToScroll == srcWin)
241 tuiVerticalSourceScroll (BACKWARD_SCROLL, _numToScroll);
242 else if (winToScroll == disassemWin)
243 tuiVerticalDisassemScroll (BACKWARD_SCROLL, _numToScroll);
244 else if (winToScroll == dataWin)
245 tuiVerticalDataScroll (BACKWARD_SCROLL, _numToScroll);
246 }
247 return;
248 } /* tuiScrollBackward */
249
250
251 /*
252 ** tuiScrollLeft().
253 */
254 void
255 tuiScrollLeft (TuiWinInfoPtr winToScroll, int numToScroll)
256 {
257 if (winToScroll != cmdWin)
258 {
259 int _numToScroll = numToScroll;
260
261 if (_numToScroll == 0)
262 _numToScroll = 1;
263 /*
264 ** If we are scrolling the source or disassembly window, do a
265 ** "psuedo" scroll since not all of the source is in memory,
266 ** only what is in the viewport. If winToScroll is the
267 ** command window do nothing since the term should handle it.
268 */
269 if (winToScroll == srcWin || winToScroll == disassemWin)
270 tuiHorizontalSourceScroll (winToScroll, LEFT_SCROLL, _numToScroll);
271 }
272 return;
273 } /* tuiScrollLeft */
274
275
276 /*
277 ** tuiScrollRight().
278 */
279 void
280 tuiScrollRight (TuiWinInfoPtr winToScroll, int numToScroll)
281 {
282 if (winToScroll != cmdWin)
283 {
284 int _numToScroll = numToScroll;
285
286 if (_numToScroll == 0)
287 _numToScroll = 1;
288 /*
289 ** If we are scrolling the source or disassembly window, do a
290 ** "psuedo" scroll since not all of the source is in memory,
291 ** only what is in the viewport. If winToScroll is the
292 ** command window do nothing since the term should handle it.
293 */
294 if (winToScroll == srcWin || winToScroll == disassemWin)
295 tuiHorizontalSourceScroll (winToScroll, RIGHT_SCROLL, _numToScroll);
296 }
297 return;
298 } /* tuiScrollRight */
299
300
301 /*
302 ** tui_scroll().
303 ** Scroll a window. Arguments are passed through a va_list.
304 */
305 void
306 tui_scroll (TuiScrollDirection direction,
307 TuiWinInfoPtr winToScroll,
308 int numToScroll)
309 {
310 switch (direction)
311 {
312 case FORWARD_SCROLL:
313 tuiScrollForward (winToScroll, numToScroll);
314 break;
315 case BACKWARD_SCROLL:
316 tuiScrollBackward (winToScroll, numToScroll);
317 break;
318 case LEFT_SCROLL:
319 tuiScrollLeft (winToScroll, numToScroll);
320 break;
321 case RIGHT_SCROLL:
322 tuiScrollRight (winToScroll, numToScroll);
323 break;
324 default:
325 break;
326 }
327 }
328
329
330 /*
331 ** tuiRefreshAll().
332 */
333 void
334 tuiRefreshAll (void)
335 {
336 TuiWinType type;
337
338 refreshAll (winList);
339 for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
340 {
341 if (winList[type] && winList[type]->generic.isVisible)
342 {
343 switch (type)
344 {
345 case SRC_WIN:
346 case DISASSEM_WIN:
347 tuiClearWin (&winList[type]->generic);
348 if (winList[type]->detail.sourceInfo.hasLocator)
349 tuiClearLocatorDisplay ();
350 tuiShowSourceContent (winList[type]);
351 checkAndDisplayHighlightIfNeeded (winList[type]);
352 tuiEraseExecInfoContent (winList[type]);
353 tuiUpdateExecInfo (winList[type]);
354 break;
355 case DATA_WIN:
356 tuiRefreshDataWin ();
357 break;
358 default:
359 break;
360 }
361 }
362 }
363 tuiClearLocatorDisplay ();
364 tuiShowLocatorContent ();
365
366 return;
367 } /* tuiRefreshAll */
368
369
370 /*
371 ** tuiResizeAll().
372 ** Resize all the windows based on the the terminal size. This
373 ** function gets called from within the readline sinwinch handler.
374 */
375 void
376 tuiResizeAll (void)
377 {
378 int heightDiff, widthDiff;
379 extern int screenheight, screenwidth; /* in readline */
380
381 widthDiff = screenwidth - termWidth ();
382 heightDiff = screenheight - termHeight ();
383 if (heightDiff || widthDiff)
384 {
385 TuiLayoutType curLayout = currentLayout ();
386 TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
387 TuiWinInfoPtr firstWin, secondWin;
388 TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
389 TuiWinType winType;
390 int i, newHeight, splitDiff, cmdSplitDiff, numWinsDisplayed = 2;
391
392 /* turn keypad off while we resize */
393 if (winWithFocus != cmdWin)
394 keypad (cmdWin->generic.handle, FALSE);
395 init_page_info ();
396 setTermHeightTo (screenheight);
397 setTermWidthTo (screenwidth);
398 if (curLayout == SRC_DISASSEM_COMMAND ||
399 curLayout == SRC_DATA_COMMAND || curLayout == DISASSEM_DATA_COMMAND)
400 numWinsDisplayed++;
401 splitDiff = heightDiff / numWinsDisplayed;
402 cmdSplitDiff = splitDiff;
403 if (heightDiff % numWinsDisplayed)
404 {
405 if (heightDiff < 0)
406 cmdSplitDiff--;
407 else
408 cmdSplitDiff++;
409 }
410 /* now adjust each window */
411 clear ();
412 refresh ();
413 switch (curLayout)
414 {
415 case SRC_COMMAND:
416 case DISASSEM_COMMAND:
417 firstWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
418 firstWin->generic.width += widthDiff;
419 locator->width += widthDiff;
420 /* check for invalid heights */
421 if (heightDiff == 0)
422 newHeight = firstWin->generic.height;
423 else if ((firstWin->generic.height + splitDiff) >=
424 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
425 newHeight = screenheight - MIN_CMD_WIN_HEIGHT - 1;
426 else if ((firstWin->generic.height + splitDiff) <= 0)
427 newHeight = MIN_WIN_HEIGHT;
428 else
429 newHeight = firstWin->generic.height + splitDiff;
430
431 _makeInvisibleAndSetNewHeight (firstWin, newHeight);
432 cmdWin->generic.origin.y = locator->origin.y + 1;
433 cmdWin->generic.width += widthDiff;
434 newHeight = screenheight - cmdWin->generic.origin.y;
435 _makeInvisibleAndSetNewHeight (cmdWin, newHeight);
436 _makeVisibleWithNewHeight (firstWin);
437 _makeVisibleWithNewHeight (cmdWin);
438 if (firstWin->generic.contentSize <= 0)
439 tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
440 break;
441 default:
442 if (curLayout == SRC_DISASSEM_COMMAND)
443 {
444 firstWin = srcWin;
445 firstWin->generic.width += widthDiff;
446 secondWin = disassemWin;
447 secondWin->generic.width += widthDiff;
448 }
449 else
450 {
451 firstWin = dataWin;
452 firstWin->generic.width += widthDiff;
453 secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
454 secondWin->generic.width += widthDiff;
455 }
456 /* Change the first window's height/width */
457 /* check for invalid heights */
458 if (heightDiff == 0)
459 newHeight = firstWin->generic.height;
460 else if ((firstWin->generic.height +
461 secondWin->generic.height + (splitDiff * 2)) >=
462 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
463 newHeight = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
464 else if ((firstWin->generic.height + splitDiff) <= 0)
465 newHeight = MIN_WIN_HEIGHT;
466 else
467 newHeight = firstWin->generic.height + splitDiff;
468 _makeInvisibleAndSetNewHeight (firstWin, newHeight);
469
470 if (firstWin == dataWin && widthDiff != 0)
471 firstWin->detail.dataDisplayInfo.regsColumnCount =
472 tuiCalculateRegsColumnCount (
473 firstWin->detail.dataDisplayInfo.regsDisplayType);
474 locator->width += widthDiff;
475
476 /* Change the second window's height/width */
477 /* check for invalid heights */
478 if (heightDiff == 0)
479 newHeight = secondWin->generic.height;
480 else if ((firstWin->generic.height +
481 secondWin->generic.height + (splitDiff * 2)) >=
482 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
483 {
484 newHeight = screenheight - MIN_CMD_WIN_HEIGHT - 1;
485 if (newHeight % 2)
486 newHeight = (newHeight / 2) + 1;
487 else
488 newHeight /= 2;
489 }
490 else if ((secondWin->generic.height + splitDiff) <= 0)
491 newHeight = MIN_WIN_HEIGHT;
492 else
493 newHeight = secondWin->generic.height + splitDiff;
494 secondWin->generic.origin.y = firstWin->generic.height - 1;
495 _makeInvisibleAndSetNewHeight (secondWin, newHeight);
496
497 /* Change the command window's height/width */
498 cmdWin->generic.origin.y = locator->origin.y + 1;
499 _makeInvisibleAndSetNewHeight (
500 cmdWin, cmdWin->generic.height + cmdSplitDiff);
501 _makeVisibleWithNewHeight (firstWin);
502 _makeVisibleWithNewHeight (secondWin);
503 _makeVisibleWithNewHeight (cmdWin);
504 if (firstWin->generic.contentSize <= 0)
505 tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
506 if (secondWin->generic.contentSize <= 0)
507 tuiEraseSourceContent (secondWin, EMPTY_SOURCE_PROMPT);
508 break;
509 }
510 /*
511 ** Now remove all invisible windows, and their content so that they get
512 ** created again when called for with the new size
513 */
514 for (winType = SRC_WIN; (winType < MAX_MAJOR_WINDOWS); winType++)
515 {
516 if (winType != CMD_WIN && m_winPtrNotNull (winList[winType]) &&
517 !winList[winType]->generic.isVisible)
518 {
519 freeWindow (winList[winType]);
520 winList[winType] = (TuiWinInfoPtr) NULL;
521 }
522 }
523 tuiSetWinResizedTo (TRUE);
524 /* turn keypad back on, unless focus is in the command window */
525 if (winWithFocus != cmdWin)
526 keypad (cmdWin->generic.handle, TRUE);
527 }
528 return;
529 } /* tuiResizeAll */
530
531
532 /*
533 ** tuiSigwinchHandler()
534 ** SIGWINCH signal handler for the tui. This signal handler is
535 ** always called, even when the readline package clears signals
536 ** because it is set as the old_sigwinch() (TUI only)
537 */
538 void
539 tuiSigwinchHandler (int signal)
540 {
541 /*
542 ** Say that a resize was done so that the readline can do it
543 ** later when appropriate.
544 */
545 tuiSetWinResizedTo (TRUE);
546
547 return;
548 } /* tuiSigwinchHandler */
549
550
551
552 /*************************
553 ** STATIC LOCAL FUNCTIONS
554 **************************/
555
556
557 /*
558 ** _tuiScrollForward_command().
559 */
560 static void
561 _tuiScrollForward_command (char *arg, int fromTTY)
562 {
563 int numToScroll = 1;
564 TuiWinInfoPtr winToScroll;
565
566 /* Make sure the curses mode is enabled. */
567 tui_enable ();
568 if (arg == (char *) NULL)
569 _parseScrollingArgs (arg, &winToScroll, (int *) NULL);
570 else
571 _parseScrollingArgs (arg, &winToScroll, &numToScroll);
572 tui_scroll (FORWARD_SCROLL, winToScroll, numToScroll);
573 }
574
575
576 /*
577 ** _tuiScrollBackward_command().
578 */
579 static void
580 _tuiScrollBackward_command (char *arg, int fromTTY)
581 {
582 int numToScroll = 1;
583 TuiWinInfoPtr winToScroll;
584
585 /* Make sure the curses mode is enabled. */
586 tui_enable ();
587 if (arg == (char *) NULL)
588 _parseScrollingArgs (arg, &winToScroll, (int *) NULL);
589 else
590 _parseScrollingArgs (arg, &winToScroll, &numToScroll);
591 tui_scroll (BACKWARD_SCROLL, winToScroll, numToScroll);
592 }
593
594
595 /*
596 ** _tuiScrollLeft_command().
597 */
598 static void
599 _tuiScrollLeft_command (char *arg, int fromTTY)
600 {
601 int numToScroll;
602 TuiWinInfoPtr winToScroll;
603
604 /* Make sure the curses mode is enabled. */
605 tui_enable ();
606 _parseScrollingArgs (arg, &winToScroll, &numToScroll);
607 tui_scroll (LEFT_SCROLL, winToScroll, numToScroll);
608 }
609
610
611 /*
612 ** _tuiScrollRight_command().
613 */
614 static void
615 _tuiScrollRight_command (char *arg, int fromTTY)
616 {
617 int numToScroll;
618 TuiWinInfoPtr winToScroll;
619
620 /* Make sure the curses mode is enabled. */
621 tui_enable ();
622 _parseScrollingArgs (arg, &winToScroll, &numToScroll);
623 tui_scroll (RIGHT_SCROLL, winToScroll, numToScroll);
624 }
625
626
627 /*
628 ** _tuiSetFocus().
629 ** Set focus to the window named by 'arg'
630 */
631 static void
632 _tuiSetFocus (char *arg, int fromTTY)
633 {
634 if (arg != (char *) NULL)
635 {
636 char *bufPtr = (char *) xstrdup (arg);
637 int i;
638 TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL;
639
640 for (i = 0; (i < strlen (bufPtr)); i++)
641 bufPtr[i] = toupper (arg[i]);
642
643 if (subset_compare (bufPtr, "NEXT"))
644 winInfo = tuiNextWin (tuiWinWithFocus ());
645 else if (subset_compare (bufPtr, "PREV"))
646 winInfo = tuiPrevWin (tuiWinWithFocus ());
647 else
648 winInfo = partialWinByName (bufPtr);
649
650 if (winInfo == (TuiWinInfoPtr) NULL || !winInfo->generic.isVisible)
651 warning ("Invalid window specified. \n\
652 The window name specified must be valid and visible.\n");
653 else
654 {
655 tuiSetWinFocusTo (winInfo);
656 keypad (cmdWin->generic.handle, (winInfo != cmdWin));
657 }
658
659 if (dataWin && dataWin->generic.isVisible)
660 tuiRefreshDataWin ();
661 tuiFree (bufPtr);
662 printf_filtered ("Focus set to %s window.\n",
663 winName ((TuiGenWinInfoPtr) tuiWinWithFocus ()));
664 }
665 else
666 warning ("Incorrect Number of Arguments.\n%s", FOCUS_USAGE);
667
668 return;
669 } /* _tuiSetFocus */
670
671 /*
672 ** _tuiSetFocus_command()
673 */
674 static void
675 _tuiSetFocus_command (char *arg, int fromTTY)
676 {
677 /* Make sure the curses mode is enabled. */
678 tui_enable ();
679 _tuiSetFocus (arg, fromTTY);
680 }
681
682
683 /*
684 ** _tuiAllWindowsInfo().
685 */
686 static void
687 _tuiAllWindowsInfo (char *arg, int fromTTY)
688 {
689 TuiWinType type;
690 TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
691
692 for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
693 if (winList[type]->generic.isVisible)
694 {
695 if (winWithFocus == winList[type])
696 printf_filtered (" %s\t(%d lines) <has focus>\n",
697 winName (&winList[type]->generic),
698 winList[type]->generic.height);
699 else
700 printf_filtered (" %s\t(%d lines)\n",
701 winName (&winList[type]->generic),
702 winList[type]->generic.height);
703 }
704
705 return;
706 } /* _tuiAllWindowsInfo */
707
708
709 /*
710 ** _tuiRefreshAll_command().
711 */
712 static void
713 _tuiRefreshAll_command (char *arg, int fromTTY)
714 {
715 /* Make sure the curses mode is enabled. */
716 tui_enable ();
717
718 tuiRefreshAll ();
719 }
720
721
722 /*
723 ** _tuiSetWinTabWidth_command().
724 ** Set the height of the specified window.
725 */
726 static void
727 _tuiSetTabWidth_command (char *arg, int fromTTY)
728 {
729 /* Make sure the curses mode is enabled. */
730 tui_enable ();
731 if (arg != (char *) NULL)
732 {
733 int ts;
734
735 ts = atoi (arg);
736 if (ts > 0)
737 tuiSetDefaultTabLen (ts);
738 else
739 warning ("Tab widths greater than 0 must be specified.\n");
740 }
741
742 return;
743 } /* _tuiSetTabWidth_command */
744
745
746 /*
747 ** _tuiSetWinHeight().
748 ** Set the height of the specified window.
749 */
750 static void
751 _tuiSetWinHeight (char *arg, int fromTTY)
752 {
753 /* Make sure the curses mode is enabled. */
754 tui_enable ();
755 if (arg != (char *) NULL)
756 {
757 char *buf = xstrdup (arg);
758 char *bufPtr = buf;
759 char *wname = (char *) NULL;
760 int newHeight, i;
761 TuiWinInfoPtr winInfo;
762
763 wname = bufPtr;
764 bufPtr = strchr (bufPtr, ' ');
765 if (bufPtr != (char *) NULL)
766 {
767 *bufPtr = (char) 0;
768
769 /*
770 ** Validate the window name
771 */
772 for (i = 0; i < strlen (wname); i++)
773 wname[i] = toupper (wname[i]);
774 winInfo = partialWinByName (wname);
775
776 if (winInfo == (TuiWinInfoPtr) NULL || !winInfo->generic.isVisible)
777 warning ("Invalid window specified. \n\
778 The window name specified must be valid and visible.\n");
779 else
780 {
781 /* Process the size */
782 while (*(++bufPtr) == ' ')
783 ;
784
785 if (*bufPtr != (char) 0)
786 {
787 int negate = FALSE;
788 int fixedSize = TRUE;
789 int inputNo;;
790
791 if (*bufPtr == '+' || *bufPtr == '-')
792 {
793 if (*bufPtr == '-')
794 negate = TRUE;
795 fixedSize = FALSE;
796 bufPtr++;
797 }
798 inputNo = atoi (bufPtr);
799 if (inputNo > 0)
800 {
801 if (negate)
802 inputNo *= (-1);
803 if (fixedSize)
804 newHeight = inputNo;
805 else
806 newHeight = winInfo->generic.height + inputNo;
807 /*
808 ** Now change the window's height, and adjust all
809 ** other windows around it
810 */
811 if (_tuiAdjustWinHeights (winInfo,
812 newHeight) == TUI_FAILURE)
813 warning ("Invalid window height specified.\n%s",
814 WIN_HEIGHT_USAGE);
815 else
816 init_page_info ();
817 }
818 else
819 warning ("Invalid window height specified.\n%s",
820 WIN_HEIGHT_USAGE);
821 }
822 }
823 }
824 else
825 printf_filtered (WIN_HEIGHT_USAGE);
826
827 if (buf != (char *) NULL)
828 tuiFree (buf);
829 }
830 else
831 printf_filtered (WIN_HEIGHT_USAGE);
832
833 return;
834 } /* _tuiSetWinHeight */
835
836 /*
837 ** _tuiSetWinHeight_command().
838 ** Set the height of the specified window, with va_list.
839 */
840 static void
841 _tuiSetWinHeight_command (char *arg, int fromTTY)
842 {
843 /* Make sure the curses mode is enabled. */
844 tui_enable ();
845 _tuiSetWinHeight (arg, fromTTY);
846 }
847
848
849 /*
850 ** _tuiXDBsetWinHeight().
851 ** XDB Compatibility command for setting the window height. This will
852 ** increase or decrease the command window by the specified amount.
853 */
854 static void
855 _tuiXDBsetWinHeight (char *arg, int fromTTY)
856 {
857 /* Make sure the curses mode is enabled. */
858 tui_enable ();
859 if (arg != (char *) NULL)
860 {
861 int inputNo = atoi (arg);
862
863 if (inputNo > 0)
864 { /* Add 1 for the locator */
865 int newHeight = termHeight () - (inputNo + 1);
866
867 if (!_newHeightOk (winList[CMD_WIN], newHeight) ||
868 _tuiAdjustWinHeights (winList[CMD_WIN],
869 newHeight) == TUI_FAILURE)
870 warning ("Invalid window height specified.\n%s",
871 XDBWIN_HEIGHT_USAGE);
872 }
873 else
874 warning ("Invalid window height specified.\n%s",
875 XDBWIN_HEIGHT_USAGE);
876 }
877 else
878 warning ("Invalid window height specified.\n%s", XDBWIN_HEIGHT_USAGE);
879
880 return;
881 } /* _tuiXDBsetWinHeight */
882
883 /*
884 ** _tuiSetWinHeight_command().
885 ** Set the height of the specified window, with va_list.
886 */
887 static void
888 _tuiXDBsetWinHeight_command (char *arg, int fromTTY)
889 {
890 _tuiXDBsetWinHeight (arg, fromTTY);
891 }
892
893
894 /*
895 ** _tuiAdjustWinHeights().
896 ** Function to adjust all window heights around the primary
897 */
898 static TuiStatus
899 _tuiAdjustWinHeights (TuiWinInfoPtr primaryWinInfo, int newHeight)
900 {
901 TuiStatus status = TUI_FAILURE;
902
903 if (_newHeightOk (primaryWinInfo, newHeight))
904 {
905 status = TUI_SUCCESS;
906 if (newHeight != primaryWinInfo->generic.height)
907 {
908 int i, diff;
909 TuiWinInfoPtr winInfo;
910 TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
911 TuiLayoutType curLayout = currentLayout ();
912
913 diff = (newHeight - primaryWinInfo->generic.height) * (-1);
914 if (curLayout == SRC_COMMAND || curLayout == DISASSEM_COMMAND)
915 {
916 TuiWinInfoPtr srcWinInfo;
917
918 _makeInvisibleAndSetNewHeight (primaryWinInfo, newHeight);
919 if (primaryWinInfo->generic.type == CMD_WIN)
920 {
921 winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[0];
922 srcWinInfo = winInfo;
923 }
924 else
925 {
926 winInfo = winList[CMD_WIN];
927 srcWinInfo = primaryWinInfo;
928 }
929 _makeInvisibleAndSetNewHeight (winInfo,
930 winInfo->generic.height + diff);
931 cmdWin->generic.origin.y = locator->origin.y + 1;
932 _makeVisibleWithNewHeight (winInfo);
933 _makeVisibleWithNewHeight (primaryWinInfo);
934 if (srcWinInfo->generic.contentSize <= 0)
935 tuiEraseSourceContent (srcWinInfo, EMPTY_SOURCE_PROMPT);
936 }
937 else
938 {
939 TuiWinInfoPtr firstWin, secondWin;
940
941 if (curLayout == SRC_DISASSEM_COMMAND)
942 {
943 firstWin = srcWin;
944 secondWin = disassemWin;
945 }
946 else
947 {
948 firstWin = dataWin;
949 secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
950 }
951 if (primaryWinInfo == cmdWin)
952 { /*
953 ** Split the change in height accross the 1st & 2nd windows
954 ** adjusting them as well.
955 */
956 int firstSplitDiff = diff / 2; /* subtract the locator */
957 int secondSplitDiff = firstSplitDiff;
958
959 if (diff % 2)
960 {
961 if (firstWin->generic.height >
962 secondWin->generic.height)
963 if (diff < 0)
964 firstSplitDiff--;
965 else
966 firstSplitDiff++;
967 else
968 {
969 if (diff < 0)
970 secondSplitDiff--;
971 else
972 secondSplitDiff++;
973 }
974 }
975 /* make sure that the minimum hieghts are honored */
976 while ((firstWin->generic.height + firstSplitDiff) < 3)
977 {
978 firstSplitDiff++;
979 secondSplitDiff--;
980 }
981 while ((secondWin->generic.height + secondSplitDiff) < 3)
982 {
983 secondSplitDiff++;
984 firstSplitDiff--;
985 }
986 _makeInvisibleAndSetNewHeight (
987 firstWin,
988 firstWin->generic.height + firstSplitDiff);
989 secondWin->generic.origin.y = firstWin->generic.height - 1;
990 _makeInvisibleAndSetNewHeight (
991 secondWin, secondWin->generic.height + secondSplitDiff);
992 cmdWin->generic.origin.y = locator->origin.y + 1;
993 _makeInvisibleAndSetNewHeight (cmdWin, newHeight);
994 }
995 else
996 {
997 if ((cmdWin->generic.height + diff) < 1)
998 { /*
999 ** If there is no way to increase the command window
1000 ** take real estate from the 1st or 2nd window.
1001 */
1002 if ((cmdWin->generic.height + diff) < 1)
1003 {
1004 int i;
1005 for (i = cmdWin->generic.height + diff;
1006 (i < 1); i++)
1007 if (primaryWinInfo == firstWin)
1008 secondWin->generic.height--;
1009 else
1010 firstWin->generic.height--;
1011 }
1012 }
1013 if (primaryWinInfo == firstWin)
1014 _makeInvisibleAndSetNewHeight (firstWin, newHeight);
1015 else
1016 _makeInvisibleAndSetNewHeight (
1017 firstWin,
1018 firstWin->generic.height);
1019 secondWin->generic.origin.y = firstWin->generic.height - 1;
1020 if (primaryWinInfo == secondWin)
1021 _makeInvisibleAndSetNewHeight (secondWin, newHeight);
1022 else
1023 _makeInvisibleAndSetNewHeight (
1024 secondWin, secondWin->generic.height);
1025 cmdWin->generic.origin.y = locator->origin.y + 1;
1026 if ((cmdWin->generic.height + diff) < 1)
1027 _makeInvisibleAndSetNewHeight (cmdWin, 1);
1028 else
1029 _makeInvisibleAndSetNewHeight (
1030 cmdWin, cmdWin->generic.height + diff);
1031 }
1032 _makeVisibleWithNewHeight (cmdWin);
1033 _makeVisibleWithNewHeight (secondWin);
1034 _makeVisibleWithNewHeight (firstWin);
1035 if (firstWin->generic.contentSize <= 0)
1036 tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
1037 if (secondWin->generic.contentSize <= 0)
1038 tuiEraseSourceContent (secondWin, EMPTY_SOURCE_PROMPT);
1039 }
1040 }
1041 }
1042
1043 return status;
1044 } /* _tuiAdjustWinHeights */
1045
1046
1047 /*
1048 ** _makeInvisibleAndSetNewHeight().
1049 ** Function make the target window (and auxillary windows associated
1050 ** with the targer) invisible, and set the new height and location.
1051 */
1052 static void
1053 _makeInvisibleAndSetNewHeight (TuiWinInfoPtr winInfo, int height)
1054 {
1055 int i;
1056 struct symtab *s;
1057 TuiGenWinInfoPtr genWinInfo;
1058
1059
1060 m_beInvisible (&winInfo->generic);
1061 winInfo->generic.height = height;
1062 if (height > 1)
1063 winInfo->generic.viewportHeight = height - 1;
1064 else
1065 winInfo->generic.viewportHeight = height;
1066 if (winInfo != cmdWin)
1067 winInfo->generic.viewportHeight--;
1068
1069 /* Now deal with the auxillary windows associated with winInfo */
1070 switch (winInfo->generic.type)
1071 {
1072 case SRC_WIN:
1073 case DISASSEM_WIN:
1074 genWinInfo = winInfo->detail.sourceInfo.executionInfo;
1075 m_beInvisible (genWinInfo);
1076 genWinInfo->height = height;
1077 genWinInfo->origin.y = winInfo->generic.origin.y;
1078 if (height > 1)
1079 genWinInfo->viewportHeight = height - 1;
1080 else
1081 genWinInfo->viewportHeight = height;
1082 if (winInfo != cmdWin)
1083 genWinInfo->viewportHeight--;
1084
1085 if (m_hasLocator (winInfo))
1086 {
1087 genWinInfo = locatorWinInfoPtr ();
1088 m_beInvisible (genWinInfo);
1089 genWinInfo->origin.y = winInfo->generic.origin.y + height;
1090 }
1091 break;
1092 case DATA_WIN:
1093 /* delete all data item windows */
1094 for (i = 0; i < winInfo->generic.contentSize; i++)
1095 {
1096 genWinInfo = (TuiGenWinInfoPtr) & ((TuiWinElementPtr)
1097 winInfo->generic.content[i])->whichElement.dataWindow;
1098 tuiDelwin (genWinInfo->handle);
1099 genWinInfo->handle = (WINDOW *) NULL;
1100 }
1101 break;
1102 default:
1103 break;
1104 }
1105
1106 return;
1107 } /* _makeInvisibleAndSetNewHeight */
1108
1109
1110 /*
1111 ** _makeVisibleWithNewHeight().
1112 ** Function to make the windows with new heights visible.
1113 ** This means re-creating the windows' content since the window
1114 ** had to be destroyed to be made invisible.
1115 */
1116 static void
1117 _makeVisibleWithNewHeight (TuiWinInfoPtr winInfo)
1118 {
1119 int i;
1120 struct symtab *s;
1121
1122 m_beVisible (&winInfo->generic);
1123 checkAndDisplayHighlightIfNeeded (winInfo);
1124 switch (winInfo->generic.type)
1125 {
1126 case SRC_WIN:
1127 case DISASSEM_WIN:
1128 freeWinContent (winInfo->detail.sourceInfo.executionInfo);
1129 m_beVisible (winInfo->detail.sourceInfo.executionInfo);
1130 if (winInfo->generic.content != (OpaquePtr) NULL)
1131 {
1132 TuiLineOrAddress lineOrAddr;
1133
1134 if (winInfo->generic.type == SRC_WIN)
1135 lineOrAddr.lineNo =
1136 winInfo->detail.sourceInfo.startLineOrAddr.lineNo;
1137 else
1138 lineOrAddr.addr =
1139 winInfo->detail.sourceInfo.startLineOrAddr.addr;
1140 freeWinContent (&winInfo->generic);
1141 tuiUpdateSourceWindow (winInfo,
1142 current_source_symtab,
1143 ((winInfo->generic.type == SRC_WIN) ?
1144 (Opaque) lineOrAddr.lineNo :
1145 lineOrAddr.addr),
1146 TRUE);
1147 }
1148 else if (selected_frame != (struct frame_info *) NULL)
1149 {
1150 Opaque line = 0;
1151 extern int current_source_line;
1152
1153 s = find_pc_symtab (selected_frame->pc);
1154 if (winInfo->generic.type == SRC_WIN)
1155 line = (Opaque) current_source_line;
1156 else
1157 {
1158 CORE_ADDR pc;
1159
1160 find_line_pc (s, current_source_line, &pc);
1161 line = (Opaque) pc;
1162 }
1163 tuiUpdateSourceWindow (winInfo, s, line, TRUE);
1164 }
1165 if (m_hasLocator (winInfo))
1166 {
1167 m_beVisible (locatorWinInfoPtr ());
1168 tuiClearLocatorDisplay ();
1169 tuiShowLocatorContent ();
1170 }
1171 break;
1172 case DATA_WIN:
1173 tuiDisplayAllData ();
1174 break;
1175 case CMD_WIN:
1176 winInfo->detail.commandInfo.curLine = 0;
1177 winInfo->detail.commandInfo.curch = 0;
1178 wmove (winInfo->generic.handle,
1179 winInfo->detail.commandInfo.curLine,
1180 winInfo->detail.commandInfo.curch);
1181 break;
1182 default:
1183 break;
1184 }
1185
1186 return;
1187 } /* _makeVisibleWithNewHeight */
1188
1189
1190 static int
1191 _newHeightOk (TuiWinInfoPtr primaryWinInfo, int newHeight)
1192 {
1193 int ok = (newHeight < termHeight ());
1194
1195 if (ok)
1196 {
1197 int diff, curHeight;
1198 TuiLayoutType curLayout = currentLayout ();
1199
1200 diff = (newHeight - primaryWinInfo->generic.height) * (-1);
1201 if (curLayout == SRC_COMMAND || curLayout == DISASSEM_COMMAND)
1202 {
1203 ok = ((primaryWinInfo->generic.type == CMD_WIN &&
1204 newHeight <= (termHeight () - 4) &&
1205 newHeight >= MIN_CMD_WIN_HEIGHT) ||
1206 (primaryWinInfo->generic.type != CMD_WIN &&
1207 newHeight <= (termHeight () - 2) &&
1208 newHeight >= MIN_WIN_HEIGHT));
1209 if (ok)
1210 { /* check the total height */
1211 TuiWinInfoPtr winInfo;
1212
1213 if (primaryWinInfo == cmdWin)
1214 winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1215 else
1216 winInfo = cmdWin;
1217 ok = ((newHeight +
1218 (winInfo->generic.height + diff)) <= termHeight ());
1219 }
1220 }
1221 else
1222 {
1223 int curTotalHeight, totalHeight, minHeight;
1224 TuiWinInfoPtr firstWin, secondWin;
1225
1226 if (curLayout == SRC_DISASSEM_COMMAND)
1227 {
1228 firstWin = srcWin;
1229 secondWin = disassemWin;
1230 }
1231 else
1232 {
1233 firstWin = dataWin;
1234 secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1235 }
1236 /*
1237 ** We could simply add all the heights to obtain the same result
1238 ** but below is more explicit since we subtract 1 for the
1239 ** line that the first and second windows share, and add one
1240 ** for the locator.
1241 */
1242 curTotalHeight =
1243 (firstWin->generic.height + secondWin->generic.height - 1)
1244 + cmdWin->generic.height + 1 /*locator */ ;
1245 if (primaryWinInfo == cmdWin)
1246 {
1247 /* locator included since first & second win share a line */
1248 ok = ((firstWin->generic.height +
1249 secondWin->generic.height + diff) >=
1250 (MIN_WIN_HEIGHT * 2) &&
1251 newHeight >= MIN_CMD_WIN_HEIGHT);
1252 if (ok)
1253 {
1254 totalHeight = newHeight + (firstWin->generic.height +
1255 secondWin->generic.height + diff);
1256 minHeight = MIN_CMD_WIN_HEIGHT;
1257 }
1258 }
1259 else
1260 {
1261 minHeight = MIN_WIN_HEIGHT;
1262 /*
1263 ** First see if we can increase/decrease the command
1264 ** window. And make sure that the command window is
1265 ** at least 1 line
1266 */
1267 ok = ((cmdWin->generic.height + diff) > 0);
1268 if (!ok)
1269 { /*
1270 ** Looks like we have to increase/decrease one of
1271 ** the other windows
1272 */
1273 if (primaryWinInfo == firstWin)
1274 ok = (secondWin->generic.height + diff) >= minHeight;
1275 else
1276 ok = (firstWin->generic.height + diff) >= minHeight;
1277 }
1278 if (ok)
1279 {
1280 if (primaryWinInfo == firstWin)
1281 totalHeight = newHeight +
1282 secondWin->generic.height +
1283 cmdWin->generic.height + diff;
1284 else
1285 totalHeight = newHeight +
1286 firstWin->generic.height +
1287 cmdWin->generic.height + diff;
1288 }
1289 }
1290 /*
1291 ** Now make sure that the proposed total height doesn't exceed
1292 ** the old total height.
1293 */
1294 if (ok)
1295 ok = (newHeight >= minHeight && totalHeight <= curTotalHeight);
1296 }
1297 }
1298
1299 return ok;
1300 } /* _newHeightOk */
1301
1302
1303 /*
1304 ** _parseScrollingArgs().
1305 */
1306 static void
1307 _parseScrollingArgs (char *arg, TuiWinInfoPtr * winToScroll, int *numToScroll)
1308 {
1309 if (numToScroll)
1310 *numToScroll = 0;
1311 *winToScroll = tuiWinWithFocus ();
1312
1313 /*
1314 ** First set up the default window to scroll, in case there is no
1315 ** window name arg
1316 */
1317 if (arg != (char *) NULL)
1318 {
1319 char *buf, *bufPtr;
1320
1321 /* process the number of lines to scroll */
1322 buf = bufPtr = xstrdup (arg);
1323 if (isdigit (*bufPtr))
1324 {
1325 char *numStr;
1326
1327 numStr = bufPtr;
1328 bufPtr = strchr (bufPtr, ' ');
1329 if (bufPtr != (char *) NULL)
1330 {
1331 *bufPtr = (char) 0;
1332 if (numToScroll)
1333 *numToScroll = atoi (numStr);
1334 bufPtr++;
1335 }
1336 else if (numToScroll)
1337 *numToScroll = atoi (numStr);
1338 }
1339
1340 /* process the window name if one is specified */
1341 if (bufPtr != (char *) NULL)
1342 {
1343 char *wname;
1344 int i;
1345
1346 if (*bufPtr == ' ')
1347 while (*(++bufPtr) == ' ')
1348 ;
1349
1350 if (*bufPtr != (char) 0)
1351 wname = bufPtr;
1352
1353 /* Validate the window name */
1354 for (i = 0; i < strlen (wname); i++)
1355 wname[i] = toupper (wname[i]);
1356 *winToScroll = partialWinByName (wname);
1357
1358 if (*winToScroll == (TuiWinInfoPtr) NULL ||
1359 !(*winToScroll)->generic.isVisible)
1360 warning ("Invalid window specified. \n\
1361 The window name specified must be valid and visible.\n");
1362 else if (*winToScroll == cmdWin)
1363 *winToScroll = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1364 }
1365 tuiFree (buf);
1366 }
1367
1368 return;
1369 } /* _parseScrollingArgs */