--- /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; + } + } +}