GRASS Programmer's Manual  6.4.2(2012)
V_call.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines