| // * this is for making emacs happy: -*-Mode: C++;-*- |
| /**************************************************************************** |
| * Copyright (c) 1998-2012,2013 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 * |
| * "Software"), to deal in the Software without restriction, including * |
| * without limitation the rights to use, copy, modify, merge, publish, * |
| * distribute, distribute with modifications, sublicense, and/or sell * |
| * copies of the Software, and to permit persons to whom the Software is * |
| * furnished to do so, subject to the following conditions: * |
| * * |
| * The above copyright notice and this permission notice shall be included * |
| * in all copies or substantial portions of the Software. * |
| * * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * |
| * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * |
| * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * |
| * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * |
| * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * |
| * * |
| * Except as contained in this notice, the name(s) of the above copyright * |
| * holders shall not be used in advertising or otherwise to promote the * |
| * sale, use or other dealings in this Software without prior written * |
| * authorization. * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Author: Juergen Pfeifer, 1999 * |
| ****************************************************************************/ |
| |
| #include "internal.h" |
| |
| #include <cursesw.h> |
| |
| MODULE_ID("$Id: cursespad.cc,v 1.17 2013/03/30 19:45:36 tom Exp $") |
| |
| NCursesPad::NCursesPad(int nlines, int ncols) |
| : NCursesWindow(), |
| viewWin(static_cast<NCursesWindow*>(0)), |
| viewSub(static_cast<NCursesWindow*>(0)), |
| h_gridsize(0), v_gridsize(0), |
| min_row(0), min_col(0) |
| { |
| w = ::newpad(nlines, ncols); |
| if (static_cast<WINDOW*>(0) == w) { |
| count--; |
| err_handler("Cannot construct window"); |
| } |
| alloced = TRUE; |
| } |
| |
| |
| int NCursesPad::driver (int key) |
| { |
| // Default implementation |
| switch(key) { |
| case KEY_UP: |
| // ======= |
| return REQ_PAD_UP; |
| case KEY_DOWN: |
| // ========= |
| return REQ_PAD_DOWN; |
| case KEY_LEFT: |
| // ========= |
| return REQ_PAD_LEFT; |
| case KEY_RIGHT: |
| // ========== |
| return REQ_PAD_RIGHT; |
| case KEY_EXIT: |
| // ========= |
| case CTRL('X'): |
| // ========== |
| return REQ_PAD_EXIT; |
| |
| default: return(key); |
| } |
| } |
| |
| |
| void NCursesPad::operator()(void) |
| { |
| NCursesWindow* W = Win(); |
| |
| if (static_cast<NCursesWindow*>(0) != W) { |
| int Width = W->width(); |
| int Height = W->height(); |
| |
| int req = REQ_PAD_REFRESH; |
| |
| W->keypad(TRUE); |
| W->meta(TRUE); |
| refresh(); |
| |
| do { |
| bool changed = FALSE; |
| |
| switch (req) { |
| case REQ_PAD_REFRESH: |
| // ================ |
| changed = TRUE; |
| break; |
| case REQ_PAD_LEFT: |
| // ============= |
| if (min_col > 0) { |
| changed = TRUE; |
| if (min_col < h_gridsize) |
| min_col = 0; |
| else |
| min_col -= h_gridsize; |
| } |
| else |
| OnNavigationError(req); |
| break; |
| case REQ_PAD_RIGHT: |
| // ============== |
| if (min_col < (width() - Width - 1)) { |
| changed = TRUE; |
| if (min_col > (width() - Width - h_gridsize - 1)) |
| min_col = width() - Width - 1; |
| else |
| min_col += h_gridsize; |
| } |
| else |
| OnNavigationError(req); |
| break; |
| case REQ_PAD_UP: |
| // =========== |
| if (min_row > 0) { |
| changed = TRUE; |
| if (min_row < v_gridsize) |
| min_row = 0; |
| else |
| min_row -= v_gridsize; |
| } |
| else |
| OnNavigationError(req); |
| break; |
| case REQ_PAD_DOWN: |
| // ============= |
| if (min_row < (height() - Height - 1)) { |
| changed = TRUE; |
| if (min_row > (height() - Height - v_gridsize - 1)) |
| min_row = height() - Height - 1; |
| else |
| min_row += v_gridsize; |
| } |
| else |
| OnNavigationError(req); |
| break; |
| |
| default: |
| OnUnknownOperation(req); |
| } |
| |
| if (changed) { |
| noutrefresh(); |
| W->syncup(); |
| OnOperation(req); |
| viewWin->refresh(); |
| } |
| } while( (req=driver(W->getch())) != REQ_PAD_EXIT ); |
| } |
| } |
| |
| |
| int NCursesPad::refresh() |
| { |
| int res = noutrefresh(); |
| if (res==OK && (static_cast<NCursesWindow*>(0) != viewWin)) { |
| res = (viewWin->refresh()); |
| } |
| return(res); |
| } |
| |
| int NCursesPad::noutrefresh() |
| { |
| int res = OK; |
| NCursesWindow* W = Win(); |
| if (static_cast<NCursesWindow*>(0) != W) { |
| int high = W->maxy(); |
| int wide = W->maxx(); |
| res = copywin(*W, min_row, min_col, |
| 0, 0, high, wide, |
| FALSE); |
| if (res==OK) { |
| W->syncup(); |
| res = viewWin->noutrefresh(); |
| } |
| } |
| return (res); |
| } |
| |
| void NCursesPad::setWindow(NCursesWindow& view, |
| int v_grid NCURSES_PARAM_INIT(1), |
| int h_grid NCURSES_PARAM_INIT(1)) |
| { |
| viewWin = &view; |
| min_row = min_col = 0; |
| if (h_grid <=0 || v_grid <= 0) |
| err_handler("Illegal Gridsize"); |
| else { |
| h_gridsize = h_grid; |
| v_gridsize = v_grid; |
| } |
| } |
| |
| void NCursesPad::setSubWindow(NCursesWindow& sub) |
| { |
| if (static_cast<NCursesWindow*>(0) == viewWin) |
| err_handler("Pad has no viewport"); |
| assert(viewWin != 0); |
| if (!viewWin->isDescendant(sub)) |
| THROW(new NCursesException("NCursesFramePad", E_SYSTEM_ERROR)); |
| viewSub = ⊂ |
| } |
| |
| void NCursesFramedPad::OnOperation(int pad_req) |
| { |
| (void) pad_req; |
| NCursesWindow* W = Win(); |
| NCursesWindow* W2 = getWindow(); |
| |
| if ((static_cast<NCursesWindow*>(0) != W) && (static_cast<NCursesWindow*>(0) != W2)) { |
| int Width = W->width(); |
| int Height = W->height(); |
| int i, row, col, h_len, v_len; |
| |
| int my_width = width(); |
| |
| if (my_width != 0) { |
| h_len = (Width*Width + my_width - 1) / my_width; |
| if (h_len==0) |
| h_len = 1; |
| if (h_len > Width) |
| h_len = Width; |
| } else { |
| h_len = 1; |
| } |
| |
| int my_height = height(); |
| |
| if (my_height != 0) { |
| v_len = (Height*Height + my_height - 1) / my_height; |
| if (v_len==0) |
| v_len = 1; |
| if (v_len > Height) |
| v_len = Height; |
| } else { |
| v_len = 1; |
| } |
| |
| if (my_width != 0) { |
| col = (min_col * Width + my_width - 1) / my_width; |
| if (col + h_len > Width) |
| col = Width - h_len; |
| } else { |
| col = 0; |
| } |
| |
| if (my_height != 0) { |
| row = (min_row * Height + my_height - 1) / my_height; |
| if (row + v_len > Height) |
| row = Height - v_len; |
| } else { |
| row = 0; |
| } |
| |
| W2->vline(1,Width+1,Height); |
| W2->attron(A_REVERSE); |
| if (v_len>=2) { |
| W2->addch(row+1,Width+1,ACS_UARROW); |
| for(i=2;i<v_len;i++) |
| W2->addch(row+i,Width+1,' '); |
| W2->addch(row+v_len,Width+1,ACS_DARROW); |
| } |
| else { |
| for(i=1;i<=v_len;i++) |
| W2->addch(row+i,Width+1,' '); |
| } |
| W2->attroff(A_REVERSE); |
| |
| W2->hline(Height+1,1,Width); |
| W2->attron(A_REVERSE); |
| if (h_len >= 2) { |
| W2->addch(Height+1,col+1,ACS_LARROW); |
| for(i=2;i<h_len;i++) |
| W2->addch(Height+1,col+i,' '); |
| W2->addch(Height+1,col+h_len,ACS_RARROW); |
| } |
| else { |
| for(i=1;i<=h_len;i++) |
| W2->addch(Height+1,col+i,' '); |
| } |
| W2->attroff(A_REVERSE); |
| } |
| } |