ncurses 6.0 - patch 20170408
[ncurses.git] / test / movewindow.c
index a45121db91d6e732969a902868cee1874414f672..91c7266ad77998834cfe1b499303638342fc08a4 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 2006-2007,2008 Free Software Foundation, Inc.              *
+ * Copyright (c) 2006-2013,2017 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
  * authorization.                                                           *
  ****************************************************************************/
 /*
- * $Id: movewindow.c,v 1.21 2008/02/09 18:08:28 tom Exp $
+ * $Id: movewindow.c,v 1.40 2017/04/08 23:01:47 tom Exp $
  *
  * Demonstrate move functions for windows and derived windows from the curses
  * library.
  *
- * Thomas Dickey - 2006/2/11
+ * Author: Thomas E. Dickey
  */
 /*
 derwin
 mvderwin
 subwin
 mvwin
+
+TODO:
+    add command to reset subwindow's origin to coincide with parent.
+    add command to delete subwindow (check if it has subwindows though)
  */
 
 #include <test.priv.h>
@@ -75,6 +79,14 @@ static void tail_line(CONST_FMT char *fmt,...) GCC_PRINTFLIKE(1, 2);
 static unsigned num_windows;
 static FRAME *all_windows;
 
+static void
+failed(const char *s)
+{
+    perror(s);
+    endwin();
+    ExitProgram(EXIT_FAILURE);
+}
+
 static void
 message(int lineno, CONST_FMT char *fmt, va_list argp)
 {
@@ -122,7 +134,12 @@ tail_line(CONST_FMT char *fmt,...)
  * Arrow keys move cursor, return location at current on non-arrow key.
  */
 static PAIR *
-selectcell(WINDOW *parent, int uli, int ulj, int lri, int lrj)
+selectcell(WINDOW *parent,
+          WINDOW *child,
+          int uli, int ulj,
+          int lri, int lrj,
+          bool relative,
+          bool * more)
 {
     static PAIR res;           /* result cell */
     int si = lri - uli + 1;    /* depth of the select area */
@@ -131,25 +148,46 @@ selectcell(WINDOW *parent, int uli, int ulj, int lri, int lrj)
 
     res.y = uli;
     res.x = ulj;
+
+    if (child != 0) {
+       if (relative) {
+           getparyx(child, i, j);
+       } else {
+           getbegyx(child, i, j);
+           i -= uli + getbegy(parent);
+           j -= ulj + getbegx(parent);
+       }
+    }
+
+    if (more)
+       *more = FALSE;
+
     for (;;) {
-       tail_line("Upper left [%2d,%2d] Lower right [%2d,%2d] -> %d,%d",
+       bool moved = FALSE;
+
+       tail_line("Upper left [%2d,%2d] Lower right [%2d,%2d] -> %d,%d -> %d,%d",
                  uli, ulj,
                  lri, lrj,
+                 i, j,
                  uli + i, ulj + j);
        wmove(parent, uli + i, ulj + j);
 
        switch (wgetch(parent)) {
        case KEY_UP:
            i += si - 1;
+           moved = TRUE;
            break;
        case KEY_DOWN:
            i++;
+           moved = TRUE;
            break;
        case KEY_LEFT:
            j += sj - 1;
+           moved = TRUE;
            break;
        case KEY_RIGHT:
            j++;
+           moved = TRUE;
            break;
        case QUIT:
        case ESCAPE:
@@ -161,8 +199,13 @@ selectcell(WINDOW *parent, int uli, int ulj, int lri, int lrj)
 
                getmouse(&event);
                if (event.y > uli && event.x > ulj) {
-                   i = event.y - uli;
-                   j = event.x - ulj;
+                   if (parent != stdscr) {
+                       i = event.y - getbegy(parent) - uli;
+                       j = event.x - getbegx(parent) - ulj;
+                   } else {
+                       i = event.y - uli;
+                       j = event.x - ulj;
+                   }
                } else {
                    beep();
                    break;
@@ -175,8 +218,26 @@ selectcell(WINDOW *parent, int uli, int ulj, int lri, int lrj)
            res.x = ulj + j;
            return (&res);
        }
-       i %= si;
-       j %= sj;
+
+       if (si <= 0)
+           i = 0;
+       else
+           i %= si;
+
+       if (sj <= 0)
+           j = 0;
+       else
+           j %= sj;
+
+       /*
+        * If the caller can handle continuous movement, return the result.
+        */
+       if (moved && more) {
+           *more = TRUE;
+           res.y = uli + i;
+           res.x = ulj + j;
+           return (&res);
+       }
     }
 }
 
@@ -194,14 +255,22 @@ getwindow(WINDOW *parent, PAIR * ul, PAIR * lr)
     bool result = FALSE;
 
     head_line("Use arrows to move cursor, anything else to mark corner 1");
-    if ((tmp = selectcell(parent, min_line, min_col, max_line, max_col)) != 0) {
+    if ((tmp = selectcell(parent, 0,
+                         min_line, min_col,
+                         max_line, max_col,
+                         FALSE,
+                         (bool *) 0)) != 0) {
        *ul = *tmp;
-       mvwaddch(parent, ul->y, ul->x, '*');
+       MvWAddCh(parent, ul->y, ul->x, '*');
 
        head_line("Use arrows to move cursor, anything else to mark corner 2");
-       if ((tmp = selectcell(parent, ul->y, ul->x, max_line, max_col)) != 0) {
+       if ((tmp = selectcell(parent, 0,
+                             ul->y, ul->x,
+                             max_line, max_col,
+                             FALSE,
+                             (bool *) 0)) != 0) {
            *lr = *tmp;
-           mvwaddch(parent, lr->y, lr->x, '*');
+           MvWAddCh(parent, lr->y, lr->x, '*');
            wmove(parent, lr->y, lr->x);
            wsyncdown(parent);
            wrefresh(parent);
@@ -224,16 +293,16 @@ box_inside(WINDOW *win)
     getyx(win, y0, x0);
     getmaxyx(win, y1, x1);
 
-    mvwhline(win, 0, 0, ACS_HLINE, x1);
-    mvwhline(win, y1 - 1, 0, ACS_HLINE, x1);
+    MvWHLine(win, 0, 0, ACS_HLINE, x1);
+    MvWHLine(win, y1 - 1, 0, ACS_HLINE, x1);
 
-    mvwvline(win, 0, 0, ACS_VLINE, y1);
-    mvwvline(win, 0, x1 - 1, ACS_VLINE, y1);
+    MvWVLine(win, 0, 0, ACS_VLINE, y1);
+    MvWVLine(win, 0, x1 - 1, ACS_VLINE, y1);
 
-    mvwaddch(win, 0, 0, ACS_ULCORNER);
-    mvwaddch(win, y1 - 1, 0, ACS_LLCORNER);
-    mvwaddch(win, 0, x1 - 1, ACS_URCORNER);
-    mvwaddch(win, y1 - 1, x1 - 1, ACS_LRCORNER);
+    MvWAddCh(win, 0, 0, ACS_ULCORNER);
+    MvWAddCh(win, y1 - 1, 0, ACS_LLCORNER);
+    MvWAddCh(win, 0, x1 - 1, ACS_URCORNER);
+    MvWAddCh(win, y1 - 1, x1 - 1, ACS_LRCORNER);
 
     wsyncdown(win);
     wmove(win, y0, x0);
@@ -251,7 +320,9 @@ add_window(WINDOW *parent, WINDOW *child)
 
     keypad(child, TRUE);
     if (need > have) {
-       all_windows = (FRAME *) realloc(all_windows, need * sizeof(FRAME));
+       all_windows = typeRealloc(FRAME, need, all_windows);
+       if (!all_windows)
+           failed("add_window");
     }
     all_windows[num_windows].parent = parent;
     all_windows[num_windows].child = child;
@@ -311,7 +382,7 @@ next_window(WINDOW *win)
     int n = window2num(win);
 
     if (n++ >= 0) {
-       result = all_windows[n % num_windows].child;
+       result = all_windows[(unsigned) n % num_windows].child;
        wmove(result, 0, 0);
        wrefresh(result);
     }
@@ -326,8 +397,8 @@ prev_window(WINDOW *win)
 
     if (n-- >= 0) {
        if (n < 0)
-           n = num_windows - 1;
-       result = all_windows[n % num_windows].child;
+           n = (int) (num_windows - 1);
+       result = all_windows[(unsigned) n % num_windows].child;
        wmove(result, 0, 0);
        wrefresh(result);
     }
@@ -341,10 +412,7 @@ recur_move_window(WINDOW *parent, int dy, int dx)
 
     for (n = 0; n < num_windows; ++n) {
        if (all_windows[n].parent == parent) {
-           int y0, x0;
-
-           getbegyx(all_windows[n].child, y0, x0);
-           mvwin(all_windows[n].child, y0 + dy, x0 + dx);
+           mvwin(all_windows[n].child, dy, dx);
            recur_move_window(all_windows[n].child, dy, dx);
        }
     }
@@ -366,20 +434,24 @@ move_window(WINDOW *win, bool recur)
        int min_line = top ? LINE_MIN : 0;
        int max_line = top ? LINE_MAX : getmaxy(parent);
        PAIR *tmp;
+       bool more;
 
        head_line("Select new position for %swindow", top ? "" : "sub");
 
-       if ((tmp = selectcell(parent,
-                             min_line, min_col,
-                             max_line, max_col)) != 0) {
+       while ((tmp = selectcell(parent,
+                                win,
+                                min_line, min_col,
+                                max_line, max_col,
+                                FALSE,
+                                &more)) != 0) {
            int y0, x0;
            getbegyx(parent, y0, x0);
            /*
-            * Note:  Moving a subwindow has the effect of moving a viewport
-            * around the screen.  The parent window retains the contents of
-            * the subwindow in the original location, but the viewport will
-            * show the contents (again) at the new location.  So it will look
-            * odd when testing.
+            * Moving a subwindow has the effect of moving a viewport around
+            * the screen.  The parent window retains the contents of the
+            * subwindow in the original location, but the viewport will show
+            * the contents (again) at the new location.  So it will look odd
+            * when testing.
             */
            if (mvwin(win, y0 + tmp->y, x0 + tmp->x) != ERR) {
                if (recur) {
@@ -388,45 +460,69 @@ move_window(WINDOW *win, bool recur)
                refresh_all(win);
                doupdate();
                result = TRUE;
+           } else {
+               result = FALSE;
            }
+           if (!more)
+               break;
        }
     }
+    head_line("done");
     return result;
 }
 
+static void
+show_derwin(WINDOW *win)
+{
+    int pary, parx, maxy, maxx;
+
+    getmaxyx(win, maxy, maxx);
+    getparyx(win, pary, parx);
+
+    head_line("Select new position for derived window at %d,%d (%d,%d)",
+             pary, parx, maxy, maxx);
+}
+
 /*
  * test mvderwin().
  */
 static bool
-move_subwin(WINDOW *win)
+move_derwin(WINDOW *win)
 {
     WINDOW *parent = parent_of(win);
     bool result = FALSE;
 
     if (parent != 0) {
        bool top = (parent == stdscr);
-       if (!top) {
-           int min_col = top ? COL_MIN : 0;
-           int max_col = top ? COL_MAX : getmaxx(parent);
-           int min_line = top ? LINE_MIN : 0;
-           int max_line = top ? LINE_MAX : getmaxy(parent);
-           PAIR *tmp;
-
-           head_line("Select new position for subwindow");
-
-           if ((tmp = selectcell(parent,
-                                 min_line, min_col,
-                                 max_line, max_col)) != 0) {
-               int y0, x0;
-               getbegyx(parent, y0, x0);
-               if (mvderwin(win, y0 + tmp->y, x0 + tmp->x) != ERR) {
-                   refresh_all(win);
-                   doupdate();
-                   result = TRUE;
-               }
+       int min_col = top ? COL_MIN : 0;
+       int max_col = top ? COL_MAX : getmaxx(parent);
+       int min_line = top ? LINE_MIN : 0;
+       int max_line = top ? LINE_MAX : getmaxy(parent);
+       PAIR *tmp;
+       bool more;
+
+       show_derwin(win);
+       while ((tmp = selectcell(parent,
+                                win,
+                                min_line, min_col,
+                                max_line, max_col,
+                                TRUE,
+                                &more)) != 0) {
+           if (mvderwin(win, tmp->y, tmp->x) != ERR) {
+               refresh_all(win);
+               doupdate();
+               repaint_one(win);
+               doupdate();
+               result = TRUE;
+               show_derwin(win);
+           } else {
+               flash();
            }
+           if (!more)
+               break;
        }
     }
+    head_line("done");
     return result;
 }
 
@@ -441,7 +537,29 @@ fill_window(WINDOW *win, chtype ch)
     getmaxyx(win, y1, x1);
     for (y = 0; y < y1; ++y) {
        for (x = 0; x < x1; ++x) {
-           mvwaddch(win, y, x, ch);
+           MvWAddCh(win, y, x, ch);
+       }
+    }
+    wsyncdown(win);
+    wmove(win, y0, x0);
+    wrefresh(win);
+}
+
+static void
+fill_with_pattern(WINDOW *win)
+{
+    int y, x;
+    int y0, x0;
+    int y1, x1;
+    int ch = 'a';
+
+    getyx(win, y0, x0);
+    getmaxyx(win, y1, x1);
+    for (y = 0; y < y1; ++y) {
+       for (x = 0; x < x1; ++x) {
+           MvWAddCh(win, y, x, (chtype) ch);
+           if (++ch > 'z')
+               ch = 'a';
        }
     }
     wsyncdown(win);
@@ -523,12 +641,13 @@ show_help(WINDOW *current)
        { 'b',          "Draw a box inside the current window" },
        { 'c',          "Create a new window" },
        { 'd',          "Create a new derived window" },
+       { 'D',          "Move derived window (moves viewport)" },
        { 'f',          "Fill the current window with the next character" },
+       { 'F',          "Fill the current window with a pattern" },
        { 'm',          "Move the current window" },
        { 'M',          "Move the current window (and its children)" },
        { 'q',          "Quit" },
        { 's',          "Create a new subwindow" },
-       { 't',          "Move the current subwindow (moves content)" },
        { CTRL('L'),    "Repaint all windows, doing current one last" },
        { CTRL('N'),    "Cursor to next window" },
        { CTRL('P'),    "Cursor to previous window" },
@@ -571,6 +690,10 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
 #endif /* NCURSES_MOUSE_VERSION */
 
     while (!done && (ch = wgetch(current_win)) != ERR) {
+       int y, x;
+
+       getyx(current_win, y, x);
+
        switch (ch) {
        case '?':
            show_help(current_win);
@@ -584,9 +707,18 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
        case 'd':
            current_win = create_my_derwin(current_win);
            break;
+       case 'D':
+           if (!move_derwin(current_win)) {
+               tail_line("error");
+               continue;
+           }
+           break;
        case 'f':
            fill_window(current_win, (chtype) wgetch(current_win));
            break;
+       case 'F':
+           fill_with_pattern(current_win);
+           break;
        case 'm':
        case 'M':
            if (!move_window(current_win, (ch == 'M'))) {
@@ -600,12 +732,6 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
        case 's':
            current_win = create_my_subwin(current_win);
            break;
-       case 't':
-           if (!move_subwin(current_win)) {
-               tail_line("error");
-               continue;
-           }
-           break;
        case CTRL('L'):
            refresh_all(current_win);
            break;
@@ -621,6 +747,7 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
            /* want to allow deleting a window also */
 #endif
        default:
+           wmove(current_win, y, x);
            tail_line("unrecognized key (use '?' for help)");
            beep();
            continue;
@@ -635,5 +762,8 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
        wmove(current_win, 0, 0);
     }
     endwin();
+#if NO_LEAKS
+    free(all_windows);
+#endif
     ExitProgram(EXIT_SUCCESS);
 }