pdcurses/window.c

changeset 97
2d43f05b284c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pdcurses/window.c	Thu Jul 23 18:07:39 2015 +0300
@@ -0,0 +1,562 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: window.c,v 1.62 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         window
+
+  Synopsis:
+        WINDOW *newwin(int nlines, int ncols, int begy, int begx);
+        WINDOW *derwin(WINDOW* orig, int nlines, int ncols,
+                int begy, int begx);
+        WINDOW *subwin(WINDOW* orig, int nlines, int ncols,
+                int begy, int begx);
+        WINDOW *dupwin(WINDOW *win);
+        int delwin(WINDOW *win);
+        int mvwin(WINDOW *win, int y, int x);
+        int mvderwin(WINDOW *win, int pary, int parx);
+        int syncok(WINDOW *win, bool bf);
+        void wsyncup(WINDOW *win);
+        void wcursyncup(WINDOW *win);
+        void wsyncdown(WINDOW *win);
+
+        WINDOW *resize_window(WINDOW *win, int nlines, int ncols);
+        int wresize(WINDOW *win, int nlines, int ncols);
+        WINDOW *PDC_makelines(WINDOW *win);
+        WINDOW *PDC_makenew(int nlines, int ncols, int begy, int begx);
+        void PDC_sync(WINDOW *win);
+
+  Description:
+        newwin() creates a new window with the given number of lines,
+        nlines and columns, ncols. The upper left corner of the window
+        is at line begy, column begx. If nlines is zero, it defaults to
+        LINES - begy; ncols to COLS - begx. Create a new full-screen
+        window by calling newwin(0, 0, 0, 0).
+
+        delwin() deletes the named window, freeing all associated 
+        memory. In the case of overlapping windows, subwindows should be 
+        deleted before the main window.
+
+        mvwin() moves the window so that the upper left-hand corner is
+        at position (y,x). If the move would cause the window to be off
+        the screen, it is an error and the window is not moved. Moving
+        subwindows is allowed.
+
+        subwin() creates a new subwindow within a window.  The
+        dimensions of the subwindow are nlines lines and ncols columns.
+        The subwindow is at position (begy, begx) on the screen.  This
+        position is relative to the screen, and not to the window orig.
+        Changes made to either window will affect both.  When using this
+        routine, you will often need to call touchwin() before calling
+        wrefresh().
+
+        derwin() is the same as subwin(), except that begy and begx are
+        relative to the origin of the window orig rather than the
+        screen.  There is no difference between subwindows and derived
+        windows.
+
+        mvderwin() moves a derived window (or subwindow) inside its
+        parent window.  The screen-relative parameters of the window are
+        not changed.  This routine is used to display different parts of
+        the parent window at the same physical position on the screen.
+
+        dupwin() creates an exact duplicate of the window win.
+
+        wsyncup() causes a touchwin() of all of the window's parents.
+
+        If wsyncok() is called with a second argument of TRUE, this
+        causes a wsyncup() to be called every time the window is
+        changed.
+
+        wcursyncup() causes the current cursor position of all of a
+        window's ancestors to reflect the current cursor position of the
+        current window.
+
+        wsyncdown() causes a touchwin() of the current window if any of
+        its parent's windows have been touched.
+
+        resize_window() allows the user to resize an existing window. It 
+        returns the pointer to the new window, or NULL on failure.
+
+        wresize() is an ncurses-compatible wrapper for resize_window().
+        Note that, unlike ncurses, it will NOT process any subwindows of
+        the window. (However, you still can call it _on_ subwindows.) It 
+        returns OK or ERR.
+
+        PDC_makenew() allocates all data for a new WINDOW * except the
+        actual lines themselves. If it's unable to allocate memory for
+        the window structure, it will free all allocated memory and
+        return a NULL pointer.
+
+        PDC_makelines() allocates the memory for the lines.
+
+        PDC_sync() handles wrefresh() and wsyncup() calls when a window
+        is changed.
+
+  Return Value:
+        newwin(), subwin(), derwin() and dupwin() return a pointer
+        to the new window, or NULL on failure. delwin(), mvwin(),
+        mvderwin() and syncok() return OK or ERR. wsyncup(),
+        wcursyncup() and wsyncdown() return nothing.
+
+  Errors:
+        It is an error to call resize_window() before calling initscr().
+        Also, an error will be generated if we fail to create a newly
+        sized replacement window for curscr, or stdscr. This could
+        happen when increasing the window size. NOTE: If this happens,
+        the previously successfully allocated windows are left alone;
+        i.e., the resize is NOT cancelled for those windows.
+
+  Portability                                X/Open    BSD    SYS V
+        newwin                                  Y       Y       Y
+        delwin                                  Y       Y       Y
+        mvwin                                   Y       Y       Y
+        subwin                                  Y       Y       Y
+        derwin                                  Y       -       Y
+        mvderwin                                Y       -       Y
+        dupwin                                  Y       -      4.0
+        wsyncup                                 Y       -      4.0
+        syncok                                  Y       -      4.0
+        wcursyncup                              Y       -      4.0
+        wsyncdown                               Y       -      4.0
+        resize_window                           -       -       -
+        wresize                                 -       -       -
+        PDC_makelines                           -       -       -
+        PDC_makenew                             -       -       -
+        PDC_sync                                -       -       -
+
+**man-end****************************************************************/
+
+#include <stdlib.h>
+
+WINDOW *PDC_makenew(int nlines, int ncols, int begy, int begx)
+{
+    WINDOW *win;
+
+    PDC_LOG(("PDC_makenew() - called: lines %d cols %d begy %d begx %d\n",
+             nlines, ncols, begy, begx));
+
+    /* allocate the window structure itself */
+
+    if ((win = calloc(1, sizeof(WINDOW))) == (WINDOW *)NULL)
+        return win;
+
+    /* allocate the line pointer array */
+
+    if ((win->_y = malloc(nlines * sizeof(chtype *))) == NULL)
+    {
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    /* allocate the minchng and maxchng arrays */
+
+    if ((win->_firstch = malloc(nlines * sizeof(int))) == NULL)
+    {
+        free(win->_y);
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    if ((win->_lastch = malloc(nlines * sizeof(int))) == NULL)
+    {
+        free(win->_firstch);
+        free(win->_y);
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    /* initialize window variables */
+
+    win->_maxy = nlines;  /* real max screen size */
+    win->_maxx = ncols;   /* real max screen size */
+    win->_begy = begy;
+    win->_begx = begx;
+    win->_bkgd = ' ';     /* wrs 4/10/93 -- initialize background to blank */
+    win->_clear = (bool) ((nlines == LINES) && (ncols == COLS));
+    win->_bmarg = nlines - 1;
+    win->_parx = win->_pary = -1;
+
+    /* init to say window all changed */
+
+    touchwin(win);
+
+    return win;
+}
+
+WINDOW *PDC_makelines(WINDOW *win)
+{
+    int i, j, nlines, ncols;
+
+    PDC_LOG(("PDC_makelines() - called: lines %d cols %d\n", nlines, ncols));
+
+    if (!win)
+        return (WINDOW *)NULL;
+
+    nlines = win->_maxy;
+    ncols = win->_maxx;
+
+    for (i = 0; i < nlines; i++)
+    {
+        if ((win->_y[i] = malloc(ncols * sizeof(chtype))) == NULL)
+        {
+            /* if error, free all the data */
+
+            for (j = 0; j < i; j++)
+                free(win->_y[j]);
+
+            free(win->_firstch);
+            free(win->_lastch);
+            free(win->_y);
+            free(win);
+
+            return (WINDOW *)NULL;
+        }
+    }
+
+    return win;
+}
+
+void PDC_sync(WINDOW *win)
+{
+    PDC_LOG(("PDC_sync() - called:\n"));
+
+    if (win->_immed)
+        wrefresh(win);
+    if (win->_sync)
+        wsyncup(win);
+}
+
+WINDOW *newwin(int nlines, int ncols, int begy, int begx)
+{
+    WINDOW *win;
+
+    PDC_LOG(("newwin() - called:lines=%d cols=%d begy=%d begx=%d\n",
+             nlines, ncols, begy, begx));
+
+    if (!nlines)
+        nlines = LINES - begy;
+    if (!ncols)
+        ncols  = COLS  - begx;
+
+    if ( (begy + nlines > SP->lines || begx + ncols > SP->cols)
+        || !(win = PDC_makenew(nlines, ncols, begy, begx))
+        || !(win = PDC_makelines(win)) )
+        return (WINDOW *)NULL;
+
+    werase(win);
+
+    return win;
+}
+
+int delwin(WINDOW *win)
+{
+    int i;
+
+    PDC_LOG(("delwin() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    /* subwindows use parents' lines */
+
+    if (!(win->_flags & (_SUBWIN|_SUBPAD)))
+        for (i = 0; i < win->_maxy && win->_y[i]; i++)
+            if (win->_y[i])
+                free(win->_y[i]);
+
+    free(win->_firstch);
+    free(win->_lastch);
+    free(win->_y);
+    free(win);
+
+    return OK;
+}
+
+int mvwin(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwin() - called\n"));
+
+    if (!win || (y + win->_maxy > LINES || y < 0)
+             || (x + win->_maxx > COLS || x < 0))
+        return ERR;
+
+    win->_begy = y;
+    win->_begx = x;
+    touchwin(win);
+
+    return OK;
+}
+
+WINDOW *subwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
+{
+    WINDOW *win;
+    int i;
+    int j = begy - orig->_begy;
+    int k = begx - orig->_begx;
+
+    PDC_LOG(("subwin() - called: lines %d cols %d begy %d begx %d\n",
+             nlines, ncols, begy, begx));
+
+    /* make sure window fits inside the original one */
+
+    if (!orig || (begy < orig->_begy) || (begx < orig->_begx) ||
+        (begy + nlines) > (orig->_begy + orig->_maxy) ||
+        (begx + ncols) > (orig->_begx + orig->_maxx))
+        return (WINDOW *)NULL;
+
+    if (!nlines)
+        nlines = orig->_maxy - 1 - j;
+    if (!ncols)
+        ncols  = orig->_maxx - 1 - k;
+
+    if ( !(win = PDC_makenew(nlines, ncols, begy, begx)) )
+        return (WINDOW *)NULL;
+
+    /* initialize window variables */
+
+    win->_attrs = orig->_attrs;
+    win->_bkgd = orig->_bkgd;
+    win->_leaveit = orig->_leaveit;
+    win->_scroll = orig->_scroll;
+    win->_nodelay = orig->_nodelay;
+    win->_use_keypad = orig->_use_keypad;
+    win->_immed = orig->_immed;
+    win->_sync = orig->_sync;
+    win->_pary = j;
+    win->_parx = k;
+    win->_parent = orig;
+
+    for (i = 0; i < nlines; i++, j++)
+        win->_y[i] = orig->_y[j] + k;
+
+    win->_flags |= _SUBWIN;
+
+    return win;
+}
+
+WINDOW *derwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
+{
+    return subwin(orig, nlines, ncols, begy + orig->_begy, begx + orig->_begx);
+}
+
+int mvderwin(WINDOW *win, int pary, int parx)
+{
+    int i, j;
+    WINDOW *mypar;
+
+    if (!win || !(win->_parent))
+        return ERR;
+
+    mypar = win->_parent;
+
+    if (pary < 0 || parx < 0 || (pary + win->_maxy) > mypar->_maxy ||
+                                (parx + win->_maxx) > mypar->_maxx)
+        return ERR;
+
+    j = pary;
+
+    for (i = 0; i < win->_maxy; i++)
+        win->_y[i] = (mypar->_y[j++]) + parx;
+
+    win->_pary = pary;
+    win->_parx = parx;
+
+    return OK;
+}
+
+WINDOW *dupwin(WINDOW *win)
+{
+    WINDOW *new;
+    chtype *ptr, *ptr1;
+    int nlines, ncols, begy, begx, i;
+
+    if (!win)
+        return (WINDOW *)NULL;
+
+    nlines = win->_maxy;
+    ncols = win->_maxx;
+    begy = win->_begy;
+    begx = win->_begx;
+
+    if ( !(new = PDC_makenew(nlines, ncols, begy, begx))
+        || !(new = PDC_makelines(new)) )
+        return (WINDOW *)NULL;
+
+    /* copy the contents of win into new */
+
+    for (i = 0; i < nlines; i++)
+    {
+        for (ptr = new->_y[i], ptr1 = win->_y[i];
+             ptr < new->_y[i] + ncols; ptr++, ptr1++)
+            *ptr = *ptr1;
+
+        new->_firstch[i] = 0;
+        new->_lastch[i] = ncols - 1;
+    }
+
+    new->_curx = win->_curx;
+    new->_cury = win->_cury;
+    new->_maxy = win->_maxy;
+    new->_maxx = win->_maxx;
+    new->_begy = win->_begy;
+    new->_begx = win->_begx;
+    new->_flags = win->_flags;
+    new->_attrs = win->_attrs;
+    new->_clear = win->_clear;
+    new->_leaveit = win->_leaveit;
+    new->_scroll = win->_scroll;
+    new->_nodelay = win->_nodelay;
+    new->_use_keypad = win->_use_keypad;
+    new->_tmarg = win->_tmarg;
+    new->_bmarg = win->_bmarg;
+    new->_parx = win->_parx;
+    new->_pary = win->_pary;
+    new->_parent = win->_parent;
+    new->_bkgd = win->_bkgd;
+    new->_flags = win->_flags;
+
+    return new;
+}
+
+WINDOW *resize_window(WINDOW *win, int nlines, int ncols)
+{
+    WINDOW *new;
+    int i, save_cury, save_curx, new_begy, new_begx;
+
+    PDC_LOG(("resize_window() - called: nlines %d ncols %d\n",
+             nlines, ncols));
+
+    if (!win)
+        return (WINDOW *)NULL;
+
+    if (win->_flags & _SUBPAD)
+    {
+        if ( !(new = subpad(win->_parent, nlines, ncols,
+                            win->_begy, win->_begx)) )
+            return (WINDOW *)NULL;
+    }
+    else if (win->_flags & _SUBWIN)
+    {
+        if ( !(new = subwin(win->_parent, nlines, ncols,
+                            win->_begy, win->_begx)) )
+            return (WINDOW *)NULL;
+    }
+    else
+    {
+        if (win == SP->slk_winptr)
+        {
+            new_begy = SP->lines - SP->slklines;
+            new_begx = 0;
+        }
+        else
+        {
+            new_begy = win->_begy;
+            new_begx = win->_begx;
+        }
+
+        if ( !(new = PDC_makenew(nlines, ncols, new_begy, new_begx)) )
+            return (WINDOW *)NULL;
+    }
+
+    save_curx = min(win->_curx, new->_maxx);
+    save_cury = min(win->_cury, new->_maxy);
+
+    if (!(win->_flags & (_SUBPAD|_SUBWIN)))
+    {
+        if ( !(new = PDC_makelines(new)) )
+            return (WINDOW *)NULL;
+
+        werase(new);
+
+        copywin(win, new, 0, 0, 0, 0, min(win->_maxy, new->_maxy) - 1,
+                min(win->_maxx, new->_maxx) - 1, FALSE);
+
+        for (i = 0; i < win->_maxy && win->_y[i]; i++)
+            if (win->_y[i])
+                free(win->_y[i]);
+    }
+
+    new->_flags = win->_flags;
+    new->_attrs = win->_attrs;
+    new->_clear = win->_clear;
+    new->_leaveit = win->_leaveit;
+    new->_scroll = win->_scroll;
+    new->_nodelay = win->_nodelay;
+    new->_use_keypad = win->_use_keypad;
+    new->_tmarg = (win->_tmarg > new->_maxy - 1) ? 0 : win->_tmarg;
+    new->_bmarg = (win->_bmarg == win->_maxy - 1) ?
+                  new->_maxy - 1 : min(win->_bmarg, (new->_maxy - 1));
+    new->_parent = win->_parent;
+    new->_immed = win->_immed;
+    new->_sync = win->_sync;
+    new->_bkgd = win->_bkgd;
+
+    new->_curx = save_curx;
+    new->_cury = save_cury;
+
+    free(win->_firstch);
+    free(win->_lastch);
+    free(win->_y);
+
+    *win = *new;
+    free(new);
+
+    return win;
+}
+
+int wresize(WINDOW *win, int nlines, int ncols)
+{
+    return (resize_window(win, nlines, ncols) ? OK : ERR);
+}
+
+void wsyncup(WINDOW *win)
+{
+    WINDOW *tmp;
+
+    PDC_LOG(("wsyncup() - called\n"));
+
+    for (tmp = win; tmp; tmp = tmp->_parent)
+        touchwin(tmp);
+}
+
+int syncok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("syncok() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_sync = bf;
+
+    return OK;
+}
+
+void wcursyncup(WINDOW *win)
+{
+    WINDOW *tmp;
+
+    PDC_LOG(("wcursyncup() - called\n"));
+
+    for (tmp = win; tmp && tmp->_parent; tmp = tmp->_parent)
+        wmove(tmp->_parent, tmp->_pary + tmp->_cury, tmp->_parx + tmp->_curx);
+}
+
+void wsyncdown(WINDOW *win)
+{
+    WINDOW *tmp;
+
+    PDC_LOG(("wsyncdown() - called\n"));
+
+    for (tmp = win; tmp; tmp = tmp->_parent)
+    {
+        if (is_wintouched(tmp))
+        {
+            touchwin(win);
+            break;
+        }
+    }
+}

mercurial