GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
V_call.c
Go to the documentation of this file.
1 
31 /*
32  ALGORITHM:
33  | Zero out screen answer locations
34  | Initial curses screens
35  | Display text, constants, and answer fields
36  | Write text (results from V_line() calls) to curses window
37  | Write constants (results from V_const() calls) to curses window
38  | Write answers (results from V_ques() calls) to curses window
39  | Take commands from the keyboard
40  | switch on commands:
41  | case CR: case NL: case UP: case ESC:
42  | switch on answer type
43  | case string
44  | remove trailing non-alphanumeric characters
45  | copy answer to target denoted in V_ques() call
46  | blank out screen line
47  | copy target to curses window
48  | case integer
49  | run atoi on answer, putting results in target
50  | denoted in V_ques() call
51  | blank out screen line
52  | printf target to curses window
53  | case long
54  | run atol on answer, putting results in target
55  | denoted in V_ques() call
56  | blank out screen line
57  | printf target to curses window
58  | case float, double
59  | run sscanf on answer, putting results in target
60  | denoted in V_ques() call
61  | blank out screen line
62  | printf target to curses window
63  | default:
64  | do nothing
65  | if ESC+CR return from V_call()
66  | if UP shift to previous question
67  | if CR or NL shift to next question
68  | case BS: Move cursor back one column in current question
69  | case FS: Move cursor forward one column in current
70  | question
71  | case RPLT: Replot the current screen image
72  | case DUMP: Dump (append) the current window to the user's
73  | home dir.
74  | default: If an alphanumeric, put that char on the screen
75  | and in the current answer field
76  | call V_exit (erase screen and exit curses)
77  ********************************************************************** */
78 
79 #include <grass/config.h>
80 #include <stdio.h>
81 #include <stdlib.h>
82 #include <string.h>
83 #include <grass/vask.h>
84 
85 
86 static void centered(const char *);
87 static void fmt(char *, int, double);
88 
89 /* define the V__ struct defined in vask.h */
90 struct V__ V__;
91 
92 #define DUMP 001
93 #define BS 010
94 #define FS 014
95 #define NL 012
96 #define UP 013
97 #define CR 015
98 #define RPLT 022
99 #define ESC 033
100 #define CTRLC 003
101 
102 #define TARGET V__.usr_answ[at_answer].targetptr
103 #define ROW V__.usr_answ[at_answer].row
104 #define COL V__.usr_answ[at_answer].col
105 #define LENGTH V__.usr_answ[at_answer].length
106 #define TYPE V__.usr_answ[at_answer].var_type
107 #define ANSWER scr_answ[at_answer].position
108 #define RELINE do { \
109  move(ROW, COL) ; \
110  for (incr2=0;incr2<LENGTH; incr2++) \
111  addch('_') ; \
112  move(ROW, COL) ; \
113  } while (0)
114 
115 /* flag ctrl-c is to be allowed */
116 
117 static int interrupts_ok = 0; /* mod shapiro */
118 
119 
149 int V_call(void)
150 {
151  int incr;
152  int incr2;
153  int num_answers;
154  int at_answer;
155  int at_constant;
156  int ans_col = 0;
157  int newchar;
158  int lastchar = 0;
159  int new_answer = 0;
160  struct
161  {
162  char position[80];
163  } scr_answ[MAX_ANSW];
164  int y, x; /* shapiro */
165  char temp[100];
166  int done;
167 
168  /* Zero out screen answer locations */
169  for (incr = 0; incr < MAX_ANSW; incr++)
170  for (incr2 = 0; incr2 < 80; incr2++)
171  scr_answ[incr].position[incr2] = 000;
172 
173  /* Initialize the curses windows */
174  V_init();
175 
176  /* Display text */
177  for (incr = 0; incr < MAX_LINE; incr++) {
178  move(incr, 0);
179  addstr(V__.page.line[incr]);
180  }
181 
182  /* Display constants */
183  for (at_constant = 0; at_constant < V__.NUM_CONST; at_constant++) {
184  move(V__.constant[at_constant].row, V__.constant[at_constant].col);
185  switch (V__.constant[at_constant].var_type) {
186  case 's':
187  addstr(V__.constant[at_constant].targetptr.c);
188  break;
189  case 'i':
190  sprintf(temp, "%d", *V__.constant[at_constant].targetptr.i);
191  addstr(temp);
192  break;
193  case 'l':
194  sprintf(temp, "%ld", *V__.constant[at_constant].targetptr.l);
195  addstr(temp);
196  break;
197  case 'f':
198  fmt(temp, V__.constant[at_constant].decimal_places,
199  (double)*V__.constant[at_constant].targetptr.f);
200  addstr(temp);
201  break;
202  case 'd':
203  fmt(temp, V__.constant[at_constant].decimal_places,
204  (double)*V__.constant[at_constant].targetptr.d);
205  addstr(temp);
206  break;
207  default:
208  break;
209  }
210  }
211 
212  /* Display answer locations */
213  for (at_answer = 0; at_answer < V__.NUM_ANSW; at_answer++) {
214  /* clear ANSWER */
215  for (incr = 0; incr < 80; incr++)
216  scr_answ[at_answer].position[incr] = 000;
217 
218  switch (TYPE) {
219  case 's':
220  strcpy(ANSWER, TARGET.c);
221  RELINE;
222  for (incr = 0; incr < LENGTH; incr++) {
223  if (*(TARGET.c + incr) == '\000')
224  while (incr++ < LENGTH)
225  addch('_');
226  else
227  addch(*(TARGET.c + incr));
228  }
229  break;
230  case 'i':
231  sprintf(ANSWER, "%d", *TARGET.i);
232  RELINE;
233  addstr(ANSWER);
234  break;
235  case 'l':
236  sprintf(ANSWER, "%ld", *TARGET.l);
237  RELINE;
238  addstr(ANSWER);
239  break;
240  case 'f':
241  fmt(ANSWER, V__.usr_answ[at_answer].decimal_places,
242  (double)*TARGET.f);
243  RELINE;
244  addstr(ANSWER);
245  break;
246  case 'd':
247  fmt(ANSWER, V__.usr_answ[at_answer].decimal_places,
248  (double)*TARGET.d);
249  RELINE;
250  addstr(ANSWER);
251  break;
252  default:
253  break;
254  }
255  }
256  num_answers = at_answer;
257 
258  if (interrupts_ok)
259  move(22, 0);
260  else
261  move(23, 0);
262 
263  centered("AFTER COMPLETING ALL ANSWERS, HIT <ESC><ENTER> TO CONTINUE");
264  if (interrupts_ok) {
265  sprintf(temp, "(OR <Ctrl-C> TO %s)", V__.interrupt_msg);
266  centered(temp);
267  }
268 
269  /* Begin taking commands/answers from terminal */
270  at_answer = 0;
271 
272  move(ROW, COL);
273  refresh();
274 
275  for (done = 0; !done;) {
276  getyx(stdscr, y, x);
277 
278  newchar = getch();
279 
280  switch (newchar) {
281  case ERR:
282  break;
283 
284  case ESC:
285  if (V__.NUM_ANSW <= 0)
286  done = 1;
287  break;
288 
289  case CTRLC:
290  if (interrupts_ok || V__.NUM_ANSW <= 0)
291  done = 1;
292  break;
293 
294 #ifdef KEY_UP
295  case KEY_UP:
296 #endif
297  case UP:
298  new_answer = (at_answer + num_answers - 1) % num_answers;
299  ans_col = 0;
300  break;
301 
302 #ifdef KEY_DOWN
303  case KEY_DOWN:
304 #endif
305  case CR:
306  case NL:
307  new_answer = (at_answer + 1) % num_answers;
308  ans_col = 0;
309  if (lastchar == ESC && (newchar == CR || newchar == NL))
310  done = 1;
311  break;
312 
313 #ifdef KEY_LEFT
314  case KEY_LEFT:
315  ans_col = (ans_col - 1 >= 0) ? ans_col - 1 : 0;
316  break;
317 #endif
318 
319 #ifdef KEY_BACKSPACE
320  case KEY_BACKSPACE:
321 #endif
322  case BS:
323  ans_col = (ans_col - 1 >= 0) ? ans_col - 1 : 0;
324  ANSWER[ans_col] = ' ';
325  move(ROW, COL + ans_col);
326  addch(' ');
327  break;
328 
329 #ifdef KEY_RIGHT
330  case KEY_RIGHT:
331 #endif
332  case FS:
333  ans_col = (ans_col + 1 < LENGTH &&
334  ANSWER[ans_col]) ? ans_col + 1 : ans_col;
335  break;
336 
337 #ifdef KEY_HOME
338  case KEY_HOME:
339  ans_col = 0;
340  break;
341 #endif
342 
343 #ifdef KEY_END
344  case KEY_END:
345  for (ans_col = 0; ans_col < LENGTH && ANSWER[ans_col];
346  ans_col++) ;
347  break;
348 #endif
349 
350 #ifdef KEY_REFRESH
351  case KEY_REFRESH:
352 #endif
353  case RPLT:
354  wrefresh(curscr);
355  break;
356 
357 #ifdef KEY_PRINT
358  case KEY_PRINT:
359 #endif
360  case DUMP:
361  V__dump_window();
362  break;
363 
364  case '\177':
365  break;
366 
367  default:
368  if (ans_col < LENGTH && newchar >= 040 && newchar <= 0377) {
369  addch(newchar);
370  ANSWER[ans_col] = newchar;
371  ans_col++;
372  }
373  break;
374  }
375 
376  if (new_answer != at_answer || done) {
378  switch (TYPE) {
379  case 's':
380  strcpy(TARGET.c, ANSWER);
381  RELINE;
382  addstr(TARGET.c);
383  break;
384  case 'i':
385  *TARGET.i = atoi(ANSWER);
386  RELINE;
387  sprintf(temp, "%d", *TARGET.i);
388  addstr(temp);
389  break;
390  case 'l':
391  *TARGET.l = atol(ANSWER);
392  RELINE;
393  sprintf(temp, "%ld", *TARGET.l);
394  addstr(temp);
395  break;
396  case 'f':
397  sscanf(ANSWER, "%f", TARGET.f);
398  RELINE;
399  fmt(ANSWER, V__.usr_answ[at_answer].decimal_places,
400  (double)*TARGET.f);
401  sscanf(ANSWER, "%f", TARGET.f);
402  addstr(ANSWER);
403  break;
404  case 'd':
405  sscanf(ANSWER, "%lf", TARGET.d);
406  RELINE;
407  fmt(ANSWER, V__.usr_answ[at_answer].decimal_places,
408  (double)*TARGET.d);
409  sscanf(ANSWER, "%lf", TARGET.d);
410  addstr(ANSWER);
411  break;
412  default:
413  break;
414  }
415 
416  at_answer = new_answer;
417  }
418 
419  lastchar = newchar;
420  move(ROW, COL + ans_col);
421  refresh();
422 
423  if (done) {
424  interrupts_ok = 0;
425  V_exit();
426  return (newchar != CTRLC);
427  }
428  }
429 
430  return -1;
431 }
432 
433 
455 void V_intrpt_ok(void)
456 {
457  interrupts_ok = 1; /* will be set false when V_call() exists */
458 }
459 
460 
475 void V_intrpt_msg(const char *msg)
476 {
477  strcpy(V__.interrupt_msg, msg);
478 }
479 
480 
481 static void fmt(char *s, int n, double x)
482 {
483  char buf[20];
484 
485  if (n >= 0)
486  sprintf(buf, "%%.%dlf", n);
487  else
488  strcpy(buf, "%.5lf");
489 
490  /* I had to use .5lf instead of just lf since a number like 65.8 got
491  * sprintf'ed as 65.800003 this is a hack - I admit it.
492  */
493  sprintf(s, buf, x);
494  if (n < 0)
495  V__trim_decimal(s);
496 }
497 
498 
499 static void centered(const char *msg)
500 {
501  int indent;
502 
503  indent = (80 - strlen(msg)) / 2;
504  while (indent-- > 0)
505  addstr(" ");
506 
507  addstr(msg);
508  addstr("\n");
509 }
#define ANSWER
Definition: V_call.c:107
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
#define COL
Definition: V_call.c:104
void V__remove_trail(int ans_col, char *answer)
Remove trailing text from answer?
Definition: V_support.c:95
struct V__ V__
Definition: V_call.c:90
void V_exit(void)
Erases the current screen and flushes the current curses setup.
Definition: V_exit.c:41
#define BS
Definition: V_call.c:93
#define TARGET
Definition: V_call.c:102
#define DUMP
Definition: V_call.c:92
int V_call(void)
Interact with the user.
Definition: V_call.c:149
#define NL
Definition: V_call.c:95
int y
Definition: plot.c:34
#define ERR
A fatal error message.
Definition: lib/gis/error.c:41
#define CTRLC
Definition: V_call.c:100
#define LENGTH
Definition: V_call.c:105
#define UP
Definition: V_call.c:96
#define TYPE
Definition: V_call.c:106
#define ESC
Definition: V_call.c:99
#define FS
Definition: V_call.c:94
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
Definition: g3drange.c:62
int V__dump_window(void)
Dumps screen to file.
Definition: V_support.c:50
tuple msg
Definition: wxnviz.py:32
void V_intrpt_msg(const char *msg)
Change CTRL-C message.
Definition: V_call.c:475
#define ROW
Definition: V_call.c:103
void V_init(void)
Initialize curses and prepare screen.
Definition: V_init.c:42
#define RPLT
Definition: V_call.c:98
#define RELINE
Definition: V_call.c:108
void V__trim_decimal(char *buf)
Remove trailing zeros from decimal number.
Definition: V_trim_dec.c:42
#define CR
Definition: V_call.c:97
int n
Definition: dataquad.c:291
void V_intrpt_ok(void)
Allow CTRL-C.
Definition: V_call.c:455