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