cursesf.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. // * This makes emacs happy -*-Mode: C++;-*-
  2. /****************************************************************************
  3. * Copyright 2019,2020 Thomas E. Dickey *
  4. * Copyright 1998-2012,2014 Free Software Foundation, Inc. *
  5. * *
  6. * Permission is hereby granted, free of charge, to any person obtaining a *
  7. * copy of this software and associated documentation files (the *
  8. * "Software"), to deal in the Software without restriction, including *
  9. * without limitation the rights to use, copy, modify, merge, publish, *
  10. * distribute, distribute with modifications, sublicense, and/or sell *
  11. * copies of the Software, and to permit persons to whom the Software is *
  12. * furnished to do so, subject to the following conditions: *
  13. * *
  14. * The above copyright notice and this permission notice shall be included *
  15. * in all copies or substantial portions of the Software. *
  16. * *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
  20. * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
  21. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
  22. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
  23. * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
  24. * *
  25. * Except as contained in this notice, the name(s) of the above copyright *
  26. * holders shall not be used in advertising or otherwise to promote the *
  27. * sale, use or other dealings in this Software without prior written *
  28. * authorization. *
  29. ****************************************************************************/
  30. /****************************************************************************
  31. * Author: Juergen Pfeifer, 1997 *
  32. ****************************************************************************/
  33. // $Id: cursesf.h,v 1.35 2020/02/02 23:34:34 tom Exp $
  34. #ifndef NCURSES_CURSESF_H_incl
  35. #define NCURSES_CURSESF_H_incl 1
  36. #include <cursesp.h>
  37. #ifndef __EXT_QNX
  38. #include <string.h>
  39. #endif
  40. extern "C" {
  41. # include <form.h>
  42. }
  43. //
  44. // -------------------------------------------------------------------------
  45. // The abstract base class for builtin and user defined Fieldtypes.
  46. // -------------------------------------------------------------------------
  47. //
  48. class NCURSES_IMPEXP NCursesFormField; // forward declaration
  49. // Class to represent builtin field types as well as C++ written new
  50. // fieldtypes (see classes UserDefineFieldType...
  51. class NCURSES_IMPEXP NCursesFieldType
  52. {
  53. friend class NCursesFormField;
  54. protected:
  55. FIELDTYPE* fieldtype;
  56. inline void OnError(int err) const THROW2(NCursesException const, NCursesFormException) {
  57. if (err!=E_OK)
  58. THROW(new NCursesFormException (err));
  59. }
  60. NCursesFieldType(FIELDTYPE *f) : fieldtype(f) {
  61. }
  62. virtual ~NCursesFieldType() {}
  63. // Set the fields f fieldtype to this one.
  64. virtual void set(NCursesFormField& f) = 0;
  65. public:
  66. NCursesFieldType()
  67. : fieldtype(STATIC_CAST(FIELDTYPE*)(0))
  68. {
  69. }
  70. NCursesFieldType& operator=(const NCursesFieldType& rhs)
  71. {
  72. if (this != &rhs) {
  73. *this = rhs;
  74. }
  75. return *this;
  76. }
  77. NCursesFieldType(const NCursesFieldType& rhs)
  78. : fieldtype(rhs.fieldtype)
  79. {
  80. }
  81. };
  82. //
  83. // -------------------------------------------------------------------------
  84. // The class representing a forms field, wrapping the lowlevel FIELD struct
  85. // -------------------------------------------------------------------------
  86. //
  87. class NCURSES_IMPEXP NCursesFormField
  88. {
  89. friend class NCursesForm;
  90. protected:
  91. FIELD *field; // lowlevel structure
  92. NCursesFieldType* ftype; // Associated field type
  93. // Error handler
  94. inline void OnError (int err) const THROW2(NCursesException const, NCursesFormException) {
  95. if (err != E_OK)
  96. THROW(new NCursesFormException (err));
  97. }
  98. public:
  99. // Create a 'Null' field. Can be used to delimit a field list
  100. NCursesFormField()
  101. : field(STATIC_CAST(FIELD*)(0)),
  102. ftype(STATIC_CAST(NCursesFieldType*)(0))
  103. {
  104. }
  105. // Create a new field
  106. NCursesFormField (int rows,
  107. int ncols,
  108. int first_row = 0,
  109. int first_col = 0,
  110. int offscreen_rows = 0,
  111. int additional_buffers = 0)
  112. : field(0),
  113. ftype(STATIC_CAST(NCursesFieldType*)(0))
  114. {
  115. field = ::new_field(rows, ncols, first_row, first_col,
  116. offscreen_rows, additional_buffers);
  117. if (!field)
  118. OnError(errno);
  119. }
  120. NCursesFormField& operator=(const NCursesFormField& rhs)
  121. {
  122. if (this != &rhs) {
  123. *this = rhs;
  124. }
  125. return *this;
  126. }
  127. NCursesFormField(const NCursesFormField& rhs)
  128. : field(rhs.field), ftype(rhs.ftype)
  129. {
  130. }
  131. virtual ~NCursesFormField () THROWS(NCursesException);
  132. // Duplicate the field at a new position
  133. inline NCursesFormField* dup(int first_row, int first_col)
  134. {
  135. NCursesFormField* f = new NCursesFormField();
  136. if (!f)
  137. OnError(E_SYSTEM_ERROR);
  138. else {
  139. f->ftype = ftype;
  140. f->field = ::dup_field(field,first_row,first_col);
  141. if (!f->field)
  142. OnError(errno);
  143. }
  144. return f;
  145. }
  146. // Link the field to a new location
  147. inline NCursesFormField* link(int first_row, int first_col) {
  148. NCursesFormField* f = new NCursesFormField();
  149. if (!f)
  150. OnError(E_SYSTEM_ERROR);
  151. else {
  152. f->ftype = ftype;
  153. f->field = ::link_field(field,first_row,first_col);
  154. if (!f->field)
  155. OnError(errno);
  156. }
  157. return f;
  158. }
  159. // Get the lowlevel field representation
  160. inline FIELD* get_field() const {
  161. return field;
  162. }
  163. // Retrieve info about the field
  164. inline void info(int& rows, int& ncols,
  165. int& first_row, int& first_col,
  166. int& offscreen_rows, int& additional_buffers) const {
  167. OnError(::field_info(field, &rows, &ncols,
  168. &first_row, &first_col,
  169. &offscreen_rows, &additional_buffers));
  170. }
  171. // Retrieve info about the fields dynamic properties.
  172. inline void dynamic_info(int& dynamic_rows, int& dynamic_cols,
  173. int& max_growth) const {
  174. OnError(::dynamic_field_info(field, &dynamic_rows, &dynamic_cols,
  175. &max_growth));
  176. }
  177. // For a dynamic field you may set the maximum growth limit.
  178. // A zero means unlimited growth.
  179. inline void set_maximum_growth(int growth = 0) {
  180. OnError(::set_max_field(field,growth));
  181. }
  182. // Move the field to a new position
  183. inline void move(int row, int col) {
  184. OnError(::move_field(field,row,col));
  185. }
  186. // Mark the field to start a new page
  187. inline void new_page(bool pageFlag = FALSE) {
  188. OnError(::set_new_page(field,pageFlag));
  189. }
  190. // Retrieve whether or not the field starts a new page.
  191. inline bool is_new_page() const {
  192. return ::new_page(field);
  193. }
  194. // Set the justification for the field
  195. inline void set_justification(int just) {
  196. OnError(::set_field_just(field,just));
  197. }
  198. // Retrieve the fields justification
  199. inline int justification() const {
  200. return ::field_just(field);
  201. }
  202. // Set the foreground attribute for the field
  203. inline void set_foreground(chtype foreground) {
  204. OnError(::set_field_fore(field,foreground));
  205. }
  206. // Retrieve the fields foreground attribute
  207. inline chtype fore() const {
  208. return ::field_fore(field);
  209. }
  210. // Set the background attribute for the field
  211. inline void set_background(chtype background) {
  212. OnError(::set_field_back(field,background));
  213. }
  214. // Retrieve the fields background attribute
  215. inline chtype back() const {
  216. return ::field_back(field);
  217. }
  218. // Set the padding character for the field
  219. inline void set_pad_character(int padding) {
  220. OnError(::set_field_pad(field, padding));
  221. }
  222. // Retrieve the fields padding character
  223. inline int pad() const {
  224. return ::field_pad(field);
  225. }
  226. // Switch on the fields options
  227. inline void options_on (Field_Options opts) {
  228. OnError (::field_opts_on (field, opts));
  229. }
  230. // Switch off the fields options
  231. inline void options_off (Field_Options opts) {
  232. OnError (::field_opts_off (field, opts));
  233. }
  234. // Retrieve the fields options
  235. inline Field_Options options () const {
  236. return ::field_opts (field);
  237. }
  238. // Set the fields options
  239. inline void set_options (Field_Options opts) {
  240. OnError (::set_field_opts (field, opts));
  241. }
  242. // Mark the field as changed
  243. inline void set_changed(bool changeFlag = TRUE) {
  244. OnError(::set_field_status(field,changeFlag));
  245. }
  246. // Test whether or not the field is marked as changed
  247. inline bool changed() const {
  248. return ::field_status(field);
  249. }
  250. // Return the index of the field in the field array of a form
  251. // or -1 if the field is not associated to a form
  252. inline int (index)() const {
  253. return ::field_index(field);
  254. }
  255. // Store a value in a fields buffer. The default buffer is nr. 0
  256. inline void set_value(const char *val, int buffer = 0) {
  257. OnError(::set_field_buffer(field,buffer,val));
  258. }
  259. // Retrieve the value of a fields buffer. The default buffer is nr. 0
  260. inline char* value(int buffer = 0) const {
  261. return ::field_buffer(field,buffer);
  262. }
  263. // Set the validation type of the field.
  264. inline void set_fieldtype(NCursesFieldType& f) {
  265. ftype = &f;
  266. f.set(*this); // A good friend may do that...
  267. }
  268. // Retrieve the validation type of the field.
  269. inline NCursesFieldType* fieldtype() const {
  270. return ftype;
  271. }
  272. };
  273. // This are the built-in hook functions in this C++ binding. In C++ we use
  274. // virtual member functions (see below On_..._Init and On_..._Termination)
  275. // to provide this functionality in an object oriented manner.
  276. extern "C" {
  277. void _nc_xx_frm_init(FORM *);
  278. void _nc_xx_frm_term(FORM *);
  279. void _nc_xx_fld_init(FORM *);
  280. void _nc_xx_fld_term(FORM *);
  281. }
  282. //
  283. // -------------------------------------------------------------------------
  284. // The class representing a form, wrapping the lowlevel FORM struct
  285. // -------------------------------------------------------------------------
  286. //
  287. class NCURSES_IMPEXP NCursesForm : public NCursesPanel
  288. {
  289. protected:
  290. FORM* form; // the lowlevel structure
  291. private:
  292. NCursesWindow* sub; // the subwindow object
  293. bool b_sub_owner; // is this our own subwindow?
  294. bool b_framed; // has the form a border?
  295. bool b_autoDelete; // Delete fields when deleting form?
  296. NCursesFormField** my_fields; // The array of fields for this form
  297. // This structure is used for the form's user data field to link the
  298. // FORM* to the C++ object and to provide extra space for a user pointer.
  299. typedef struct {
  300. void* m_user; // the pointer for the user's data
  301. const NCursesForm* m_back; // backward pointer to C++ object
  302. const FORM* m_owner;
  303. } UserHook;
  304. // Get the backward pointer to the C++ object from a FORM
  305. static inline NCursesForm* getHook(const FORM *f) {
  306. UserHook* hook = reinterpret_cast<UserHook*>(::form_userptr(f));
  307. assert(hook != 0 && hook->m_owner==f);
  308. return const_cast<NCursesForm*>(hook->m_back);
  309. }
  310. friend void _nc_xx_frm_init(FORM *);
  311. friend void _nc_xx_frm_term(FORM *);
  312. friend void _nc_xx_fld_init(FORM *);
  313. friend void _nc_xx_fld_term(FORM *);
  314. // Calculate FIELD* array for the menu
  315. FIELD** mapFields(NCursesFormField* nfields[]);
  316. protected:
  317. // internal routines
  318. inline void set_user(void *user) {
  319. UserHook* uptr = reinterpret_cast<UserHook*>(::form_userptr (form));
  320. assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form);
  321. uptr->m_user = user;
  322. }
  323. inline void *get_user() {
  324. UserHook* uptr = reinterpret_cast<UserHook*>(::form_userptr (form));
  325. assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form);
  326. return uptr->m_user;
  327. }
  328. void InitForm (NCursesFormField* Fields[],
  329. bool with_frame,
  330. bool autoDeleteFields);
  331. inline void OnError (int err) const THROW2(NCursesException const, NCursesFormException) {
  332. if (err != E_OK)
  333. THROW(new NCursesFormException (err));
  334. }
  335. // this wraps the form_driver call.
  336. virtual int driver (int c) ;
  337. // 'Internal' constructor, builds an object without association to a
  338. // field array.
  339. NCursesForm( int nlines,
  340. int ncols,
  341. int begin_y = 0,
  342. int begin_x = 0)
  343. : NCursesPanel(nlines, ncols, begin_y, begin_x),
  344. form (STATIC_CAST(FORM*)(0)),
  345. sub(0),
  346. b_sub_owner(0),
  347. b_framed(0),
  348. b_autoDelete(0),
  349. my_fields(0)
  350. {
  351. }
  352. public:
  353. // Create form for the default panel.
  354. NCursesForm (NCursesFormField* Fields[],
  355. bool with_frame=FALSE, // reserve space for a frame?
  356. bool autoDelete_Fields=FALSE) // do automatic cleanup?
  357. : NCursesPanel(),
  358. form(0),
  359. sub(0),
  360. b_sub_owner(0),
  361. b_framed(0),
  362. b_autoDelete(0),
  363. my_fields(0)
  364. {
  365. InitForm(Fields, with_frame, autoDelete_Fields);
  366. }
  367. // Create a form in a panel with the given position and size.
  368. NCursesForm (NCursesFormField* Fields[],
  369. int nlines,
  370. int ncols,
  371. int begin_y,
  372. int begin_x,
  373. bool with_frame=FALSE, // reserve space for a frame?
  374. bool autoDelete_Fields=FALSE) // do automatic cleanup?
  375. : NCursesPanel(nlines, ncols, begin_y, begin_x),
  376. form(0),
  377. sub(0),
  378. b_sub_owner(0),
  379. b_framed(0),
  380. b_autoDelete(0),
  381. my_fields(0)
  382. {
  383. InitForm(Fields, with_frame, autoDelete_Fields);
  384. }
  385. NCursesForm& operator=(const NCursesForm& rhs)
  386. {
  387. if (this != &rhs) {
  388. *this = rhs;
  389. NCursesPanel::operator=(rhs);
  390. }
  391. return *this;
  392. }
  393. NCursesForm(const NCursesForm& rhs)
  394. : NCursesPanel(rhs),
  395. form(rhs.form),
  396. sub(rhs.sub),
  397. b_sub_owner(rhs.b_sub_owner),
  398. b_framed(rhs.b_framed),
  399. b_autoDelete(rhs.b_autoDelete),
  400. my_fields(rhs.my_fields)
  401. {
  402. }
  403. virtual ~NCursesForm() THROWS(NCursesException);
  404. // Set the default attributes for the form
  405. virtual void setDefaultAttributes();
  406. // Retrieve current field of the form.
  407. inline NCursesFormField* current_field() const {
  408. return my_fields[::field_index(::current_field(form))];
  409. }
  410. // Set the forms subwindow
  411. void setSubWindow(NCursesWindow& sub);
  412. // Set these fields for the form
  413. inline void setFields(NCursesFormField* Fields[]) {
  414. OnError(::set_form_fields(form,mapFields(Fields)));
  415. }
  416. // Remove the form from the screen
  417. inline void unpost (void) {
  418. OnError (::unpost_form (form));
  419. }
  420. // Post the form to the screen if flag is true, unpost it otherwise
  421. inline void post(bool flag = TRUE) {
  422. OnError (flag ? ::post_form(form) : ::unpost_form (form));
  423. }
  424. // Decorations
  425. inline void frame(const char *title=NULL, const char* btitle=NULL) {
  426. if (b_framed)
  427. NCursesPanel::frame(title,btitle);
  428. else
  429. OnError(E_SYSTEM_ERROR);
  430. }
  431. inline void boldframe(const char *title=NULL, const char* btitle=NULL) {
  432. if (b_framed)
  433. NCursesPanel::boldframe(title,btitle);
  434. else
  435. OnError(E_SYSTEM_ERROR);
  436. }
  437. inline void label(const char *topLabel, const char *bottomLabel) {
  438. if (b_framed)
  439. NCursesPanel::label(topLabel,bottomLabel);
  440. else
  441. OnError(E_SYSTEM_ERROR);
  442. }
  443. // -----
  444. // Hooks
  445. // -----
  446. // Called after the form gets repositioned in its window.
  447. // This is especially true if the form is posted.
  448. virtual void On_Form_Init();
  449. // Called before the form gets repositioned in its window.
  450. // This is especially true if the form is unposted.
  451. virtual void On_Form_Termination();
  452. // Called after the field became the current field
  453. virtual void On_Field_Init(NCursesFormField& field);
  454. // Called before this field is left as current field.
  455. virtual void On_Field_Termination(NCursesFormField& field);
  456. // Calculate required window size for the form.
  457. void scale(int& rows, int& ncols) const {
  458. OnError(::scale_form(form,&rows,&ncols));
  459. }
  460. // Retrieve number of fields in the form.
  461. int count() const {
  462. return ::field_count(form);
  463. }
  464. // Make the page the current page of the form.
  465. void set_page(int pageNum) {
  466. OnError(::set_form_page(form, pageNum));
  467. }
  468. // Retrieve current page number
  469. int page() const {
  470. return ::form_page(form);
  471. }
  472. // Switch on the forms options
  473. inline void options_on (Form_Options opts) {
  474. OnError (::form_opts_on (form, opts));
  475. }
  476. // Switch off the forms options
  477. inline void options_off (Form_Options opts) {
  478. OnError (::form_opts_off (form, opts));
  479. }
  480. // Retrieve the forms options
  481. inline Form_Options options () const {
  482. return ::form_opts (form);
  483. }
  484. // Set the forms options
  485. inline void set_options (Form_Options opts) {
  486. OnError (::set_form_opts (form, opts));
  487. }
  488. // Are there more data in the current field after the data shown
  489. inline bool data_ahead() const {
  490. return ::data_ahead(form);
  491. }
  492. // Are there more data in the current field before the data shown
  493. inline bool data_behind() const {
  494. return ::data_behind(form);
  495. }
  496. // Position the cursor to the current field
  497. inline void position_cursor () {
  498. OnError (::pos_form_cursor (form));
  499. }
  500. // Set the current field
  501. inline void set_current(NCursesFormField& F) {
  502. OnError (::set_current_field(form, F.field));
  503. }
  504. // Provide a default key virtualization. Translate the keyboard
  505. // code c into a form request code.
  506. // The default implementation provides a hopefully straightforward
  507. // mapping for the most common keystrokes and form requests.
  508. virtual int virtualize(int c);
  509. // Operators
  510. inline NCursesFormField* operator[](int i) const {
  511. if ( (i < 0) || (i >= ::field_count (form)) )
  512. OnError (E_BAD_ARGUMENT);
  513. return my_fields[i];
  514. }
  515. // Perform the menu's operation
  516. // Return the field where you left the form.
  517. virtual NCursesFormField* operator()(void);
  518. // Exception handlers. The default is a Beep.
  519. virtual void On_Request_Denied(int c) const;
  520. virtual void On_Invalid_Field(int c) const;
  521. virtual void On_Unknown_Command(int c) const;
  522. };
  523. //
  524. // -------------------------------------------------------------------------
  525. // This is the typical C++ typesafe way to allow to attach
  526. // user data to a field of a form. Its assumed that the user
  527. // data belongs to some class T. Use T as template argument
  528. // to create a UserField.
  529. // -------------------------------------------------------------------------
  530. template<class T> class NCURSES_IMPEXP NCursesUserField : public NCursesFormField
  531. {
  532. public:
  533. NCursesUserField (int rows,
  534. int ncols,
  535. int first_row = 0,
  536. int first_col = 0,
  537. const T* p_UserData = STATIC_CAST(T*)(0),
  538. int offscreen_rows = 0,
  539. int additional_buffers = 0)
  540. : NCursesFormField (rows, ncols,
  541. first_row, first_col,
  542. offscreen_rows, additional_buffers) {
  543. if (field)
  544. OnError(::set_field_userptr(field, STATIC_CAST(void *)(p_UserData)));
  545. }
  546. virtual ~NCursesUserField() THROWS(NCursesException) {};
  547. inline const T* UserData (void) const {
  548. return reinterpret_cast<const T*>(::field_userptr (field));
  549. }
  550. inline virtual void setUserData(const T* p_UserData) {
  551. if (field)
  552. OnError (::set_field_userptr (field, STATIC_CAST(void *)(p_UserData)));
  553. }
  554. };
  555. //
  556. // -------------------------------------------------------------------------
  557. // The same mechanism is used to attach user data to a form
  558. // -------------------------------------------------------------------------
  559. //
  560. template<class T> class NCURSES_IMPEXP NCursesUserForm : public NCursesForm
  561. {
  562. protected:
  563. // 'Internal' constructor, builds an object without association to a
  564. // field array.
  565. NCursesUserForm( int nlines,
  566. int ncols,
  567. int begin_y = 0,
  568. int begin_x = 0,
  569. const T* p_UserData = STATIC_CAST(T*)(0))
  570. : NCursesForm(nlines,ncols,begin_y,begin_x) {
  571. if (form)
  572. set_user (const_cast<void *>(reinterpret_cast<const void*>
  573. (p_UserData)));
  574. }
  575. public:
  576. NCursesUserForm (NCursesFormField* Fields[],
  577. const T* p_UserData = STATIC_CAST(T*)(0),
  578. bool with_frame=FALSE,
  579. bool autoDelete_Fields=FALSE)
  580. : NCursesForm (Fields, with_frame, autoDelete_Fields) {
  581. if (form)
  582. set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
  583. };
  584. NCursesUserForm (NCursesFormField* Fields[],
  585. int nlines,
  586. int ncols,
  587. int begin_y = 0,
  588. int begin_x = 0,
  589. const T* p_UserData = STATIC_CAST(T*)(0),
  590. bool with_frame=FALSE,
  591. bool autoDelete_Fields=FALSE)
  592. : NCursesForm (Fields, nlines, ncols, begin_y, begin_x,
  593. with_frame, autoDelete_Fields) {
  594. if (form)
  595. set_user (const_cast<void *>(reinterpret_cast<const void*>
  596. (p_UserData)));
  597. };
  598. virtual ~NCursesUserForm() THROWS(NCursesException) {
  599. };
  600. inline T* UserData (void) {
  601. return reinterpret_cast<T*>(get_user ());
  602. };
  603. inline virtual void setUserData (const T* p_UserData) {
  604. if (form)
  605. set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
  606. }
  607. };
  608. //
  609. // -------------------------------------------------------------------------
  610. // Builtin Fieldtypes
  611. // -------------------------------------------------------------------------
  612. //
  613. class NCURSES_IMPEXP Alpha_Field : public NCursesFieldType
  614. {
  615. private:
  616. int min_field_width;
  617. void set(NCursesFormField& f) {
  618. OnError(::set_field_type(f.get_field(),fieldtype,min_field_width));
  619. }
  620. public:
  621. Alpha_Field(int width)
  622. : NCursesFieldType(TYPE_ALPHA),
  623. min_field_width(width) {
  624. }
  625. };
  626. class NCURSES_IMPEXP Alphanumeric_Field : public NCursesFieldType
  627. {
  628. private:
  629. int min_field_width;
  630. void set(NCursesFormField& f) {
  631. OnError(::set_field_type(f.get_field(),fieldtype,min_field_width));
  632. }
  633. public:
  634. Alphanumeric_Field(int width)
  635. : NCursesFieldType(TYPE_ALNUM),
  636. min_field_width(width) {
  637. }
  638. };
  639. class NCURSES_IMPEXP Integer_Field : public NCursesFieldType
  640. {
  641. private:
  642. int precision;
  643. long lower_limit, upper_limit;
  644. void set(NCursesFormField& f) {
  645. OnError(::set_field_type(f.get_field(),fieldtype,
  646. precision,lower_limit,upper_limit));
  647. }
  648. public:
  649. Integer_Field(int prec, long low=0L, long high=0L)
  650. : NCursesFieldType(TYPE_INTEGER),
  651. precision(prec), lower_limit(low), upper_limit(high) {
  652. }
  653. };
  654. class NCURSES_IMPEXP Numeric_Field : public NCursesFieldType
  655. {
  656. private:
  657. int precision;
  658. double lower_limit, upper_limit;
  659. void set(NCursesFormField& f) {
  660. OnError(::set_field_type(f.get_field(),fieldtype,
  661. precision,lower_limit,upper_limit));
  662. }
  663. public:
  664. Numeric_Field(int prec, double low=0.0, double high=0.0)
  665. : NCursesFieldType(TYPE_NUMERIC),
  666. precision(prec), lower_limit(low), upper_limit(high) {
  667. }
  668. };
  669. class NCURSES_IMPEXP Regular_Expression_Field : public NCursesFieldType
  670. {
  671. private:
  672. char* regex;
  673. void set(NCursesFormField& f) {
  674. OnError(::set_field_type(f.get_field(),fieldtype,regex));
  675. }
  676. void copy_regex(const char *source)
  677. {
  678. regex = new char[1 + ::strlen(source)];
  679. (::strcpy)(regex, source);
  680. }
  681. public:
  682. Regular_Expression_Field(const char *expr)
  683. : NCursesFieldType(TYPE_REGEXP),
  684. regex(NULL)
  685. {
  686. copy_regex(expr);
  687. }
  688. Regular_Expression_Field& operator=(const Regular_Expression_Field& rhs)
  689. {
  690. if (this != &rhs) {
  691. *this = rhs;
  692. copy_regex(rhs.regex);
  693. NCursesFieldType::operator=(rhs);
  694. }
  695. return *this;
  696. }
  697. Regular_Expression_Field(const Regular_Expression_Field& rhs)
  698. : NCursesFieldType(rhs),
  699. regex(NULL)
  700. {
  701. copy_regex(rhs.regex);
  702. }
  703. ~Regular_Expression_Field() {
  704. delete[] regex;
  705. }
  706. };
  707. class NCURSES_IMPEXP Enumeration_Field : public NCursesFieldType
  708. {
  709. private:
  710. const char** list;
  711. int case_sensitive;
  712. int non_unique_matches;
  713. void set(NCursesFormField& f) {
  714. OnError(::set_field_type(f.get_field(),fieldtype,
  715. list,case_sensitive,non_unique_matches));
  716. }
  717. public:
  718. Enumeration_Field(const char* enums[],
  719. bool case_sens=FALSE,
  720. bool non_unique=FALSE)
  721. : NCursesFieldType(TYPE_ENUM),
  722. list(enums),
  723. case_sensitive(case_sens ? -1 : 0),
  724. non_unique_matches(non_unique ? -1 : 0) {
  725. }
  726. Enumeration_Field& operator=(const Enumeration_Field& rhs)
  727. {
  728. if (this != &rhs) {
  729. *this = rhs;
  730. NCursesFieldType::operator=(rhs);
  731. }
  732. return *this;
  733. }
  734. Enumeration_Field(const Enumeration_Field& rhs)
  735. : NCursesFieldType(rhs),
  736. list(rhs.list),
  737. case_sensitive(rhs.case_sensitive),
  738. non_unique_matches(rhs.non_unique_matches)
  739. {
  740. }
  741. };
  742. class NCURSES_IMPEXP IPV4_Address_Field : public NCursesFieldType
  743. {
  744. private:
  745. void set(NCursesFormField& f) {
  746. OnError(::set_field_type(f.get_field(),fieldtype));
  747. }
  748. public:
  749. IPV4_Address_Field() : NCursesFieldType(TYPE_IPV4) {
  750. }
  751. };
  752. extern "C" {
  753. bool _nc_xx_fld_fcheck(FIELD *, const void*);
  754. bool _nc_xx_fld_ccheck(int c, const void *);
  755. void* _nc_xx_fld_makearg(va_list*);
  756. }
  757. //
  758. // -------------------------------------------------------------------------
  759. // Abstract base class for User-Defined Fieldtypes
  760. // -------------------------------------------------------------------------
  761. //
  762. class NCURSES_IMPEXP UserDefinedFieldType : public NCursesFieldType
  763. {
  764. friend class UDF_Init; // Internal helper to set up statics
  765. private:
  766. // For all C++ defined fieldtypes we need only one generic lowlevel
  767. // FIELDTYPE* element.
  768. static FIELDTYPE* generic_fieldtype;
  769. protected:
  770. // This are the functions required by the low level libforms functions
  771. // to construct a fieldtype.
  772. friend bool _nc_xx_fld_fcheck(FIELD *, const void*);
  773. friend bool _nc_xx_fld_ccheck(int c, const void *);
  774. friend void* _nc_xx_fld_makearg(va_list*);
  775. void set(NCursesFormField& f) {
  776. OnError(::set_field_type(f.get_field(),fieldtype,&f));
  777. }
  778. protected:
  779. // Redefine this function to do a field validation. The argument
  780. // is a reference to the field you should validate.
  781. virtual bool field_check(NCursesFormField& f) = 0;
  782. // Redefine this function to do a character validation. The argument
  783. // is the character to be validated.
  784. virtual bool char_check (int c) = 0;
  785. public:
  786. UserDefinedFieldType() : NCursesFieldType(generic_fieldtype) {
  787. }
  788. };
  789. extern "C" {
  790. bool _nc_xx_next_choice(FIELD*, const void *);
  791. bool _nc_xx_prev_choice(FIELD*, const void *);
  792. }
  793. //
  794. // -------------------------------------------------------------------------
  795. // Abstract base class for User-Defined Fieldtypes with Choice functions
  796. // -------------------------------------------------------------------------
  797. //
  798. class NCURSES_IMPEXP UserDefinedFieldType_With_Choice : public UserDefinedFieldType
  799. {
  800. friend class UDF_Init; // Internal helper to set up statics
  801. private:
  802. // For all C++ defined fieldtypes with choice functions we need only one
  803. // generic lowlevel FIELDTYPE* element.
  804. static FIELDTYPE* generic_fieldtype_with_choice;
  805. // This are the functions required by the low level libforms functions
  806. // to construct a fieldtype with choice functions.
  807. friend bool _nc_xx_next_choice(FIELD*, const void *);
  808. friend bool _nc_xx_prev_choice(FIELD*, const void *);
  809. protected:
  810. // Redefine this function to do the retrieval of the next choice value.
  811. // The argument is a reference to the field tobe examined.
  812. virtual bool next (NCursesFormField& f) = 0;
  813. // Redefine this function to do the retrieval of the previous choice value.
  814. // The argument is a reference to the field tobe examined.
  815. virtual bool previous(NCursesFormField& f) = 0;
  816. public:
  817. UserDefinedFieldType_With_Choice() {
  818. fieldtype = generic_fieldtype_with_choice;
  819. }
  820. };
  821. #endif /* NCURSES_CURSESF_H_incl */