summaryrefslogtreecommitdiffstats
path: root/curses/curses.C
diff options
context:
space:
mode:
authorSam Varshavchik2013-08-19 16:39:41 -0400
committerSam Varshavchik2013-08-25 14:43:51 -0400
commit9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch)
tree7a81a04cb51efb078ee350859a64be2ebc6b8813 /curses/curses.C
parenta9520698b770168d1f33d6301463bb70a19655ec (diff)
downloadcourier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2
Initial checkin
Imported from subversion report, converted to git. Updated all paths in scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'curses/curses.C')
-rw-r--r--curses/curses.C524
1 files changed, 524 insertions, 0 deletions
diff --git a/curses/curses.C b/curses/curses.C
new file mode 100644
index 0000000..5dbf22f
--- /dev/null
+++ b/curses/curses.C
@@ -0,0 +1,524 @@
+/*
+**
+** Copyright 2002-2011, Double Precision Inc.
+**
+** See COPYING for distribution information.
+*/
+
+#include "curses_config.h"
+
+#include "mycurses.H"
+#include "widechar.H"
+#include "cursescontainer.H"
+#include "curseskeyhandler.H"
+
+#include <algorithm>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <iostream>
+
+bool Curses::keepgoing=false;
+bool Curses::shiftmode=false;
+
+std::string Curses::suspendCommand;
+
+#define TABSIZE 8
+
+const char Curses::Key::LEFT[]="LEFT",
+ Curses::Key::RIGHT[]="RIGHT",
+ Curses::Key::SHIFTLEFT[]="SHIFTLEFT",
+ Curses::Key::SHIFTRIGHT[]="SHIFTRIGHT",
+ Curses::Key::UP[]="UP",
+ Curses::Key::DOWN[]="DOWN",
+ Curses::Key::SHIFTUP[]="SHIFTUP",
+ Curses::Key::SHIFTDOWN[]="SHIFTDOWN",
+ Curses::Key::DEL[]="DEL",
+ Curses::Key::CLREOL[]="CLREOL",
+ Curses::Key::BACKSPACE[]="BACKSPACE",
+ Curses::Key::ENTER[]="ENTER",
+ Curses::Key::PGUP[]="PGUP",
+ Curses::Key::PGDN[]="PGDN",
+ Curses::Key::SHIFTPGUP[]="SHIFTPGUP",
+ Curses::Key::SHIFTPGDN[]="SHIFTPGDN",
+ Curses::Key::HOME[]="HOME",
+ Curses::Key::END[]="END",
+ Curses::Key::SHIFTHOME[]="SHIFTHOME",
+ Curses::Key::SHIFTEND[]="SHIFTEND",
+ Curses::Key::SHIFT[]="SHIFT",
+ Curses::Key::RESIZE[]="RESIZE";
+
+bool Curses::Key::operator==(const std::vector<unicode_char> &v) const
+{
+ return keycode == 0 &&
+ std::find(v.begin(), v.end(), ukey) != v.end();
+}
+
+Curses::Curses(CursesContainer *parentArg) : parent(parentArg),
+ row(0), col(0),
+ alignment(Curses::LEFT)
+{
+ if (parent != NULL)
+ parent->addChild(this);
+}
+
+Curses::~Curses()
+{
+ CursesContainer *p=getParent();
+
+ if (p)
+ p->deleteChild(this);
+
+ if (hasFocus())
+ currentFocus=0;
+}
+
+int Curses::getScreenWidth() const
+{
+ const CursesContainer *p=getParent();
+
+ while (p && p->getParent())
+ p=p->getParent();
+
+ return (p ? p->getWidth():0);
+}
+
+int Curses::getScreenHeight() const
+{
+ const CursesContainer *p=getParent();
+
+ while (p && p->getParent())
+ p=p->getParent();
+
+ return (p ? p->getHeight():0);
+}
+
+int Curses::getRow() const
+{
+ return row;
+}
+
+int Curses::getCol() const
+{
+ return col;
+}
+
+void Curses::setRow(int r)
+{
+ row=r;
+}
+
+void Curses::scrollTo(size_t r)
+{
+ if (parent)
+ parent->scrollTo(r + row);
+}
+
+void Curses::setCol(int c)
+{
+ col=c;
+}
+
+void Curses::resized()
+{
+ draw();
+}
+
+void Curses::getVerticalViewport(size_t &first_row,
+ size_t &nrows)
+{
+ CursesContainer *p=getParent();
+
+ if (!p)
+ {
+ first_row=0;
+ nrows=getHeight();
+ return;
+ }
+
+ p->getVerticalViewport(first_row, nrows);
+ size_t r=getRow();
+ size_t h=getHeight();
+
+
+ if (r + h <= first_row || r >= first_row + nrows)
+ {
+ first_row=nrows=0;
+ return;
+ }
+
+ if (first_row < r)
+ {
+ nrows -= r-first_row;
+ first_row=r;
+ }
+
+ first_row -= r;
+
+ if (first_row + nrows > h)
+ nrows=h-first_row;
+}
+
+void Curses::setAlignment(Alignment alignmentArg)
+{
+ alignment=alignmentArg;
+}
+
+Curses::Alignment Curses::getAlignment()
+{
+ return alignment;
+}
+
+int Curses::getRowAligned() const
+{
+ return row;
+}
+
+int Curses::getColAligned() const
+{
+ int c=col;
+
+ if (alignment == PARENTCENTER)
+ {
+ const CursesContainer *p=getParent();
+
+ if (p != NULL)
+ {
+ c=p->getWidth()/2;
+ c -= getWidth()/2;
+ }
+ }
+ else if (alignment == CENTER)
+ c -= getWidth() / 2;
+ else if (alignment == RIGHT)
+ c -= getWidth();
+ return c;
+}
+
+Curses *Curses::getDialogChild() const
+{
+ return NULL;
+}
+
+bool Curses::writeText(const char *text, int r, int c,
+ const CursesAttr &attr) const
+{
+ CursesContainer *p=parent;
+
+ if (!isDialog() && p && p->getDialogChild())
+ return false; // Parent has a dialog and it ain't us
+
+ if (p)
+ return p->writeText(text, r+getRowAligned(),
+ c+getColAligned(), attr);
+ return false;
+}
+
+bool Curses::writeText(const std::vector<unicode_char> &text, int r, int c,
+ const Curses::CursesAttr &attr) const
+{
+ CursesContainer *p=parent;
+
+ if (!isDialog() && p && p->getDialogChild())
+ return false; // Parent has a dialog and it ain't us
+
+ if (p)
+ return p->writeText(text, r+getRowAligned(),
+ c+getColAligned(), attr);
+ return false;
+}
+
+
+void Curses::writeText(std::string text, int row, int col,
+ const CursesAttr &attr) const
+{
+ writeText(text.c_str(), row, col, attr);
+}
+
+bool Curses::isDialog() const
+{
+ return false;
+}
+
+void Curses::erase()
+{
+ const CursesContainer *p=getParent();
+
+ if (!isDialog() && p && p->getDialogChild())
+ return; // Parent has a dialog and it ain't us
+
+ size_t w=getWidth();
+ size_t h=getHeight();
+
+ std::vector<unicode_char> spaces;
+
+ spaces.insert(spaces.end(), w, ' ');
+
+ size_t i;
+
+ CursesAttr attr;
+
+ for (i=0; i<h; i++)
+ writeText(spaces, i, 0, attr);
+}
+
+void Curses::beepError()
+{
+ CursesContainer *p=getParent();
+
+ if (p)
+ p->beepError();
+}
+
+Curses *Curses::currentFocus=0;
+
+void Curses::requestFocus()
+{
+ Curses *oldFocus=currentFocus;
+
+ currentFocus=NULL;
+
+ cursesPtr<Curses> ptr=this;
+
+ if (oldFocus)
+ oldFocus->focusLost();
+
+ if (!ptr.isDestroyed() && currentFocus == NULL)
+ {
+ currentFocus=this;
+ focusGained();
+ }
+}
+
+void Curses::dropFocus()
+{
+ Curses *oldFocus=currentFocus;
+
+ currentFocus=NULL;
+
+ if (oldFocus)
+ oldFocus->focusLost();
+}
+
+void Curses::focusGained()
+{
+ draw();
+}
+
+void Curses::focusLost()
+{
+ draw();
+}
+
+void Curses::flush()
+{
+ CursesContainer *p=getParent();
+
+ if (p)
+ p->flush();
+}
+
+bool Curses::hasFocus()
+{
+ return currentFocus == this;
+}
+
+int Curses::getCursorPosition(int &r, int &c)
+{
+ r += getRowAligned();
+ c += getColAligned();
+
+ CursesContainer *parent=getParent();
+ if (parent)
+ return parent->getCursorPosition(r, c);
+
+ return 1;
+}
+
+
+bool Curses::processKey(const Key &k)
+{
+ if (k == Key::RESIZE)
+ return true; // No-op.
+
+ return CursesKeyHandler::handle(k, currentFocus);
+}
+
+bool Curses::processKeyInFocus(const Key &key)
+{
+ if ((key.plain() && key.ukey == '\t')
+ || key == key.DOWN || key == key.SHIFTDOWN
+ || key == key.ENTER)
+ {
+ transferNextFocus();
+ return true;
+ }
+
+ if (key == key.UP || key == key.SHIFTUP)
+ {
+ transferPrevFocus();
+ return true;
+ }
+
+ if (key == key.PGUP || key == key.SHIFTPGUP)
+ {
+ int h=getScreenHeight();
+
+ if (h > 5)
+ h -= 5;
+
+ if (h < 5)
+ h=5;
+
+ while (h)
+ {
+ processKey(Key(key ==
+ Key::PGUP ? Key::UP:Key::SHIFTUP));
+ --h;
+ }
+ return true;
+ }
+
+ if (key == key.PGDN || key == key.SHIFTPGDN)
+ {
+ int h=getScreenHeight();
+
+ if (h > 5)
+ h -= 5;
+
+ if (h < 5)
+ h=5;
+
+ while (h)
+ {
+ processKey(Key(key ==
+ Key::PGDN ? Key::DOWN:Key::SHIFTDOWN));
+ --h;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool Curses::isFocusable()
+{
+ return 0;
+}
+
+void Curses::transferNextFocus()
+{
+ Curses *p=this;
+
+ do
+ {
+ p=p->getNextFocus();
+
+ } while (p != NULL && !p->isFocusable());
+
+ if (p)
+ p->requestFocus();
+}
+
+void Curses::transferPrevFocus()
+{
+ Curses *p=this;
+
+ do
+ {
+ p=p->getPrevFocus();
+ } while (p != NULL && !p->isFocusable());
+
+ if (p)
+ p->requestFocus();
+}
+
+bool Curses::childPositionCompareFunc(Curses *a, Curses *b)
+{
+ if (a->getRow() < b->getRow())
+ return true;
+
+ if (a->getRow() == b->getRow())
+ {
+ if (a->getCol() < b->getCol())
+ return true;
+ if (a->getCol() == b->getCol())
+ {
+ CursesContainer *p=a->getParent();
+ size_t ai, bi;
+
+ for (ai=0; ai<p->children.size(); ai++)
+ if (a == p->children[ai].child)
+ {
+ for (bi=0; bi<p->children.size(); bi++)
+ if (b == p->children[bi].child)
+ return ai < bi;
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+Curses *Curses::getNextFocus()
+{
+ CursesContainer *p=getParent();
+ Curses *child=this;
+
+ while (p != NULL)
+ {
+ size_t i;
+ Curses *nextFocusPtr=NULL;
+
+ for (i=0; i<p->children.size(); i++)
+ if ( childPositionCompareFunc(child,
+ p->children[i].child) &&
+ (nextFocusPtr == NULL ||
+ childPositionCompareFunc(p->children[i].child,
+ nextFocusPtr)))
+ nextFocusPtr=p->children[i].child;
+
+ if (nextFocusPtr)
+ return nextFocusPtr;
+
+ if (p->isDialog())
+ break; // Do not cross dialog box boundaries.
+
+ child=p;
+ p=p->getParent();
+ }
+ return NULL;
+}
+
+Curses *Curses::getPrevFocus()
+{
+ CursesContainer *p=getParent();
+ Curses *child=this;
+
+ while (p != NULL)
+ {
+ size_t i;
+
+ Curses *prevFocusPtr=NULL;
+
+ for (i=0; i<p->children.size(); i++)
+ if ( childPositionCompareFunc(p->children[i].child,
+ child) &&
+ (prevFocusPtr == NULL ||
+ childPositionCompareFunc(prevFocusPtr,
+ p->children[i].child)))
+ prevFocusPtr=p->children[i].child;
+
+ if (prevFocusPtr)
+ return prevFocusPtr;
+
+ if (p->isDialog())
+ break; // Do not cross dialog box boundaries.
+
+ child=p;
+ p=p->getParent();
+ }
+ return NULL;
+}