1 /* This file is part of Netwib. Read and honor its license.
2 */
3 
4 /*-------------------------------------------------------------*/
netwib_priv_kbd_init_fd(int fd,netwib_priv_kbd * pkbd)5 netwib_err netwib_priv_kbd_init_fd(int fd,
6                                    netwib_priv_kbd *pkbd)
7 #if defined NETWIBDEF_SYSNAME_Unix
8 {
9   struct termios thetermios;
10 
11   pkbd->fd = fd;
12 
13   /* check if it's a tty */
14   pkbd->type = NETWIB_PRIV_KBDTYPE_UNKNOWN;
15   pkbd->consoleecho = NETWIB_FALSE;
16   pkbd->consolereadbyline = NETWIB_FALSE;
17   if (isatty(fd)) {
18     pkbd->type = NETWIB_PRIV_KBDTYPE_CONSOLE;
19     /* check if characters are echoed */
20     if (tcgetattr(fd, &thetermios)) {
21       return(NETWIB_ERR_FUTCGETATTR);
22     }
23     if (thetermios.c_lflag & ECHO) {
24       pkbd->consoleecho = NETWIB_TRUE;
25     }
26     if (thetermios.c_lflag & ICANON) {
27       pkbd->consolereadbyline = NETWIB_TRUE;
28     }
29   }
30 
31   pkbd->originalconsoleecho = pkbd->consoleecho;
32   pkbd->originalconsolereadbyline = pkbd->consolereadbyline;
33 
34   pkbd->availdata = NETWIB_FALSE;
35 
36   return(NETWIB_ERR_OK);
37 }
38 #elif defined NETWIBDEF_SYSNAME_Windows
39 {
40   pkbd = pkbd; /* for compiler warning */
41   fd = fd; /* for compiler warning */
42   return(NETWIB_ERR_LONOTIMPLEMENTED);
43 }
44 #else
45  #error "Unknown value for NETWIBDEF_SYSNAME"
46 #endif
47 /*-------------------------------------------------------------*/
netwib_priv_kbd_init_handle(NETWIBHANDLE h,netwib_priv_kbd * pkbd)48 netwib_err netwib_priv_kbd_init_handle(NETWIBHANDLE h,
49                                        netwib_priv_kbd *pkbd)
50 #if defined NETWIBDEF_SYSNAME_Unix
51 {
52   pkbd = pkbd; /* for compiler warning */
53   h = h; /* for compiler warning */
54   return(NETWIB_ERR_LONOTIMPLEMENTED);
55 }
56 #elif defined NETWIBDEF_SYSNAME_Windows
57 {
58   DWORD ftype, conmode;
59   BOOL err;
60 
61   pkbd->h = h;
62 
63   /* check if it's a tty */
64   pkbd->type = NETWIB_PRIV_KBDTYPE_UNKNOWN;
65   ftype = GetFileType(h);
66   if (ftype == FILE_TYPE_CHAR) {
67     pkbd->type = NETWIB_PRIV_KBDTYPE_CONSOLE;
68   } else if (ftype == FILE_TYPE_DISK) {
69     pkbd->type = NETWIB_PRIV_KBDTYPE_FILE;
70   } else if (ftype == FILE_TYPE_PIPE) {
71     pkbd->type = NETWIB_PRIV_KBDTYPE_PIPE;
72   }
73 
74   pkbd->availdata = NETWIB_FALSE;
75 
76   /* check if characters are echoed */
77   pkbd->consoleecho = NETWIB_TRUE;
78   if (pkbd->type == NETWIB_PRIV_KBDTYPE_CONSOLE) {
79     err = GetConsoleMode(h, &conmode);
80     if (!err) return(NETWIB_ERR_FUGETCONSOLEMODE);
81     if (!(conmode & ENABLE_ECHO_INPUT)) {
82       pkbd->consoleecho = NETWIB_FALSE;
83     }
84   }
85 
86   /* default behavior is to read line by line */
87   pkbd->consolereadbyline = NETWIB_TRUE;
88 
89   pkbd->originalconsoleecho = pkbd->consoleecho;
90   pkbd->originalconsolereadbyline = pkbd->consolereadbyline;
91 
92   return(NETWIB_ERR_OK);
93 }
94 #else
95  #error "Unknown value for NETWIBDEF_SYSNAME"
96 #endif
97 
98 /*-------------------------------------------------------------*/
netwib_priv_kbd_initdefault(netwib_priv_kbd * pkbd)99 netwib_err netwib_priv_kbd_initdefault(netwib_priv_kbd *pkbd)
100 {
101 #if defined NETWIBDEF_SYSNAME_Unix
102   return(netwib_priv_kbd_init_fd(0, pkbd));
103 #elif defined NETWIBDEF_SYSNAME_Windows
104   return(netwib_priv_kbd_init_handle(GetStdHandle(STD_INPUT_HANDLE), pkbd));
105 #else
106  #error "Unknown value for NETWIBDEF_SYSNAME"
107 #endif
108 }
109 
110 /*-------------------------------------------------------------*/
netwib_priv_kbd_close(netwib_priv_kbd * pkbd)111 netwib_err netwib_priv_kbd_close(netwib_priv_kbd *pkbd)
112 {
113   netwib_er(netwib_priv_kbd_ctl_set_echoline(pkbd,
114                                              pkbd->originalconsoleecho,
115                                              pkbd->originalconsolereadbyline));
116   return(NETWIB_ERR_OK);
117 }
118 
119 /*-------------------------------------------------------------*/
netwib_priv_kbd_ctl_set_purge(netwib_priv_kbd * pkbd)120 netwib_err netwib_priv_kbd_ctl_set_purge(netwib_priv_kbd *pkbd)
121 {
122   if (pkbd->type == NETWIB_PRIV_KBDTYPE_CONSOLE) {
123 #if defined NETWIBDEF_SYSNAME_Unix
124     struct termios old_termios;
125     if (tcgetattr(pkbd->fd, &old_termios)) {
126       return(NETWIB_ERR_FUTCGETATTR);
127     }
128     /* we use TCSAFLUSH which discards all input */
129     if (tcsetattr(pkbd->fd, TCSAFLUSH, &old_termios)) {
130       return(NETWIB_ERR_FUTCSETATTR);
131     }
132 #if 0
133     /* this works under Linux, Solaris, but not FreeBSD or OpenBSD (it
134        perturbs next calls) */
135     /* Note for next implementation : we can also use tcflush() */
136     struct termios old_termios, new_termios;
137     int c;
138 
139     /* ensure we read char by char (instead of line by line) */
140     if (tcgetattr(pkbd->fd, &old_termios)) {
141       return(NETWIB_ERR_FUTCGETATTR);
142     }
143     new_termios = old_termios;
144     new_termios.c_lflag &= (~ICANON);
145     new_termios.c_cc[VMIN] = 0;
146     new_termios.c_cc[VTIME] = 0;
147     if (tcsetattr(pkbd->fd, TCSANOW, &new_termios)) {
148       return(NETWIB_ERR_FUTCSETATTR);
149     }
150 
151     do {
152       c = getchar();
153     } while (c != EOF);
154 
155     /* reset */
156     if (tcsetattr(pkbd->fd, TCSANOW, &old_termios)) {
157       return(NETWIB_ERR_FUTCSETATTR);
158     }
159 #endif
160 #elif defined NETWIBDEF_SYSNAME_Windows
161     while (_kbhit()) {
162       _getch();
163     }
164 #else
165  #error "Unknown value for NETWIBDEF_SYSNAME"
166 #endif
167   }
168 
169   pkbd->availdata = NETWIB_FALSE;
170 
171   return(NETWIB_ERR_OK);
172 }
173 
174 /*-------------------------------------------------------------*/
netwib_priv_kbd_ctl_set_echoline(netwib_priv_kbd * pkbd,netwib_bool consoleecho,netwib_bool consolereadbyline)175 netwib_err netwib_priv_kbd_ctl_set_echoline(netwib_priv_kbd *pkbd,
176                                             netwib_bool consoleecho,
177                                             netwib_bool consolereadbyline)
178 #if defined NETWIBDEF_SYSNAME_Unix
179 {
180   struct termios thetermios;
181 
182   /* change mode */
183   if (pkbd->type == NETWIB_PRIV_KBDTYPE_CONSOLE) {
184     if (tcgetattr(pkbd->fd, &thetermios)) {
185       return(NETWIB_ERR_FUTCGETATTR);
186     }
187     if (consoleecho) {
188       thetermios.c_lflag |= ECHO;
189     } else {
190       thetermios.c_lflag &= ~ECHO;
191     }
192     if (consolereadbyline) {
193       thetermios.c_lflag |= ICANON;
194     } else {
195       thetermios.c_lflag &= (~ICANON);
196       thetermios.c_cc[VMIN] = 1;   /* need one char */
197       thetermios.c_cc[VTIME] = 0;  /* wait forever */
198     }
199     if (tcsetattr(pkbd->fd, TCSANOW, &thetermios)) {
200       return(NETWIB_ERR_FUTCSETATTR);
201     }
202   }
203 
204   /* store them */
205   pkbd->consoleecho = consoleecho;
206   pkbd->consolereadbyline = consolereadbyline;
207 
208   return(NETWIB_ERR_OK);
209 }
210 #elif defined NETWIBDEF_SYSNAME_Windows
211 {
212   /* we cannot change. We'll then use getch/getche */
213 
214   /* store them */
215   pkbd->consoleecho = consoleecho;
216   pkbd->consolereadbyline = consolereadbyline;
217 
218   return(NETWIB_ERR_OK);
219 }
220 #else
221  #error "Unknown value for NETWIBDEF_SYSNAME"
222 #endif
223 
224 /*-------------------------------------------------------------*/
netwib_priv_kbd_press(netwib_priv_kbd * pkbd,netwib_char * pc)225 netwib_err netwib_priv_kbd_press(netwib_priv_kbd *pkbd,
226                                  netwib_char *pc)
227 #if defined NETWIBDEF_SYSNAME_Unix
228 {
229   netwib_bool consoleecho, consolereadbyline;
230 
231   netwib_er(netwib_priv_kbd_ctl_set_purge(pkbd));
232   consoleecho = pkbd->consoleecho;
233   consolereadbyline = pkbd->consolereadbyline;
234   netwib_er(netwib_priv_kbd_ctl_set_echoline(pkbd, NETWIB_FALSE,
235                                              NETWIB_FALSE));
236   netwib_er(netwib_priv_kbd_read_key(pkbd, pc));
237   netwib_er(netwib_priv_kbd_ctl_set_echoline(pkbd, consoleecho,
238                                              consolereadbyline));
239 
240   return(NETWIB_ERR_OK);
241 }
242 #elif defined NETWIBDEF_SYSNAME_Windows
243 {
244   netwib_byte c;
245   netwib_err ret;
246   BOOL err;
247 
248   netwib_er(netwib_priv_kbd_ctl_set_purge(pkbd));
249 
250   /* cases which cannot be treated here */
251   if (pkbd->type != NETWIB_PRIV_KBDTYPE_CONSOLE) {
252     ret = netwib_priv_kbd_read_key(pkbd, pc);
253     return(ret);
254   }
255 
256   c = (netwib_byte) _getch();
257   if (c == 0x00) {
258     /* on Function-i, get the second part */
259     _getch();
260   } else if (c == 0xE0) {
261     /* arrow key, but get the second part */
262     _getch();
263   } else if (c == 0x03) {
264     /* on control-c, generate the event (then the program should exit) */
265     err = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
266     if (!err) {
267       return(NETWIB_ERR_FUGENERATECONSOLECTRLEVENT);
268     }
269   }
270   if (pc != NULL) *pc = c;
271 
272   return(NETWIB_ERR_OK);
273 }
274 #else
275  #error "Unknown value for NETWIBDEF_SYSNAME"
276 #endif
277 
278 /*-------------------------------------------------------------*/
netwib_priv_kbd_read_key_pipe(netwib_priv_kbd * pkbd,netwib_char * pc)279 static netwib_err netwib_priv_kbd_read_key_pipe(netwib_priv_kbd *pkbd,
280                                                 netwib_char *pc)
281 {
282 #if defined NETWIBDEF_SYSNAME_Unix
283   return(netwib_priv_fd_read_byte(pkbd->fd, (netwib_byte*)pc));
284 #elif defined NETWIBDEF_SYSNAME_Windows
285   return(netwib_priv_handle_read_byte(pkbd->h, (netwib_byte*)pc));
286 #else
287  #error "Unknown value for NETWIBDEF_SYSNAME"
288 #endif
289 }
290 
291 /*-------------------------------------------------------------*/
netwib_priv_kbd_read_key(netwib_priv_kbd * pkbd,netwib_char * pc)292 netwib_err netwib_priv_kbd_read_key(netwib_priv_kbd *pkbd,
293                                     netwib_char *pc)
294 #if defined NETWIBDEF_SYSNAME_Unix
295 {
296   netwib_char c;
297 
298   /* cases which cannot be treated here */
299   if (pkbd->type != NETWIB_PRIV_KBDTYPE_CONSOLE || pkbd->fd != 0) {
300     return(netwib_priv_kbd_read_key_pipe(pkbd, pc));
301   }
302 
303   /* read */
304   c = (netwib_char)fgetc(stdin);
305 
306   if (pc != NULL) *pc = c;
307   return(NETWIB_ERR_OK);
308 }
309 #elif defined NETWIBDEF_SYSNAME_Windows
310 {
311   netwib_byte c;
312   BOOL err;
313 
314   /* cases which cannot be treated here */
315   if (pkbd->type != NETWIB_PRIV_KBDTYPE_CONSOLE) {
316     return(netwib_priv_kbd_read_key_pipe(pkbd, pc));
317   }
318 
319   c = 0;
320   while (NETWIB_TRUE) {
321     c = (netwib_byte)_getch();
322     if (c == 0x08) {
323       /* ignore backspace */
324     } else if (c == 0x00) {
325       /* ignore Function-i, but get the second part */
326       _getch();
327     } else if (c == 0xE0) {
328       /* ignore arrow, but get the second part */
329       _getch();
330     } else if (c == 0x03) {
331       /* on control-c, generate the event (then the program should exit) */
332       err = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
333       if (!err) {
334         return(NETWIB_ERR_FUGENERATECONSOLECTRLEVENT);
335       }
336     } else {
337       /* ok */
338       break;
339     }
340   }
341 
342   if (pkbd->consoleecho) {
343     /* display pressed key */
344     if (c == 0x0D) {
345       /* because the newline is suppressed */
346       putchar(0x0D);
347       putchar(0x0A);
348     } else {
349       putchar(c);
350     }
351   }
352 
353   if (pc != NULL) *pc = c;
354   return(NETWIB_ERR_OK);
355 }
356 #else
357  #error "Unknown value for NETWIBDEF_SYSNAME"
358 #endif
359 
360 /*-------------------------------------------------------------*/
netwib_priv_kbd_read_line_pipe(netwib_priv_kbd * pkbd,netwib_buf * pbuf)361 static netwib_err netwib_priv_kbd_read_line_pipe(netwib_priv_kbd *pkbd,
362                                                  netwib_buf *pbuf)
363 {
364   netwib_char c;
365 
366   while(NETWIB_TRUE) {
367     netwib_er(netwib_priv_kbd_read_key(pkbd, &c));
368     if (c == '\n') break;
369     netwib_er(netwib_buf_append_byte(c, pbuf));
370   }
371 
372   return(NETWIB_ERR_OK);
373 }
374 
375 /*-------------------------------------------------------------*/
netwib_priv_kbd_read_line(netwib_priv_kbd * pkbd,netwib_buf * pbuf)376 netwib_err netwib_priv_kbd_read_line(netwib_priv_kbd *pkbd,
377                                      netwib_buf *pbuf)
378 #if defined NETWIBDEF_SYSNAME_Unix
379 {
380   int c;
381   netwib_err ret;
382 
383   /* cases which cannot be treated here */
384   if (pkbd->type != NETWIB_PRIV_KBDTYPE_CONSOLE || pkbd->fd != 0) {
385     return(netwib_priv_kbd_read_line_pipe(pkbd, pbuf));
386   }
387 
388   ret = NETWIB_ERR_OK;
389   while (NETWIB_TRUE) {
390     c = getc(stdin);
391     if (c == 0x0D || c == 0x0A || c == EOF) {
392       break;
393     }
394     ret = netwib_buf_append_byte(c, pbuf);
395     if (ret != NETWIB_ERR_OK) {
396       break;
397     }
398   }
399   if (!pkbd->consoleecho) {
400     puts("");
401   }
402 
403   return(NETWIB_ERR_OK);
404 }
405 #elif defined NETWIBDEF_SYSNAME_Windows
406 {
407   netwib_uint32 userstringsize;
408   int c;
409   BOOL err;
410 
411   /* cases which cannot be treated here */
412   if (pkbd->type != NETWIB_PRIV_KBDTYPE_CONSOLE) {
413     return(netwib_priv_kbd_read_line_pipe(pkbd, pbuf));
414   }
415 
416   userstringsize = 0;
417   while (NETWIB_TRUE) {
418     /* cannot use getche because backspace can erase data
419        printed before calling the function */
420     c = _getch();
421     if (c == 0x0D || c == 0x0A) {
422       if (pkbd->consoleecho) {
423         putchar(0x0D);
424         putchar(0x0A);
425       }
426       break;
427     } else if (c == 0x08) {
428       /* backspace */
429       if (userstringsize) {
430         userstringsize--;
431         pbuf->endoffset--;
432         if (pkbd->consoleecho) {
433           putchar(0x08);
434           putchar(' ');
435           putchar(0x08);
436         }
437       }
438     } else if (c == 0x00) {
439       /* Function-i ignore, but get the second part */
440       _getch();
441     } else if (c == 0xE0) {
442       /* ignore arrow, but get the second part */
443       _getch();
444     } else if (c == 0x03) {
445       /* on control-c, generate the event (then the program should exit) */
446       err = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
447       if (!err) {
448         return(NETWIB_ERR_FUGENERATECONSOLECTRLEVENT);
449       }
450     } else {
451       netwib_er(netwib_buf_append_byte((netwib_char)c, pbuf));
452       userstringsize++;
453       if (pkbd->consoleecho) {
454         putchar(c);
455       }
456     }
457   }
458   if (!pkbd->consoleecho) {
459     puts("");
460   }
461 
462   return(NETWIB_ERR_OK);
463 }
464 #else
465  #error "Unknown value for NETWIBDEF_SYSNAME"
466 #endif
467 
468 /*-------------------------------------------------------------*/
netwib_priv_kbd_wait(netwib_priv_kbd * pkbd,netwib_consttime * pabstime,netwib_bool * pevent)469 netwib_err netwib_priv_kbd_wait(netwib_priv_kbd *pkbd,
470                                 netwib_consttime *pabstime,
471                                 netwib_bool *pevent)
472 #if defined NETWIBDEF_SYSNAME_Unix
473 {
474   netwib_bool event;
475 
476   /* unfortunately, Linux does not detect a line twice, so we have
477      to keep state. This state is reset when we purge or read. */
478   if (pkbd->availdata) {
479     if (pevent != NULL) *pevent = NETWIB_TRUE;
480     return(NETWIB_ERR_OK);
481   }
482 
483   /* wait */
484   netwib_er(netwib_priv_fd_wait(pkbd->fd, NETWIB_IO_WAYTYPE_READ,
485                                 pabstime, &event));
486 
487   /* save state */
488   if (event) {
489     pkbd->availdata = NETWIB_TRUE;
490   }
491 
492   if (pevent != NULL) *pevent = event;
493   return(NETWIB_ERR_OK);
494 }
495 #elif defined NETWIBDEF_SYSNAME_Windows
496 {
497   netwib_handletype handletype;
498   netwib_bool event;
499 
500   switch(pkbd->type) {
501     case NETWIB_PRIV_KBDTYPE_CONSOLE : handletype = NETWIB_HANDLETYPE_CONSOLE; break;
502     case NETWIB_PRIV_KBDTYPE_FILE : handletype = NETWIB_HANDLETYPE_FILE; break;
503     case NETWIB_PRIV_KBDTYPE_PIPE : handletype = NETWIB_HANDLETYPE_PIPE; break;
504     default : handletype = NETWIB_HANDLETYPE_UNKNOWN; break;
505   }
506 
507   netwib_er(netwib_priv_handle_wait(pkbd->h, handletype,
508                                     NETWIB_IO_WAYTYPE_READ,
509                                     pabstime, &event));
510   /* waiting on a console handle does not ensure we have an event
511      because we use PeekConsoleInput to recheck */
512   if (!event) {
513     return(NETWIB_ERR_PLEASELOOPTIME);
514   }
515 
516   if (pevent != NULL) *pevent = NETWIB_TRUE;
517   return(NETWIB_ERR_OK);
518 }
519 #else
520  #error "Unknown value for NETWIBDEF_SYSNAME"
521 #endif
522 
523 /*-------------------------------------------------------------*/
netwib_priv_kbd_read(netwib_priv_kbd * pkbd,netwib_buf * pbuf)524 netwib_err netwib_priv_kbd_read(netwib_priv_kbd *pkbd,
525                                 netwib_buf *pbuf)
526 #if defined NETWIBDEF_SYSNAME_Unix
527 {
528   netwib_char c;
529 
530   /* reset state */
531   pkbd->availdata = NETWIB_FALSE;
532 
533   if (pkbd->consolereadbyline) {
534     netwib_er(netwib_priv_kbd_read_line(pkbd, pbuf));
535   } else {
536     netwib_er(netwib_priv_kbd_read_key(pkbd, &c));
537     netwib_er(netwib_buf_append_byte(c, pbuf));
538   }
539 
540   return(NETWIB_ERR_OK);
541 }
542 #elif defined NETWIBDEF_SYSNAME_Windows
543 {
544   netwib_char c;
545 
546   if (pkbd->consolereadbyline) {
547     netwib_er(netwib_priv_kbd_read_line(pkbd, pbuf));
548   } else {
549     netwib_er(netwib_priv_kbd_read_key(pkbd, &c));
550     netwib_er(netwib_buf_append_byte(c, pbuf));
551   }
552 
553   return(NETWIB_ERR_OK);
554 }
555 #else
556  #error "Unknown value for NETWIBDEF_SYSNAME"
557 #endif
558 
559 /*-------------------------------------------------------------*/
netwib_priv_kbd_buf_append(netwib_constbuf * pmessage,netwib_constbuf * pdefaulttext,netwib_bool echokeys,netwib_char prompt,netwib_bool askifempty,netwib_buf * pbuf)560 netwib_err netwib_priv_kbd_buf_append(netwib_constbuf *pmessage,
561                                       netwib_constbuf *pdefaulttext,
562                                       netwib_bool echokeys,
563                                       netwib_char prompt,
564                                       netwib_bool askifempty,
565                                       netwib_buf *pbuf)
566 {
567   netwib_buf buf, cmsg, call;
568   netwib_string bufref;
569   netwib_priv_kbd kbd;
570   netwib_bool havemessage, havedefaulttext;
571   netwib_char c;
572   netwib_err ret;
573 
574   /* obtain strings */
575   havemessage = NETWIB_FALSE;
576   if (netwib__buf_ref_data_sizenull(pmessage) != 0) {
577     havemessage = NETWIB_TRUE;
578   }
579   havedefaulttext = NETWIB_FALSE;
580   if (netwib__buf_ref_data_sizenull(pdefaulttext) != 0) {
581     havedefaulttext = NETWIB_TRUE;
582   }
583 
584   /* display message */
585   if (havemessage) {
586     if (echokeys && havedefaulttext) {
587       netwib_er(netwib_fmt_display("%{buf} [%{buf}]%c ", pmessage,
588                                    pdefaulttext, prompt));
589     } else {
590       netwib_er(netwib_fmt_display("%{buf}%c ", pmessage, prompt));
591     }
592   }
593 
594   /* get user string */
595   netwib_er(netwib_buf_init_mallocdefault(&buf));
596   netwib_er(netwib_priv_kbd_initdefault(&kbd));
597   netwib_er(netwib_priv_kbd_ctl_set_echoline(&kbd, echokeys, NETWIB_TRUE));
598   netwib_er(netwib_priv_kbd_read_line(&kbd, &buf));
599   netwib_er(netwib_priv_kbd_close(&kbd));
600 
601   /* user entered something */
602   netwib_er(netwib_buf_ref_string(&buf, &bufref));
603   if (bufref[0] != '\0') {
604     ret = netwib_buf_append_buf(&buf, pbuf);
605     netwib_er(netwib_buf_close(&buf));
606     return(ret);
607   }
608   netwib_er(netwib_buf_close(&buf));
609 
610   /* user entered nothing and there is no default : nothing to append */
611   if (!havedefaulttext) {
612     return(NETWIB_ERR_OK);
613   }
614 
615   /* ask user */
616   if (askifempty) {
617     netwib_er(netwib_buf_init_ext_string("Do you want an Empty string or the Default string ?", &cmsg));
618     netwib_er(netwib_buf_init_ext_string("eEdD", &call));
619     netwib_er(netwib_char_init_kbd(&cmsg, &call, 'd', &c));
620     if (c == 'd' || c == 'D') {
621       netwib_er(netwib_buf_append_buf(pdefaulttext, pbuf));
622     }
623   }
624 
625   return(NETWIB_ERR_OK);
626 }
627