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