1 /****************************************************************************
2 * Copyright (c) 2006-2012,2013 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 * $Id: movewindow.c,v 1.39 2013/05/04 19:41:02 tom Exp $
31 * Demonstrate move functions for windows and derived windows from the curses
34 * Author: Thomas E. Dickey
43 add command to reset subwindow's origin to coincide with parent.
44 add command to delete subwindow (check if it has subwindows though)
47 #include <test.priv.h>
54 #ifdef NCURSES_VERSION
55 #define CONST_FMT const
57 #define CONST_FMT /* nothing */
63 #define LINE_MAX (LINES - 2)
65 #define COL_MAX (COLS - 2)
72 WINDOW
*parent
; /* need this since WINDOW->_parent is not portable */
73 WINDOW
*child
; /* the actual value */
76 static void head_line(CONST_FMT
char *fmt
,...) GCC_PRINTFLIKE(1, 2);
77 static void tail_line(CONST_FMT
char *fmt
,...) GCC_PRINTFLIKE(1, 2);
79 static unsigned num_windows
;
80 static FRAME
*all_windows
;
87 ExitProgram(EXIT_FAILURE
);
91 message(int lineno
, CONST_FMT
char *fmt
, va_list argp
)
102 vsprintf(buffer
, fmt
, argp
);
106 vwprintw(stdscr
, fmt
, argp
);
114 head_line(CONST_FMT
char *fmt
,...)
119 message(0, fmt
, argp
);
124 tail_line(CONST_FMT
char *fmt
,...)
129 message(LINES
- 1, fmt
, argp
);
134 * Arrow keys move cursor, return location at current on non-arrow key.
137 selectcell(WINDOW
*parent
,
144 static PAIR res
; /* result cell */
145 int si
= lri
- uli
+ 1; /* depth of the select area */
146 int sj
= lrj
- ulj
+ 1; /* width of the select area */
147 int i
= 0, j
= 0; /* offsets into the select area */
154 getparyx(child
, i
, j
);
156 getbegyx(child
, i
, j
);
157 i
-= uli
+ getbegy(parent
);
158 j
-= ulj
+ getbegx(parent
);
168 tail_line("Upper left [%2d,%2d] Lower right [%2d,%2d] -> %d,%d -> %d,%d",
173 wmove(parent
, uli
+ i
, ulj
+ j
);
175 switch (wgetch(parent
)) {
195 #ifdef NCURSES_MOUSE_VERSION
201 if (event
.y
> uli
&& event
.x
> ulj
) {
202 if (parent
!= stdscr
) {
203 i
= event
.y
- getbegy(parent
) - uli
;
204 j
= event
.x
- getbegx(parent
) - ulj
;
233 * If the caller can handle continuous movement, return the result.
245 * Ask user for a window definition.
248 getwindow(WINDOW
*parent
, PAIR
* ul
, PAIR
* lr
)
250 int min_col
= (parent
== stdscr
) ? COL_MIN
: 0;
251 int max_col
= (parent
== stdscr
) ? COL_MAX
: getmaxx(parent
);
252 int min_line
= (parent
== stdscr
) ? LINE_MIN
: 0;
253 int max_line
= (parent
== stdscr
) ? LINE_MAX
: getmaxy(parent
);
257 head_line("Use arrows to move cursor, anything else to mark corner 1");
258 if ((tmp
= selectcell(parent
, 0,
264 MvWAddCh(parent
, ul
->y
, ul
->x
, '*');
266 head_line("Use arrows to move cursor, anything else to mark corner 2");
267 if ((tmp
= selectcell(parent
, 0,
273 MvWAddCh(parent
, lr
->y
, lr
->x
, '*');
274 wmove(parent
, lr
->y
, lr
->x
);
277 result
= (lr
->y
!= ul
->y
&& lr
->x
!= ul
->x
);
285 * Draw a box inside the given window.
288 box_inside(WINDOW
*win
)
294 getmaxyx(win
, y1
, x1
);
296 MvWHLine(win
, 0, 0, ACS_HLINE
, x1
);
297 MvWHLine(win
, y1
- 1, 0, ACS_HLINE
, x1
);
299 MvWVLine(win
, 0, 0, ACS_VLINE
, y1
);
300 MvWVLine(win
, 0, x1
- 1, ACS_VLINE
, y1
);
302 MvWAddCh(win
, 0, 0, ACS_ULCORNER
);
303 MvWAddCh(win
, y1
- 1, 0, ACS_LLCORNER
);
304 MvWAddCh(win
, 0, x1
- 1, ACS_URCORNER
);
305 MvWAddCh(win
, y1
- 1, x1
- 1, ACS_LRCORNER
);
313 * Add a window to our list.
316 add_window(WINDOW
*parent
, WINDOW
*child
)
318 static unsigned have
= 0;
319 unsigned need
= ((num_windows
+ 1) | 31) + 1;
323 all_windows
= typeRealloc(FRAME
, need
, all_windows
);
325 failed("add_window");
327 all_windows
[num_windows
].parent
= parent
;
328 all_windows
[num_windows
].child
= child
;
333 window2num(WINDOW
*win
)
337 for (n
= 0; n
< (int) num_windows
; ++n
) {
338 if (win
== all_windows
[n
].child
) {
347 parent_of(WINDOW
*win
)
350 int n
= window2num(win
);
352 result
= all_windows
[n
].parent
;
357 repaint_one(WINDOW
*win
)
364 refresh_all(WINDOW
*win
)
368 for (n
= 0; n
< num_windows
; ++n
) {
369 if (all_windows
[n
].child
!= win
) {
370 repaint_one(all_windows
[n
].child
);
379 next_window(WINDOW
*win
)
381 WINDOW
*result
= win
;
382 int n
= window2num(win
);
385 result
= all_windows
[(unsigned) n
% num_windows
].child
;
393 prev_window(WINDOW
*win
)
395 WINDOW
*result
= win
;
396 int n
= window2num(win
);
400 n
= (int) (num_windows
- 1);
401 result
= all_windows
[(unsigned) n
% num_windows
].child
;
409 recur_move_window(WINDOW
*parent
, int dy
, int dx
)
413 for (n
= 0; n
< num_windows
; ++n
) {
414 if (all_windows
[n
].parent
== parent
) {
415 mvwin(all_windows
[n
].child
, dy
, dx
);
416 recur_move_window(all_windows
[n
].child
, dy
, dx
);
425 move_window(WINDOW
*win
, bool recur
)
427 WINDOW
*parent
= parent_of(win
);
431 bool top
= (parent
== stdscr
);
432 int min_col
= top
? COL_MIN
: 0;
433 int max_col
= top
? COL_MAX
: getmaxx(parent
);
434 int min_line
= top
? LINE_MIN
: 0;
435 int max_line
= top
? LINE_MAX
: getmaxy(parent
);
439 head_line("Select new position for %swindow", top
? "" : "sub");
441 while ((tmp
= selectcell(parent
,
448 getbegyx(parent
, y0
, x0
);
450 * Moving a subwindow has the effect of moving a viewport around
451 * the screen. The parent window retains the contents of the
452 * subwindow in the original location, but the viewport will show
453 * the contents (again) at the new location. So it will look odd
456 if (mvwin(win
, y0
+ tmp
->y
, x0
+ tmp
->x
) != ERR
) {
458 recur_move_window(win
, tmp
->y
, tmp
->x
);
475 show_derwin(WINDOW
*win
)
477 int pary
, parx
, maxy
, maxx
;
479 getmaxyx(win
, maxy
, maxx
);
480 getparyx(win
, pary
, parx
);
482 head_line("Select new position for derived window at %d,%d (%d,%d)",
483 pary
, parx
, maxy
, maxx
);
490 move_derwin(WINDOW
*win
)
492 WINDOW
*parent
= parent_of(win
);
496 bool top
= (parent
== stdscr
);
497 int min_col
= top
? COL_MIN
: 0;
498 int max_col
= top
? COL_MAX
: getmaxx(parent
);
499 int min_line
= top
? LINE_MIN
: 0;
500 int max_line
= top
? LINE_MAX
: getmaxy(parent
);
505 while ((tmp
= selectcell(parent
,
511 if (mvderwin(win
, tmp
->y
, tmp
->x
) != ERR
) {
530 fill_window(WINDOW
*win
, chtype ch
)
537 getmaxyx(win
, y1
, x1
);
538 for (y
= 0; y
< y1
; ++y
) {
539 for (x
= 0; x
< x1
; ++x
) {
540 MvWAddCh(win
, y
, x
, ch
);
549 fill_with_pattern(WINDOW
*win
)
557 getmaxyx(win
, y1
, x1
);
558 for (y
= 0; y
< y1
; ++y
) {
559 for (x
= 0; x
< x1
; ++x
) {
560 MvWAddCh(win
, y
, x
, (chtype
) ch
);
570 #define lines_of(ul,lr) (lr.y - ul.y + 1)
571 #define cols_of(ul,lr) (lr.x - ul.x + 1)
572 #define pair_of(ul) ul.y, ul.x
575 create_my_window(WINDOW
*current
)
580 if (getwindow(stdscr
, &ul
, &lr
)) {
581 result
= newwin(lines_of(ul
, lr
), cols_of(ul
, lr
), pair_of(ul
));
583 fill_window(result
, 'c');
584 add_window(stdscr
, result
);
593 create_my_derwin(WINDOW
*parent
)
598 if (getwindow(parent
, &ul
, &lr
)) {
599 result
= derwin(parent
, lines_of(ul
, lr
), cols_of(ul
, lr
), pair_of(ul
));
601 fill_window(result
, 'd');
602 add_window(parent
, result
);
611 create_my_subwin(WINDOW
*parent
)
616 if (getwindow(parent
, &ul
, &lr
)) {
617 result
= subwin(parent
,
620 ul
.y
+ getbegy(parent
),
621 ul
.x
+ getbegx(parent
));
623 fill_window(result
, 's');
624 add_window(parent
, result
);
633 show_help(WINDOW
*current
)
638 CONST_FMT
char * msg
;
640 { '?', "Show this screen" },
641 { 'b', "Draw a box inside the current window" },
642 { 'c', "Create a new window" },
643 { 'd', "Create a new derived window" },
644 { 'D', "Move derived window (moves viewport)" },
645 { 'f', "Fill the current window with the next character" },
646 { 'F', "Fill the current window with a pattern" },
647 { 'm', "Move the current window" },
648 { 'M', "Move the current window (and its children)" },
650 { 's', "Create a new subwindow" },
651 { CTRL('L'), "Repaint all windows, doing current one last" },
652 { CTRL('N'), "Cursor to next window" },
653 { CTRL('P'), "Cursor to previous window" },
657 WINDOW
*mywin
= newwin(LINES
, COLS
, 0, 0);
660 for (row
= 0; row
< LINES
- 2 && row
< (int) SIZEOF(help
); ++row
) {
661 wmove(mywin
, row
+ 1, 1);
662 wprintw(mywin
, "%s", keyname(help
[row
].key
));
663 wmove(mywin
, row
+ 1, 20);
664 wprintw(mywin
, "%s", help
[row
].msg
);
670 refresh_all(current
);
674 main(int argc GCC_UNUSED
, char *argv
[]GCC_UNUSED
)
684 intrflush(stdscr
, FALSE
);
686 add_window(0, current_win
= stdscr
);
688 #ifdef NCURSES_MOUSE_VERSION
689 (void) mousemask(BUTTON1_CLICKED
, (mmask_t
*) NULL
);
690 #endif /* NCURSES_MOUSE_VERSION */
692 while (!done
&& (ch
= wgetch(current_win
)) != ERR
) {
695 getyx(current_win
, y
, x
);
699 show_help(current_win
);
702 box_inside(current_win
);
705 current_win
= create_my_window(current_win
);
708 current_win
= create_my_derwin(current_win
);
711 if (!move_derwin(current_win
)) {
717 fill_window(current_win
, (chtype
) wgetch(current_win
));
720 fill_with_pattern(current_win
);
724 if (!move_window(current_win
, (ch
== 'M'))) {
733 current_win
= create_my_subwin(current_win
);
736 refresh_all(current_win
);
739 current_win
= next_window(current_win
);
742 current_win
= prev_window(current_win
);
745 /* want to allow cursor to move around the current window too */
746 /* want to test the resizing of windows and subwindows too */
747 /* want to allow deleting a window also */
750 wmove(current_win
, y
, x
);
751 tail_line("unrecognized key (use '?' for help)");
755 tail_line("size [%d,%d] begin [%d,%d] parent [%d,%d]",
756 getmaxy(current_win
),
757 getmaxx(current_win
),
758 getbegy(current_win
),
759 getbegx(current_win
),
760 getpary(current_win
),
761 getparx(current_win
));
762 wmove(current_win
, 0, 0);
765 ExitProgram(EXIT_SUCCESS
);