Nuke INTR_NETSAFE
[dragonfly/netmp.git] / contrib / ncurses-5.4 / c++ / cursesf.cc
blobb6a0a59369896722377639b0095f4c55bd7554f3
1 // * this is for making emacs happy: -*-Mode: C++;-*-
2 /****************************************************************************
3 * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc. *
4 * *
5 * Permission is hereby granted, free of charge, to any person obtaining a *
6 * copy of this software and associated documentation files (the *
7 * "Software"), to deal in the Software without restriction, including *
8 * without limitation the rights to use, copy, modify, merge, publish, *
9 * distribute, distribute with modifications, sublicense, and/or sell *
10 * copies of the Software, and to permit persons to whom the Software is *
11 * furnished to do so, subject to the following conditions: *
12 * *
13 * The above copyright notice and this permission notice shall be included *
14 * in all copies or substantial portions of the Software. *
15 * *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * *
24 * Except as contained in this notice, the name(s) of the above copyright *
25 * holders shall not be used in advertising or otherwise to promote the *
26 * sale, use or other dealings in this Software without prior written *
27 * authorization. *
28 ****************************************************************************/
30 /****************************************************************************
31 * Author: Juergen Pfeifer, 1997 *
32 ****************************************************************************/
34 #include "internal.h"
35 #include "cursesf.h"
36 #include "cursesapp.h"
38 MODULE_ID("$Id: cursesf.cc,v 1.16 2003/10/25 15:04:46 tom Exp $")
40 NCursesFormField::~NCursesFormField () {
41 if (field)
42 OnError(::free_field (field));
45 /* Construct a FIELD* array from an array of NCursesFormField
46 * objects.
48 FIELD**
49 NCursesForm::mapFields(NCursesFormField* nfields[]) {
50 int fieldCount = 0,lcv;
51 FIELD** old_fields;
53 assert(nfields != 0);
55 for (lcv=0; nfields[lcv]->field; ++lcv)
56 ++fieldCount;
58 FIELD** fields = new FIELD*[fieldCount + 1];
60 for (lcv=0;nfields[lcv]->field;++lcv) {
61 fields[lcv] = nfields[lcv]->field;
63 fields[lcv] = NULL;
65 my_fields = nfields;
67 if (form && (old_fields = ::form_fields(form))) {
68 ::set_form_fields(form,(FIELD**)0);
69 delete[] old_fields;
71 return fields;
74 void NCursesForm::setDefaultAttributes() {
75 NCursesApplication* S = NCursesApplication::getApplication();
77 int n = count();
78 if (n > 0) {
79 for(int i=0; i<n; i++) {
80 NCursesFormField* f = (*this)[i];
81 if ((f->options() & (O_EDIT|O_ACTIVE))==(O_EDIT|O_ACTIVE)) {
82 if (S) {
83 f->set_foreground(S->foregrounds());
84 f->set_background(S->backgrounds());
86 f->set_pad_character('_');
88 else {
89 if (S)
90 f->set_background(S->labels());
95 if (S) {
96 bkgd(' '|S->dialog_backgrounds());
97 if (sub)
98 sub->bkgd(' '|S->dialog_backgrounds());
102 void
103 NCursesForm::InitForm(NCursesFormField* nfields[],
104 bool with_frame,
105 bool autoDelete_Fields) {
106 int mrows, mcols;
108 keypad(TRUE);
109 meta(TRUE);
111 b_framed = with_frame;
112 b_autoDelete = autoDelete_Fields;
114 form = (FORM*)0;
115 form = ::new_form(mapFields(nfields));
116 if (!form)
117 OnError (E_SYSTEM_ERROR);
119 UserHook* hook = new UserHook;
120 hook->m_user = NULL;
121 hook->m_back = this;
122 hook->m_owner = form;
123 ::set_form_userptr(form,(void*)hook);
125 ::set_form_init (form, NCursesForm::frm_init);
126 ::set_form_term (form, NCursesForm::frm_term);
127 ::set_field_init (form, NCursesForm::fld_init);
128 ::set_field_term (form, NCursesForm::fld_term);
130 scale(mrows, mcols);
131 ::set_form_win(form, w);
133 if (with_frame) {
134 if ((mrows > height()-2) || (mcols > width()-2))
135 OnError(E_NO_ROOM);
136 sub = new NCursesWindow(*this,mrows,mcols,1,1,'r');
137 ::set_form_sub(form, sub->w);
138 b_sub_owner = TRUE;
140 else {
141 sub = (NCursesWindow*)0;
142 b_sub_owner = FALSE;
144 options_on(O_NL_OVERLOAD);
145 setDefaultAttributes();
148 NCursesForm::~NCursesForm() {
149 UserHook* hook = (UserHook*)::form_userptr(form);
150 delete hook;
151 if (b_sub_owner) {
152 delete sub;
153 ::set_form_sub(form,(WINDOW *)0);
155 if (form) {
156 FIELD** fields = ::form_fields(form);
157 int cnt = count();
159 OnError(::set_form_fields(form,(FIELD**)0));
161 if (b_autoDelete) {
162 if (cnt>0) {
163 for (int i=0; i <= cnt; i++)
164 delete my_fields[i];
166 delete[] my_fields;
169 ::free_form(form);
170 // It's essential to do this after free_form()
171 delete[] fields;
175 void
176 NCursesForm::setSubWindow(NCursesWindow& nsub) {
177 if (!isDescendant(nsub))
178 OnError(E_SYSTEM_ERROR);
179 else {
180 if (b_sub_owner)
181 delete sub;
182 sub = &nsub;
183 ::set_form_sub(form,sub->w);
187 /* Internal hook functions. They will route the hook
188 * calls to virtual methods of the NCursesForm class,
189 * so in C++ providing a hook is done simply by
190 * implementing a virtual method in a derived class
192 void
193 NCursesForm::frm_init(FORM *f) {
194 getHook(f)->On_Form_Init();
197 void
198 NCursesForm::frm_term(FORM *f) {
199 getHook(f)->On_Form_Termination();
202 void
203 NCursesForm::fld_init(FORM *f) {
204 NCursesForm* F = getHook(f);
205 F->On_Field_Init (*(F->current_field ()));
208 void
209 NCursesForm::fld_term(FORM *f) {
210 NCursesForm* F = getHook(f);
211 F->On_Field_Termination (*(F->current_field ()));
214 void
215 NCursesForm::On_Form_Init() {
218 void
219 NCursesForm::On_Form_Termination() {
222 void
223 NCursesForm::On_Field_Init(NCursesFormField& field) {
226 void
227 NCursesForm::On_Field_Termination(NCursesFormField& field) {
230 // call the form driver and do basic error checking.
232 NCursesForm::driver (int c) {
233 int res = ::form_driver (form, c);
234 switch (res) {
235 case E_OK:
236 case E_REQUEST_DENIED:
237 case E_INVALID_FIELD:
238 case E_UNKNOWN_COMMAND:
239 break;
240 default:
241 OnError (res);
243 return (res);
246 void NCursesForm::On_Request_Denied(int c) const {
247 ::beep();
250 void NCursesForm::On_Invalid_Field(int c) const {
251 ::beep();
254 void NCursesForm::On_Unknown_Command(int c) const {
255 ::beep();
258 static const int CMD_QUIT = MAX_COMMAND + 1;
260 NCursesFormField*
261 NCursesForm::operator()(void) {
262 int drvCmnd;
263 int err;
264 int c;
266 post();
267 show();
268 refresh();
270 while (((drvCmnd = virtualize((c=getKey()))) != CMD_QUIT)) {
271 switch((err=driver(drvCmnd))) {
272 case E_REQUEST_DENIED:
273 On_Request_Denied(c);
274 break;
275 case E_INVALID_FIELD:
276 On_Invalid_Field(c);
277 break;
278 case E_UNKNOWN_COMMAND:
279 On_Unknown_Command(c);
280 break;
281 case E_OK:
282 break;
283 default:
284 OnError(err);
288 unpost();
289 hide();
290 refresh();
291 return my_fields[::field_index (::current_field (form))];
294 // Provide a default key virtualization. Translate the keyboard
295 // code c into a form request code.
296 // The default implementation provides a hopefully straightforward
297 // mapping for the most common keystrokes and form requests.
299 NCursesForm::virtualize(int c) {
300 switch(c) {
302 case KEY_HOME : return(REQ_FIRST_FIELD);
303 case KEY_END : return(REQ_LAST_FIELD);
305 case KEY_DOWN : return(REQ_DOWN_CHAR);
306 case KEY_UP : return(REQ_UP_CHAR);
307 case KEY_LEFT : return(REQ_PREV_CHAR);
308 case KEY_RIGHT : return(REQ_NEXT_CHAR);
310 case KEY_NPAGE : return(REQ_NEXT_PAGE);
311 case KEY_PPAGE : return(REQ_PREV_PAGE);
313 case KEY_BACKSPACE : return(REQ_DEL_PREV);
314 case KEY_ENTER : return(REQ_NEW_LINE);
315 case KEY_CLEAR : return(REQ_CLR_FIELD);
317 case CTRL('X') : return(CMD_QUIT); // eXit
319 case CTRL('F') : return(REQ_NEXT_FIELD); // Forward
320 case CTRL('B') : return(REQ_PREV_FIELD); // Backward
321 case CTRL('L') : return(REQ_LEFT_FIELD); // Left
322 case CTRL('R') : return(REQ_RIGHT_FIELD); // Right
323 case CTRL('U') : return(REQ_UP_FIELD); // Up
324 case CTRL('D') : return(REQ_DOWN_FIELD); // Down
326 case CTRL('W') : return(REQ_NEXT_WORD);
327 case CTRL('T') : return(REQ_PREV_WORD);
329 case CTRL('A') : return(REQ_BEG_FIELD);
330 case CTRL('E') : return(REQ_END_FIELD);
332 case CTRL('I') : return(REQ_INS_CHAR);
333 case CTRL('M') :
334 case CTRL('J') : return(REQ_NEW_LINE);
335 case CTRL('O') : return(REQ_INS_LINE);
336 case CTRL('V') : return(REQ_DEL_CHAR);
337 case CTRL('H') : return(REQ_DEL_PREV);
338 case CTRL('Y') : return(REQ_DEL_LINE);
339 case CTRL('G') : return(REQ_DEL_WORD);
340 case CTRL('K') : return(REQ_CLR_EOF);
342 case CTRL('N') : return(REQ_NEXT_CHOICE);
343 case CTRL('P') : return(REQ_PREV_CHOICE);
345 default:
346 return(c);
350 // -------------------------------------------------------------------------
351 // User Defined Fieldtypes
352 // -------------------------------------------------------------------------
354 bool UserDefinedFieldType::fcheck(FIELD *f, const void *u) {
355 NCursesFormField* F = (NCursesFormField*)u;
356 assert(F != 0);
357 UserDefinedFieldType* udf = (UserDefinedFieldType*)(F->fieldtype());
358 assert(udf != 0);
359 return udf->field_check(*F);
362 bool UserDefinedFieldType::ccheck(int c, const void *u) {
363 NCursesFormField* F = (NCursesFormField*)u;
364 assert(F != 0);
365 UserDefinedFieldType* udf =
366 (UserDefinedFieldType*)(F->fieldtype());
367 assert(udf != 0);
368 return udf->char_check(c);
371 void* UserDefinedFieldType::makearg(va_list* va) {
372 return va_arg(*va,NCursesFormField*);
375 FIELDTYPE* UserDefinedFieldType::generic_fieldtype =
376 ::new_fieldtype(UserDefinedFieldType::fcheck,
377 UserDefinedFieldType::ccheck);
379 FIELDTYPE* UserDefinedFieldType_With_Choice::generic_fieldtype_with_choice =
380 ::new_fieldtype(UserDefinedFieldType::fcheck,
381 UserDefinedFieldType::ccheck);
383 bool UserDefinedFieldType_With_Choice::next_choice(FIELD *f, const void *u) {
384 NCursesFormField* F = (NCursesFormField*)u;
385 assert(F != 0);
386 UserDefinedFieldType_With_Choice* udf =
387 (UserDefinedFieldType_With_Choice*)(F->fieldtype());
388 assert(udf != 0);
389 return udf->next(*F);
392 bool UserDefinedFieldType_With_Choice::prev_choice(FIELD *f, const void *u) {
393 NCursesFormField* F = (NCursesFormField*)u;
394 assert(F != 0);
395 UserDefinedFieldType_With_Choice* udf =
396 (UserDefinedFieldType_With_Choice*)(F->fieldtype());
397 assert(udf != 0);
398 return udf->previous(*F);
401 class UDF_Init {
402 private:
403 int code;
404 static UDF_Init* I;
405 public:
406 UDF_Init() {
407 code = ::set_fieldtype_arg(UserDefinedFieldType::generic_fieldtype,
408 UserDefinedFieldType::makearg,
409 NULL,
410 NULL);
411 if (code==E_OK)
412 code = ::set_fieldtype_arg
413 (UserDefinedFieldType_With_Choice::generic_fieldtype_with_choice,
414 UserDefinedFieldType::makearg,
415 NULL,
416 NULL);
417 if (code==E_OK)
418 code = ::set_fieldtype_choice
419 (UserDefinedFieldType_With_Choice::generic_fieldtype_with_choice,
420 UserDefinedFieldType_With_Choice::next_choice,
421 UserDefinedFieldType_With_Choice::prev_choice);
425 UDF_Init* UDF_Init::I = new UDF_Init();