ncursesw-morphos/c++/demo.cc
Thomas E. Dickey 8b06e371ed ncurses 5.9 - patch 20120225
+ modify configure script to allow creating dll's for MinGW when
  cross-compiling.
+ add --enable-string-hacks option to control whether strlcat and
  strlcpy may be used.  The same issue applies to OpenBSD's warnings
  about snprintf, noting that this function is weakly standardized.
+ add configure checks for strlcat, strlcpy and snprintf, to help
  reduce bogus warnings with OpenBSD builds.
+ build-fix for OpenBSD 4.9 to supply consistent intptr_t declaration
  (cf:20111231)
+ update config.guess, config.sub
2012-02-26 01:59:00 +00:00

571 lines
14 KiB
C++

// * This makes emacs happy -*-Mode: C++;-*-
/****************************************************************************
* Copyright (c) 1998-2011,2012 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. *
****************************************************************************/
/*
* Silly demo program for the NCursesPanel class.
*
* written by Anatoly Ivasyuk (anatoly@nick.csh.rit.edu)
*
* Demo code for NCursesMenu and NCursesForm written by
* Juergen Pfeifer
*
* $Id: demo.cc,v 1.41 2012/02/23 10:41:56 tom Exp $
*/
#include "internal.h"
#include "cursesapp.h"
#include "cursesm.h"
#include "cursesf.h"
#ifdef __MINGW32__
#undef KEY_EVENT
#endif
#ifndef __MINGW32__
extern "C" unsigned int sleep(unsigned int);
#endif
#undef index // needed for NeXT
//
// -------------------------------------------------------------------------
//
class SillyDemo
{
public:
void run(int sleeptime) {
NCursesPanel *mystd = new NCursesPanel();
// Make a few small demo panels
NCursesPanel *u = new NCursesPanel(8, 20, 12, 4);
NCursesPanel *v = new NCursesPanel(8, 20, 10, 6);
NCursesPanel *w = new NCursesPanel(8, 20, 8, 8);
NCursesPanel *x = new NCursesPanel(8, 20, 6, 10);
NCursesPanel *y = new NCursesPanel(8, 20, 4, 12);
NCursesPanel *z = new NCursesPanel(8, 30, 2, 14);
// Draw something on the main screen, so we can see what happens
// when panels get moved or deleted.
mystd->box();
mystd->move(mystd->height()/2, 1);
mystd->hline(mystd->width()-2);
mystd->move(1, mystd->width()/2);
mystd->vline(mystd->height()-2);
mystd->addch(0, mystd->width()/2, ACS_TTEE);
mystd->addch(mystd->height()-1, mystd->width()/2, ACS_BTEE);
mystd->addch(mystd->height()/2, 0, ACS_LTEE);
mystd->addch(mystd->height()/2, mystd->width()-1, ACS_RTEE);
mystd->addch(mystd->height()/2, mystd->width()/2, ACS_PLUS);
// Draw frames with titles around panels so that we can see where
// the panels are located.
u->boldframe("Win U");
v->frame("Win V");
w->boldframe("Win W");
x->frame("Win X");
y->boldframe("Win Y");
z->frame("Win Z");
if (NCursesApplication::getApplication()->useColors()) {
u->bkgd(' '|COLOR_PAIR(1));
w->bkgd(' '|COLOR_PAIR(1));
y->bkgd(' '|COLOR_PAIR(1));
v->bkgd(' '|COLOR_PAIR(2));
x->bkgd(' '|COLOR_PAIR(2));
z->bkgd(' '|COLOR_PAIR(2));
}
// A refresh to any valid panel updates all panels and refreshes
// the screen. Using mystd is just convenient - We know it's always
// valid until the end of the program.
mystd->refresh();
sleep(sleeptime);
// Show what happens when panels are deleted and moved.
sleep(sleeptime);
delete u;
mystd->refresh();
sleep(sleeptime);
delete z;
mystd->refresh();
sleep(sleeptime);
delete v;
mystd->refresh();
// show how it looks when a panel moves
sleep(sleeptime);
y->mvwin(5, 30);
mystd->refresh();
sleep(sleeptime);
delete y;
mystd->refresh();
// show how it looks when you raise a panel
sleep(sleeptime);
w->top();
mystd->refresh();
sleep(sleeptime);
delete w;
mystd->refresh();
sleep(sleeptime);
delete x;
mystd->clear();
mystd->refresh();
// Don't forget to clean up the main screen. Since this is the
// last thing using NCursesWindow, this has the effect of
// shutting down ncurses and restoring the terminal state.
sleep(sleeptime);
delete mystd;
}
};
class UserData
{
private:
int u;
public:
UserData(int x) : u(x) {}
int sleeptime() const { return u; }
};
//
// -------------------------------------------------------------------------
//
template<class T> class MyAction : public NCursesUserItem<T>
{
public:
MyAction (const char* p_name,
const T* p_UserData)
: NCursesUserItem<T>(p_name, static_cast<const char*>(0), p_UserData)
{}
virtual ~MyAction() {}
bool action() {
SillyDemo a;
a.run(NCursesUserItem<T>::UserData()->sleeptime());
return FALSE;
}
};
template class MyAction<UserData>;
template class NCURSES_IMPEXP NCursesUserItem<UserData>;
class QuitItem : public NCursesMenuItem
{
public:
QuitItem() : NCursesMenuItem("Quit") {
}
bool action() {
return TRUE;
}
};
//
// -------------------------------------------------------------------------
//
class Label : public NCursesFormField
{
public:
Label(const char* title,
int row, int col)
: NCursesFormField(1, static_cast<int>(::strlen(title)), row, col) {
set_value(title);
options_off(O_EDIT|O_ACTIVE);
}
};
//
// -------------------------------------------------------------------------
//
class MyFieldType : public UserDefinedFieldType
{
private:
int chk;
protected:
bool field_check(NCursesFormField& f) {
(void) f;
return TRUE;
}
bool char_check(int c) {
return (c==chk?TRUE:FALSE);
}
public:
MyFieldType(int x) : chk(x) {
}
};
//
// -------------------------------------------------------------------------
//
class TestForm : public NCursesForm
{
private:
NCursesFormField** F;
MyFieldType* mft;
Integer_Field *ift;
Enumeration_Field *eft;
static const char *weekdays[];
public:
TestForm()
: NCursesForm(13, 51, (lines() - 15)/2, (cols() - 53)/2),
F(0),
mft(0),
ift(0),
eft(0)
{
F = new NCursesFormField*[10];
mft = new MyFieldType('X');
ift = new Integer_Field(0, 1, 10);
eft = new Enumeration_Field(weekdays);
F[0] = new Label("Demo Entry Form", 0, 16);
F[1] = new Label("Weekday Enum", 2, 1);
F[2] = new Label("Number(1-10)", 2, 21);
F[3] = new Label("Only 'X'", 2, 35);
F[4] = new Label("Multiline Field (Dynamic and Scrollable)", 5, 1);
F[5] = new NCursesFormField(1, 18, 3, 1);
F[6] = new NCursesFormField(1, 12, 3, 21);
F[7] = new NCursesFormField(1, 12, 3, 35);
F[8] = new NCursesFormField(4, 46, 6, 1, 2);
F[9] = new NCursesFormField();
InitForm(F, TRUE, TRUE);
boldframe();
F[5]->set_fieldtype(*eft);
F[6]->set_fieldtype(*ift);
F[7]->set_fieldtype(*mft);
F[7]->set_maximum_growth(20); // max. 20 characters
F[7]->options_off(O_STATIC); // make field dynamic
F[8]->set_maximum_growth(10); // max. 10 lines
F[8]->options_off(O_STATIC); // make field dynamic
}
TestForm& operator=(const TestForm& rhs)
{
if (this != &rhs) {
*this = rhs;
}
return *this;
}
TestForm(const TestForm& rhs)
: NCursesForm(rhs), F(0), mft(0), ift(0), eft(0)
{
}
~TestForm() {
delete mft;
delete ift;
delete eft;
}
};
const char* TestForm::weekdays[] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", NULL };
//
// -------------------------------------------------------------------------
//
class FormAction : public NCursesMenuItem
{
public:
FormAction(const char *s) : NCursesMenuItem(s) {
}
bool action() {
TestForm F;
Soft_Label_Key_Set* S = new Soft_Label_Key_Set;
for(int i=1; i <= S->labels(); i++) {
char buf[8];
assert(i < 100);
::_nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) "Frm%02d", i);
(*S)[i] = buf; // Text
(*S)[i] = Soft_Label_Key_Set::Soft_Label_Key::Left; // Justification
}
NCursesApplication::getApplication()->push(*S);
F();
NCursesApplication::getApplication()->pop();
delete S;
return FALSE;
}
};
//
// -------------------------------------------------------------------------
//
class PadAction : public NCursesMenuItem
{
public:
PadAction(const char* s) : NCursesMenuItem(s) {
}
bool action() {
const int GRIDSIZE = 3;
const int PADSIZE = 200;
unsigned gridcount = 0;
NCursesPanel mystd;
NCursesPanel P(mystd.lines()-2, mystd.cols()-2, 1, 1);
NCursesFramedPad FP(P, PADSIZE, PADSIZE);
for (int i=0; i < PADSIZE; i++) {
for (int j=0; j < PADSIZE; j++) {
if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0) {
if (i==0 || j==0)
FP.addch('+');
else
FP.addch(static_cast<chtype>('A' + (gridcount++ % 26)));
}
else if (i % GRIDSIZE == 0)
FP.addch('-');
else if (j % GRIDSIZE == 0)
FP.addch('|');
else
FP.addch(' ');
}
}
P.label("Pad Demo", NULL);
FP();
P.clear();
return FALSE;
}
};
//
// -------------------------------------------------------------------------
//
class PassiveItem : public NCursesMenuItem
{
public:
PassiveItem(const char* text) : NCursesMenuItem(text) {
options_off(O_SELECTABLE);
}
};
//
// -------------------------------------------------------------------------
//
class ScanAction : public NCursesMenuItem
{
public:
ScanAction(const char* s) : NCursesMenuItem(s) {
}
bool action() {
NCursesPanel *mystd = new NCursesPanel();
NCursesPanel *w = new NCursesPanel(mystd->lines() - 2, mystd->cols() - 2, 1, 1);
w->box();
w->refresh();
NCursesPanel *s = new NCursesPanel(w->lines() - 6, w->cols() - 6, 3, 3);
s->scrollok(TRUE);
::echo();
s->printw("Enter decimal integers. The running total will be shown\n");
int nvalue = -1;
int result = 0;
while (nvalue != 0) {
nvalue = 0;
s->scanw("%d", &nvalue);
if (nvalue != 0) {
s->printw("%d: ", result += nvalue);
}
s->refresh();
}
s->printw("\nPress any key to continue...");
s->getch();
delete s;
delete w;
delete mystd;
::noecho();
return FALSE;
}
};
//
// -------------------------------------------------------------------------
//
class MyMenu : public NCursesMenu
{
private:
NCursesPanel* P;
NCursesMenuItem** I;
UserData *u;
#define n_items 7
public:
MyMenu ()
: NCursesMenu (n_items+2, 8, (lines()-10)/2, (cols()-10)/2),
P(0), I(0), u(0)
{
u = new UserData(1);
I = new NCursesMenuItem*[1+n_items];
I[0] = new PassiveItem("One");
I[1] = new PassiveItem("Two");
I[2] = new MyAction<UserData> ("Silly", u);
I[3] = new FormAction("Form");
I[4] = new PadAction("Pad");
I[5] = new ScanAction("Scan");
I[6] = new QuitItem();
I[7] = new NCursesMenuItem(); // Terminating empty item
InitMenu(I, TRUE, TRUE);
P = new NCursesPanel(1, n_items, LINES-1, 1);
boldframe("Demo", "Silly");
P->show();
}
MyMenu& operator=(const MyMenu& rhs)
{
if (this != &rhs) {
*this = rhs;
}
return *this;
}
MyMenu(const MyMenu& rhs)
: NCursesMenu(rhs), P(0), I(0), u(0)
{
}
~MyMenu()
{
P->hide();
delete P;
delete u;
}
virtual void On_Menu_Init()
{
NCursesWindow W(::stdscr);
P->move(0, 0);
P->clrtoeol();
for(int i=1; i<=count(); i++)
P->addch('0' + i);
P->bkgd(W.getbkgd());
refresh();
}
virtual void On_Menu_Termination()
{
P->move(0, 0);
P->clrtoeol();
refresh();
}
virtual void On_Item_Init(NCursesMenuItem& item)
{
P->move(0, item.index());
P->attron(A_REVERSE);
P->printw("%1d", 1+item.index());
P->attroff(A_REVERSE);
refresh();
}
virtual void On_Item_Termination(NCursesMenuItem& item)
{
P->move(0, item.index());
P->attroff(A_REVERSE);
P->printw("%1d", 1+item.index());
refresh();
}
};
//
// -------------------------------------------------------------------------
//
class TestApplication : public NCursesApplication
{
protected:
int titlesize() const { return 1; }
void title();
Soft_Label_Key_Set::Label_Layout useSLKs() const {
return Soft_Label_Key_Set::PC_Style_With_Index;
}
void init_labels(Soft_Label_Key_Set& S) const;
public:
TestApplication() : NCursesApplication(TRUE) {
}
int run();
};
void TestApplication::init_labels(Soft_Label_Key_Set& S) const
{
for(int i=1; i <= S.labels(); i++) {
char buf[8];
assert(i < 100);
::_nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) "Key%02d", i);
S[i] = buf; // Text
S[i] = Soft_Label_Key_Set::Soft_Label_Key::Left; // Justification
}
}
void TestApplication::title()
{
const char * const titleText = "Simple C++ Binding Demo";
const int len = ::strlen(titleText);
titleWindow->bkgd(screen_titles());
titleWindow->addstr(0, (titleWindow->cols() - len)/2, titleText);
titleWindow->noutrefresh();
}
int TestApplication::run()
{
MyMenu M;
M();
return 0;
}
//
// -------------------------------------------------------------------------
//
static TestApplication *Demo = new TestApplication();