mirror of
https://github.com/Aigor44/ncursesw-morphos.git
synced 2024-12-21 07:39:06 +08:00
8b06e371ed
+ 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
571 lines
14 KiB
C++
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();
|