]> andersk Git - moira.git/blob - clients/userreg/display.c
cc1df59e67db44582af590a066053d4267c63df5
[moira.git] / clients / userreg / display.c
1 /* $Id $
2  *
3  * Display function for userreg client
4  *
5  * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <moira.h>
12
13 #include <sys/time.h>
14
15 #include <curses.h>
16 #include <stdio.h>
17 #include <time.h>
18 #include <unistd.h>
19
20 #include "userreg.h"
21
22 RCSID("$Header$");
23
24 void make_border(int l);
25 void query_user(char *prompt, char *buf, int maxsize, int timeout,
26                 int echop, int emptyok, int valuep);
27
28 #define DESC_WIDTH 18
29 #define HEADER "*** Athena User Account Registration ***"
30 #define HELP   "    Press backspace to delete a character.  Press Ctrl-C to start over."
31 #define BORDER_CHAR '-'
32 #define MIN_COLS 80
33 #define MIN_LINES 24
34
35 WINDOW *displayw, *queryw;
36 WINDOW *dataw, *helpw;
37 WINDOW *fnamew, *midw, *lnamew, *idw, *loginw;
38 extern char typed_mit_id[100];
39
40 /* Set up the windows and subwindows on the display */
41 void setup_display(void)
42 {
43   initscr();                    /* Start up curses */
44
45   if (COLS < MIN_COLS || LINES < MIN_LINES)
46     {
47       fprintf(stderr, "Screen must be at least %d x %d\n",
48               MIN_LINES, MIN_COLS);
49       exit(1);
50     }
51
52   noecho();                     /* And the tty input */
53   raw();
54   freopen("/dev/null", "w", stderr);/* Toss the standard error output */
55
56   /* Make sure the place is clean */
57   clear();
58
59   /* Set up the top-level windows */
60   /* First line is the header */
61   displayw = subwin(stdscr, 12, 0, 2, 0);/* Lines 2-13 */
62   scrollok(displayw, TRUE);
63
64   queryw = subwin(stdscr, 1, 0, 15, 0);/* Line 15 */
65   scrollok(queryw, TRUE);
66
67   dataw = subwin(stdscr, 5, 0, 17, 0);/* Lines 17-21 */
68
69   /* Set up the data windows */
70   fnamew = subwin(stdscr, 1, 0, 17, DESC_WIDTH);
71   midw = subwin(stdscr, 1, 0, 18, DESC_WIDTH);
72   lnamew = subwin(stdscr, 1, 0, 19, DESC_WIDTH);
73   idw = subwin(stdscr, 1, 0, 20, DESC_WIDTH);
74   loginw = subwin(stdscr, 1, 0, 21, DESC_WIDTH);
75 }
76
77 /* Clear and restore the display */
78 void reset_display(void)
79 {
80   clear();
81
82   /* Put back the borders */
83   make_border(1);
84   make_border(14);
85   make_border(16);
86   make_border(22);
87
88   /* Put in the window dressing */
89   wmove(dataw, 0, 0);
90   waddstr(dataw, "First Name:\n");
91   waddstr(dataw, "Middle Initial:\n");
92   waddstr(dataw, "Family Name:\n");
93   waddstr(dataw, "MIT ID #:\n\n");
94   waddstr(dataw, "Username:\n");
95   wclrtoeol(dataw);
96
97   /* Set up the header */
98   mvaddstr(0, (COLS - strlen (HEADER)) / 2, HEADER);
99   mvaddstr(23, 0, HELP);
100
101   /* Put it all up */
102   refresh();
103 }
104
105
106 /* Make a one-line border on line l of stdscr */
107 void make_border(int l)
108 {
109   int i;
110
111   move(l, 0);
112   for(i = 0; i < COLS - 1; i++)
113     addch(BORDER_CHAR);
114 }
115
116 /* This replaces several "useful" display functions in the old userreg */
117 void redisp(void)
118 {
119   mvwprintw(fnamew, 0, 0, "%-24s", user.u_first);
120   wrefresh(fnamew);
121   mvwprintw(midw, 0, 0, "%-24s", user.u_mid_init);
122   wrefresh(midw);
123   mvwprintw(lnamew, 0, 0, "%-24s", user.u_last);
124   wrefresh(lnamew);
125   mvwprintw(idw, 0, 0, "%-24s", typed_mit_id);
126   wrefresh(idw);
127   mvwprintw(loginw, 0, 0, "%-24s", user.u_login);
128   wrefresh(loginw);
129 }
130
131
132 /* Input and input_no_echo exist only to save on retyping */
133 void input(char *prompt, char *buf, int maxsize, int timeout, int emptyok)
134 {
135   query_user(prompt, buf, maxsize, timeout, TRUE, emptyok, TRUE);
136 }
137
138 void input_no_echo(char *prompt, char *buf, int maxsize, int timeout)
139 {
140   query_user(prompt, buf, maxsize, timeout, FALSE, FALSE, TRUE);
141 }
142
143
144 /* make the user press any key to continue */
145 void wait_for_user(void)
146 {
147   char buf[BUFSIZ];
148
149   redisp();
150   query_user("Press RETURN or ENTER to continue", buf, 1,
151              15 * 60, FALSE, TRUE, FALSE);
152 }
153
154
155 /* Gets input through the query buffer */
156 /* Exit(1)'s on read errors */
157 /* Signals SIGALRM after 'timeout' seconds */
158 void query_user(char *prompt, char *buf, int maxsize, int timeout,
159                 int echop, int emptyok, int valuep)
160 {
161   int c;
162   int i;
163   struct itimerval it;
164
165 retry:
166   /* Set up interval timer */
167   it.it_interval.tv_sec = 0;
168   it.it_interval.tv_usec = 0;
169   it.it_value.tv_sec = timeout;
170   it.it_value.tv_usec = 0;
171   setitimer(ITIMER_REAL, &it, NULL);
172
173   /* Erase the query window and put up a prompt */
174   werase(queryw);
175   mvwaddstr(queryw, 0, 0, prompt);
176   waddch(queryw, ' ');          /* Put in a space, as Blox does */
177   wrefresh(queryw);
178
179   i = 0;
180   while ((c = getchar()) != '\r' && c != '\n')
181     {
182       switch (c)
183         {
184         case '\025':            /* Ctl-U */
185           goto retry;
186         case EOF:
187           /* We're in raw mode, so EOF means disaster */
188           exit(1);
189           break;
190         delchar:
191         case '\177':            /* Delete */
192         case '\010':            /* Backspace */
193           if (i)
194             {
195               i--;
196               if (echop)
197                 {
198                   int x, y;
199                   getyx(queryw, y, x);
200                   wmove(queryw, y, x - 1);
201                   wclrtoeol(queryw);
202                   wrefresh(queryw);
203                 }
204             }
205           break;
206         case '\003':            /* Ctrl-C */
207           clear();
208           restore_display();
209           exit(0);
210           break;
211         default:
212           if (c >= ' ')         /* Ignore all other control chars */
213             {
214               buf[i++] = c;
215               if (echop)
216                 {
217                   waddch(queryw, c);
218                   wrefresh(queryw);
219                 }
220             }
221           break;
222         }
223       if (valuep && i >= maxsize)
224         {
225           wfeep();
226           wprintw(displayw, "You are not allowed to type more than %d "
227                   "characters for this answer.\n", maxsize - 1);
228           wrefresh(displayw);
229           goto delchar;
230         }
231     }
232
233   if (i == 0)
234     {
235       if (emptyok && valuep &&
236           (askyn("Do you really want this field left blank (y/n)? ") == NO))
237         goto retry;
238       if (!emptyok)
239         {
240           wprintw(displayw, "You must enter something here.\n");
241           wrefresh(displayw);
242           goto retry;
243         }
244     }
245
246
247   /* Input is complete so disable interval timer. */
248   it.it_interval.tv_sec = 0;
249   it.it_interval.tv_usec = 0;
250   it.it_value.tv_sec = 0;
251   it.it_value.tv_usec = 0;
252   setitimer(ITIMER_REAL, &it, NULL);
253
254   buf[i] = '\0';                /* Put a null on the end */
255
256   werase(queryw);               /* Clean up the query window */
257   wrefresh(queryw);
258
259   return;                       /* And get out of here. */
260 }
261
262 int askyn(char *prompt)
263 {
264   int ypos, xpos;
265   int answer;
266   struct itimerval it;
267   int c;
268
269 start:
270   werase(queryw);
271   mvwaddstr(queryw, 0, 0, prompt);
272   wrefresh(queryw);
273
274   getyx(queryw, ypos, xpos);
275   answer = 2;                   /* No answer. */
276
277   /* Reset interval timer for y/n question. */
278   it.it_interval.tv_sec = 0;
279   it.it_interval.tv_usec = 0;
280   it.it_value.tv_sec = YN_TIMEOUT;
281   it.it_value.tv_usec = 0;
282   setitimer(ITIMER_REAL, &it, NULL);
283
284   while ((c = getchar ()) != '\r' && c != '\n') /* Wait for CR. */
285     {
286       switch (c)
287         {
288         case 'n':                       /* No. */
289         case 'N':
290           wmove(queryw, ypos, xpos);
291           wclrtoeol(queryw);
292           waddstr(queryw, "no");
293           wrefresh(queryw);
294           answer = NO;
295           continue;
296         case 'y':                       /* Yes. */
297         case 'Y':
298           wmove(queryw, ypos, xpos);
299           wclrtoeol(queryw);
300           waddstr(queryw, "yes");
301           wrefresh(queryw);
302           answer = YES;
303           continue;
304         case '\177':            /* Delete */
305         case '\010':            /* Backspace */
306         case '\025':            /* Ctl-U */
307           wmove(queryw, ypos, xpos);
308           wclrtoeol(queryw);
309           wrefresh(queryw);
310           answer = 2;           /* No answer. */
311           break;
312         case EOF:
313           /* We're in raw mode, so EOF means disaster */
314           exit(1);
315           break;
316         case '\003':            /* Ctrl-C */
317           clear();
318           restore_display();
319           exit(0);
320           break;
321         default:                /* Ignore everything else. */
322           break;
323         }
324     }
325
326   if (answer == 2)              /* No answer. */
327     {
328       display_text_line(0);
329       display_text_line("Please answer y or n.");
330       goto start;
331     }
332
333   return answer;
334 }
335
336 /* Display_text_line puts up a line of text in the display window */
337 /* Special case: if line is 0, clear the display area */
338 void display_text_line(char *line)
339 {
340   if (line)
341     {
342       waddstr(displayw, line);
343       waddch(displayw, '\n');
344     }
345   else
346     werase(displayw);
347   wrefresh(displayw);
348 }
349
350 /* Display_text displays a canned message from a file.  The string
351  * will get imbedded in any %s's in the text.
352  */
353 void display_text(char *filename, char *string)
354 {
355   FILE * fp;
356   char buf[100], buf1[110];
357
358   werase(displayw);
359   if (!(fp = fopen (filename, "r")))
360     {
361       wprintw (displayw, "Can't open file %s for reading.\n", filename);
362       return;
363     }
364
365   while (fgets (buf, 100, fp))
366     {
367       /* get rid of the newline */
368       buf[strlen(buf) - 1] = '\0';
369       sprintf(buf1, buf, string);
370       waddstr(displayw, buf1);
371       waddch(displayw, '\n');
372     }
373
374   wrefresh(displayw);
375   fclose(fp);
376 }
377
378 /* Clear_display wipes the display and turns off curses */
379 void restore_display(void)
380 {
381   clear();
382   refresh();
383   noraw();
384   echo();
385   endwin();
386 }
387
388 void timer_on(void)
389 {
390   struct itimerval it;
391
392   it.it_interval.tv_sec = 0;
393   it.it_interval.tv_usec = 0;
394   it.it_value.tv_sec = TIMER_TIMEOUT;
395   it.it_value.tv_usec = 0;
396   setitimer(ITIMER_REAL, &it, NULL);
397 }
398
399 void timer_off(void)
400 {
401   struct itimerval it;
402
403   it.it_interval.tv_sec = 0;
404   it.it_interval.tv_usec = 0;
405   it.it_value.tv_sec = 0;
406   it.it_value.tv_usec = 0;
407   setitimer(ITIMER_REAL, &it, NULL);
408 }
409
410
411 void wfeep(void)
412 {
413   char buf = '\007';
414   write(1, &buf, 1);
415 }
This page took 0.237294 seconds and 3 git commands to generate.