GRASS Programmer's Manual
6.4.2(2012)
|
00001 00031 /* 00032 ALGORITHM: 00033 | Zero out screen answer locations 00034 | Initial curses screens 00035 | Display text, constants, and answer fields 00036 | Write text (results from V_line() calls) to curses window 00037 | Write constants (results from V_const() calls) to curses window 00038 | Write answers (results from V_ques() calls) to curses window 00039 | Take commands from the keyboard 00040 | switch on commands: 00041 | case CR: case NL: case UP: case ESC: 00042 | switch on answer type 00043 | case string 00044 | remove trailing non-alphanumeric characters 00045 | copy answer to target denoted in V_ques() call 00046 | blank out screen line 00047 | copy target to curses window 00048 | case integer 00049 | run atoi on answer, putting results in target 00050 | denoted in V_ques() call 00051 | blank out screen line 00052 | printf target to curses window 00053 | case long 00054 | run atol on answer, putting results in target 00055 | denoted in V_ques() call 00056 | blank out screen line 00057 | printf target to curses window 00058 | case float, double 00059 | run sscanf on answer, putting results in target 00060 | denoted in V_ques() call 00061 | blank out screen line 00062 | printf target to curses window 00063 | default: 00064 | do nothing 00065 | if ESC+CR return from V_call() 00066 | if UP shift to previous question 00067 | if CR or NL shift to next question 00068 | case BS: Move cursor back one column in current question 00069 | case FS: Move cursor forward one column in current 00070 | question 00071 | case RPLT: Replot the current screen image 00072 | case DUMP: Dump (append) the current window to the user's 00073 | home dir. 00074 | default: If an alphanumeric, put that char on the screen 00075 | and in the current answer field 00076 | call V_exit (erase screen and exit curses) 00077 ********************************************************************** */ 00078 00079 #include <grass/config.h> 00080 #include <stdio.h> 00081 #include <stdlib.h> 00082 #include <string.h> 00083 #include <grass/vask.h> 00084 00085 00086 static void centered(const char *); 00087 static void fmt(char *, int, double); 00088 00089 /* define the V__ struct defined in vask.h */ 00090 struct V__ V__; 00091 00092 #define DUMP 001 00093 #define BS 010 00094 #define FS 014 00095 #define NL 012 00096 #define UP 013 00097 #define CR 015 00098 #define RPLT 022 00099 #define ESC 033 00100 #define CTRLC 003 00101 00102 #define TARGET V__.usr_answ[at_answer].targetptr 00103 #define ROW V__.usr_answ[at_answer].row 00104 #define COL V__.usr_answ[at_answer].col 00105 #define LENGTH V__.usr_answ[at_answer].length 00106 #define TYPE V__.usr_answ[at_answer].var_type 00107 #define ANSWER scr_answ[at_answer].position 00108 #define RELINE do { \ 00109 move(ROW, COL) ; \ 00110 for (incr2=0;incr2<LENGTH; incr2++) \ 00111 addch('_') ; \ 00112 move(ROW, COL) ; \ 00113 } while (0) 00114 00115 /* flag ctrl-c is to be allowed */ 00116 00117 static int interrupts_ok = 0; /* mod shapiro */ 00118 00119 00149 int V_call(void) 00150 { 00151 int incr; 00152 int incr2; 00153 int num_answers; 00154 int at_answer; 00155 int at_constant; 00156 int ans_col = 0; 00157 int newchar; 00158 int lastchar = 0; 00159 int new_answer = 0; 00160 struct 00161 { 00162 char position[80]; 00163 } scr_answ[MAX_ANSW]; 00164 int y, x; /* shapiro */ 00165 char temp[100]; 00166 int done; 00167 00168 /* Zero out screen answer locations */ 00169 for (incr = 0; incr < MAX_ANSW; incr++) 00170 for (incr2 = 0; incr2 < 80; incr2++) 00171 scr_answ[incr].position[incr2] = 000; 00172 00173 /* Initialize the curses windows */ 00174 V_init(); 00175 00176 /* Display text */ 00177 for (incr = 0; incr < MAX_LINE; incr++) { 00178 move(incr, 0); 00179 addstr(V__.page.line[incr]); 00180 } 00181 00182 /* Display constants */ 00183 for (at_constant = 0; at_constant < V__.NUM_CONST; at_constant++) { 00184 move(V__.constant[at_constant].row, V__.constant[at_constant].col); 00185 switch (V__.constant[at_constant].var_type) { 00186 case 's': 00187 addstr(V__.constant[at_constant].targetptr.c); 00188 break; 00189 case 'i': 00190 sprintf(temp, "%d", *V__.constant[at_constant].targetptr.i); 00191 addstr(temp); 00192 break; 00193 case 'l': 00194 sprintf(temp, "%ld", *V__.constant[at_constant].targetptr.l); 00195 addstr(temp); 00196 break; 00197 case 'f': 00198 fmt(temp, V__.constant[at_constant].decimal_places, 00199 (double)*V__.constant[at_constant].targetptr.f); 00200 addstr(temp); 00201 break; 00202 case 'd': 00203 fmt(temp, V__.constant[at_constant].decimal_places, 00204 (double)*V__.constant[at_constant].targetptr.d); 00205 addstr(temp); 00206 break; 00207 default: 00208 break; 00209 } 00210 } 00211 00212 /* Display answer locations */ 00213 for (at_answer = 0; at_answer < V__.NUM_ANSW; at_answer++) { 00214 /* clear ANSWER */ 00215 for (incr = 0; incr < 80; incr++) 00216 scr_answ[at_answer].position[incr] = 000; 00217 00218 switch (TYPE) { 00219 case 's': 00220 strcpy(ANSWER, TARGET.c); 00221 RELINE; 00222 for (incr = 0; incr < LENGTH; incr++) { 00223 if (*(TARGET.c + incr) == '\000') 00224 while (incr++ < LENGTH) 00225 addch('_'); 00226 else 00227 addch(*(TARGET.c + incr)); 00228 } 00229 break; 00230 case 'i': 00231 sprintf(ANSWER, "%d", *TARGET.i); 00232 RELINE; 00233 addstr(ANSWER); 00234 break; 00235 case 'l': 00236 sprintf(ANSWER, "%ld", *TARGET.l); 00237 RELINE; 00238 addstr(ANSWER); 00239 break; 00240 case 'f': 00241 fmt(ANSWER, V__.usr_answ[at_answer].decimal_places, 00242 (double)*TARGET.f); 00243 RELINE; 00244 addstr(ANSWER); 00245 break; 00246 case 'd': 00247 fmt(ANSWER, V__.usr_answ[at_answer].decimal_places, 00248 (double)*TARGET.d); 00249 RELINE; 00250 addstr(ANSWER); 00251 break; 00252 default: 00253 break; 00254 } 00255 } 00256 num_answers = at_answer; 00257 00258 if (interrupts_ok) 00259 move(22, 0); 00260 else 00261 move(23, 0); 00262 00263 centered("AFTER COMPLETING ALL ANSWERS, HIT <ESC><ENTER> TO CONTINUE"); 00264 if (interrupts_ok) { 00265 sprintf(temp, "(OR <Ctrl-C> TO %s)", V__.interrupt_msg); 00266 centered(temp); 00267 } 00268 00269 /* Begin taking commands/answers from terminal */ 00270 at_answer = 0; 00271 00272 move(ROW, COL); 00273 refresh(); 00274 00275 for (done = 0; !done;) { 00276 getyx(stdscr, y, x); 00277 00278 newchar = getch(); 00279 00280 switch (newchar) { 00281 case ERR: 00282 break; 00283 00284 case ESC: 00285 if (V__.NUM_ANSW <= 0) 00286 done = 1; 00287 break; 00288 00289 case CTRLC: 00290 if (interrupts_ok || V__.NUM_ANSW <= 0) 00291 done = 1; 00292 break; 00293 00294 #ifdef KEY_UP 00295 case KEY_UP: 00296 #endif 00297 case UP: 00298 new_answer = (at_answer + num_answers - 1) % num_answers; 00299 ans_col = 0; 00300 break; 00301 00302 #ifdef KEY_DOWN 00303 case KEY_DOWN: 00304 #endif 00305 case CR: 00306 case NL: 00307 new_answer = (at_answer + 1) % num_answers; 00308 ans_col = 0; 00309 if (lastchar == ESC && (newchar == CR || newchar == NL)) 00310 done = 1; 00311 break; 00312 00313 #ifdef KEY_LEFT 00314 case KEY_LEFT: 00315 ans_col = (ans_col - 1 >= 0) ? ans_col - 1 : 0; 00316 break; 00317 #endif 00318 00319 #ifdef KEY_BACKSPACE 00320 case KEY_BACKSPACE: 00321 #endif 00322 case BS: 00323 ans_col = (ans_col - 1 >= 0) ? ans_col - 1 : 0; 00324 ANSWER[ans_col] = ' '; 00325 move(ROW, COL + ans_col); 00326 addch(' '); 00327 break; 00328 00329 #ifdef KEY_RIGHT 00330 case KEY_RIGHT: 00331 #endif 00332 case FS: 00333 ans_col = (ans_col + 1 < LENGTH && 00334 ANSWER[ans_col]) ? ans_col + 1 : ans_col; 00335 break; 00336 00337 #ifdef KEY_HOME 00338 case KEY_HOME: 00339 ans_col = 0; 00340 break; 00341 #endif 00342 00343 #ifdef KEY_END 00344 case KEY_END: 00345 for (ans_col = 0; ans_col < LENGTH && ANSWER[ans_col]; 00346 ans_col++) ; 00347 break; 00348 #endif 00349 00350 #ifdef KEY_REFRESH 00351 case KEY_REFRESH: 00352 #endif 00353 case RPLT: 00354 wrefresh(curscr); 00355 break; 00356 00357 #ifdef KEY_PRINT 00358 case KEY_PRINT: 00359 #endif 00360 case DUMP: 00361 V__dump_window(); 00362 break; 00363 00364 case '\177': 00365 break; 00366 00367 default: 00368 if (ans_col < LENGTH && newchar >= 040 && newchar <= 0377) { 00369 addch(newchar); 00370 ANSWER[ans_col] = newchar; 00371 ans_col++; 00372 } 00373 break; 00374 } 00375 00376 if (new_answer != at_answer || done) { 00377 V__remove_trail(LENGTH, ANSWER); 00378 switch (TYPE) { 00379 case 's': 00380 strcpy(TARGET.c, ANSWER); 00381 RELINE; 00382 addstr(TARGET.c); 00383 break; 00384 case 'i': 00385 *TARGET.i = atoi(ANSWER); 00386 RELINE; 00387 sprintf(temp, "%d", *TARGET.i); 00388 addstr(temp); 00389 break; 00390 case 'l': 00391 *TARGET.l = atol(ANSWER); 00392 RELINE; 00393 sprintf(temp, "%ld", *TARGET.l); 00394 addstr(temp); 00395 break; 00396 case 'f': 00397 sscanf(ANSWER, "%f", TARGET.f); 00398 RELINE; 00399 fmt(ANSWER, V__.usr_answ[at_answer].decimal_places, 00400 (double)*TARGET.f); 00401 sscanf(ANSWER, "%f", TARGET.f); 00402 addstr(ANSWER); 00403 break; 00404 case 'd': 00405 sscanf(ANSWER, "%lf", TARGET.d); 00406 RELINE; 00407 fmt(ANSWER, V__.usr_answ[at_answer].decimal_places, 00408 (double)*TARGET.d); 00409 sscanf(ANSWER, "%lf", TARGET.d); 00410 addstr(ANSWER); 00411 break; 00412 default: 00413 break; 00414 } 00415 00416 at_answer = new_answer; 00417 } 00418 00419 lastchar = newchar; 00420 move(ROW, COL + ans_col); 00421 refresh(); 00422 00423 if (done) { 00424 interrupts_ok = 0; 00425 V_exit(); 00426 return (newchar != CTRLC); 00427 } 00428 } 00429 00430 return -1; 00431 } 00432 00433 00455 void V_intrpt_ok(void) 00456 { 00457 interrupts_ok = 1; /* will be set false when V_call() exists */ 00458 } 00459 00460 00475 void V_intrpt_msg(const char *msg) 00476 { 00477 strcpy(V__.interrupt_msg, msg); 00478 } 00479 00480 00481 static void fmt(char *s, int n, double x) 00482 { 00483 char buf[20]; 00484 00485 if (n >= 0) 00486 sprintf(buf, "%%.%dlf", n); 00487 else 00488 strcpy(buf, "%.5lf"); 00489 00490 /* I had to use .5lf instead of just lf since a number like 65.8 got 00491 * sprintf'ed as 65.800003 this is a hack - I admit it. 00492 */ 00493 sprintf(s, buf, x); 00494 if (n < 0) 00495 V__trim_decimal(s); 00496 } 00497 00498 00499 static void centered(const char *msg) 00500 { 00501 int indent; 00502 00503 indent = (80 - strlen(msg)) / 2; 00504 while (indent-- > 0) 00505 addstr(" "); 00506 00507 addstr(msg); 00508 addstr("\n"); 00509 }