cursesf.h 27 KB

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