GRASS Programmer's Manual 6.4.1(2011)
|
00001 00002 /**************************************************************** 00003 * These routines prompt the user for names of GIS data files 00004 * 00005 * G_ask_new (prompt, name, element, desc) 00006 * G_ask_old (prompt, name, element, desc) 00007 * G_ask_any (prompt, name, element, desc, warn) 00008 * G_ask_in_mapset (prompt, name, element, desc) 00009 * G_ask_new_file (prompt, name, element, desc) 00010 * G_ask_old_file (prompt, name, element, desc) 00011 * 00012 * G_ask_new_ext (prompt, name, element, desc, option, lister) 00013 * G_ask_old_ext (prompt, name, element, desc, option, lister) 00014 * G_ask_any_ext (prompt, name, element, desc, warn, option, lister) 00015 * G_ask_in_mapset_ext (prompt, name, element, desc, option, lister) 00016 * 00017 * char *prompt prompt to be printed. can be "" in which 00018 * case an appropriate prompt will be printed. 00019 * char *name buffer to hold the name input by the user 00020 * char *element GIS data element - "cell", "vect", etc. 00021 * char *desc a description of element. Used for prompting 00022 * and listing. Will be set to element if given as "" 00023 * (eg, if element is "vect", set desc = "vector") 00024 * char *option list option. a description of the option. 00025 * (eg, "with utms" will prompt as follows: 00026 * list -f for a list with utms) 00027 * int (*lister)() subroutine to return text for -f option. 00028 * 00029 * 00030 * G_ask_new() requires the user to enter the name of a file 00031 * which does not exist in the current mapset 00032 * (but which may exist in other mapsets). 00033 * 00034 * G_ask_old() requires the user to enter the name of a file 00035 * which already exists. 00036 * 00037 * G_ask_in_mapset() requires the user to enter the name of a file 00038 * which exists in the current mapset 00039 * 00040 * G_ask_any() accepts any legal filename. Optionally warns user 00041 * if the file exists in the current mapset. 00042 * 00043 * G_ask_new_file() requires the user to enter the name of a new file. 00044 * 00045 * G_ask_old_file() requires the user to enter the name of any existing file. 00046 * 00047 * returns: 00048 * char * mapset where file was found, or 00049 * mapset where file is to be created 00050 * NULL user hit RETURN to cancel the request 00051 * 00052 * note: 00053 * These routines have a 'list' function built in. If a list -f 00054 * option is also desired, create a lister() routine, and 00055 * use G_ask_xxx_ext(). The lister() routine will be called as 00056 * follows: 00057 * 00058 * lister (name, mapset, buf) 00059 * 00060 * char *name name of file 00061 * char *mapset mapset to where file lives 00062 * char *buf buffer to hold description. 00063 * lister() should copy into buf. 00064 * buf will be large (about 400 bytes) 00065 * but only first 60 chars will be displayed 00066 * 00067 * 00068 * for each mapset, lister() will be called once with 00069 * name set to the empty string "" in order to get an title for the 00070 * list. Set buf to null to suppress title, otherwise copy title 00071 * into buf. The title will start above the text for the files. 00072 * 00073 * then for each file in each mapset, lister() will be called 00074 * to obtain infomation about the file. 00075 * 00076 * also: 00077 * G_set_ask_return_msg (msg) char *msg; 00078 * can be used to change the hit RETURN to cancel request message 00079 * displayed during the ask prompting. 00080 * 00081 * G_get_ask_return_msg() will return the msg. 00082 ******************************************************************/ 00083 #include <string.h> 00084 #include <stdlib.h> 00085 #include <unistd.h> 00086 #include <grass/gis.h> 00087 #include <grass/glocale.h> 00088 00089 /* 00090 * OLD references any mapset 00091 * NEW, ANY, PRJ are for the current mapset only 00092 * 00093 * OLD means must exist in some mapset 00094 * NEW means must not exist in current mapset 00095 * ANY means just get a name. If file exists, (optionally) warn user. 00096 * PRJ means must exist in current mapset 00097 */ 00098 00099 #define OLD 0 00100 #define NEW 1 00101 #define PRJ 2 00102 #define ANY 3 00103 #define ANY_NW 4 00104 #define OLD_FILE 5 00105 #define NEW_FILE 6 00106 00107 static char *ask_return_msg = 0; 00108 static char clear_return_msg = 0; 00109 static int (*no_lister) () = 0; 00110 static int parselist(const char *, int, char *); 00111 static char *ask(const char *, char *, char *, char *, char *, int (*)(), 00112 int); 00113 00114 00132 char *G_ask_new(const char *prompt, char *name, char *element, char *desc) 00133 { 00134 return ask(prompt, name, element, desc, (char *)NULL, no_lister, NEW); 00135 } 00136 00137 char *G_ask_new_ext(const char *prompt, char *name, char *element, char *desc, 00138 char *option, int (*lister) ()) 00139 { 00140 return ask(prompt, name, element, desc, option, lister, NEW); 00141 } 00142 00143 00161 char *G_ask_old(const char *prompt, char *name, char *element, char *desc) 00162 { 00163 return ask(prompt, name, element, desc, (char *)NULL, no_lister, OLD); 00164 } 00165 00166 char *G_ask_old_ext(const char *prompt, char *name, char *element, char *desc, 00167 char *option, int (*lister) ()) 00168 { 00169 return ask(prompt, name, element, desc, option, lister, OLD); 00170 } 00171 00172 00190 char *G_ask_any(const char *prompt, char *name, char *element, char *desc, 00191 int warn) 00192 { 00193 return ask(prompt, name, element, desc, (char *)NULL, no_lister, 00194 warn ? ANY : ANY_NW); 00195 } 00196 00197 char *G_ask_any_ext(const char *prompt, char *name, char *element, char *desc, 00198 int warn, char *option, int (*lister) ()) 00199 { 00200 return ask(prompt, name, element, desc, option, lister, 00201 warn ? ANY : ANY_NW); 00202 } 00203 00204 00222 char *G_ask_in_mapset(const char *prompt, char *name, char *element, 00223 char *desc) 00224 { 00225 return ask(prompt, name, element, desc, (char *)NULL, no_lister, PRJ); 00226 } 00227 00228 char *G_ask_in_mapset_ext(const char *prompt, char *name, char *element, 00229 char *desc, char *option, int (*lister) ()) 00230 { 00231 return ask(prompt, name, element, desc, option, lister, PRJ); 00232 } 00233 00234 00247 char *G_ask_new_file(const char *prompt, char *name, char *element, 00248 char *desc) 00249 { 00250 /* element is a dummy parameter for this function */ 00251 return ask(prompt, name, element, desc, (char *)NULL, no_lister, 00252 NEW_FILE); 00253 } 00254 00255 /* do we need this function? 00256 char * 00257 G_ask_new_file_ext (prompt, name, element, desc, option, lister) 00258 char *prompt; 00259 char *name; 00260 char *element; 00261 char *desc; 00262 char *option; 00263 int (*lister)(); 00264 { 00265 return ask (prompt, name, element, desc, option, lister, NEW_FILE); 00266 } 00267 */ 00268 00269 00282 char *G_ask_old_file(const char *prompt, char *name, char *element, 00283 char *desc) 00284 { 00285 /* element is a dummy parameter for this function */ 00286 return ask(prompt, name, element, desc, (char *)NULL, no_lister, 00287 OLD_FILE); 00288 } 00289 00290 /* do we need this function? 00291 char * 00292 G_ask_old_file_ext (prompt, name, element, desc, option, lister) 00293 char *prompt; 00294 char *name; 00295 char *element; 00296 char *desc; 00297 char *option; 00298 int (*lister)(); 00299 { 00300 return ask (prompt, name, element, desc, option, lister, OLD_FILE); 00301 } 00302 */ 00303 00304 00316 int G_set_ask_return_msg(const char *msg) 00317 { 00318 if (ask_return_msg) 00319 G_free(ask_return_msg); 00320 ask_return_msg = G_store(msg); 00321 clear_return_msg = 0; 00322 00323 return 0; 00324 } 00325 00326 00337 char *G_get_ask_return_msg() 00338 { 00339 static char none[80]; 00340 00341 strcpy(none, _("to cancel request")); 00342 return (ask_return_msg == NULL ? none : ask_return_msg); 00343 } 00344 00345 static char *ask(const char *prompt, 00346 char *name, 00347 char *element, 00348 char *desc, char *option, int (*lister) (), int type) 00349 { 00350 char tmapset[GMAPSET_MAX]; 00351 char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; 00352 int name_is_qualified; 00353 int ok; 00354 char tprompt[256]; 00355 char input[256]; 00356 char *mapset; 00357 char *cur_mapset; 00358 00359 G__check_gisinit(); 00360 00361 fflush(stdout); 00362 /* RETURN msg */ 00363 if (clear_return_msg) { 00364 G_free(ask_return_msg); 00365 ask_return_msg = 0; 00366 } 00367 clear_return_msg = ask_return_msg ? 1 : 0; 00368 00369 /* make sure option is valid */ 00370 if (lister && (option == 0 || *option == 0)) 00371 lister = 0; 00372 00373 /* set name to NO NAME at outset */ 00374 *name = 0; 00375 00376 /* 00377 * if element description not given, make it the same as the 00378 * element name 00379 */ 00380 if (desc == 0 || *desc == 0) 00381 desc = element; 00382 00383 /* 00384 * if no prompt is given, build an approriate prompt 00385 */ 00386 if (prompt == 0 || *prompt == 0) { 00387 switch (type) { 00388 case NEW: 00389 case NEW_FILE: 00390 sprintf(tprompt, _("Enter a new %s file name"), desc); 00391 prompt = tprompt; 00392 break; 00393 case OLD: 00394 case PRJ: 00395 case OLD_FILE: 00396 sprintf(tprompt, _("Enter the name of an existing %s file"), 00397 desc); 00398 prompt = tprompt; 00399 break; 00400 default: 00401 sprintf(tprompt, _("Enter %s file name"), desc); 00402 prompt = tprompt; 00403 break; 00404 } 00405 } 00406 00407 /* 00408 * get the current mapset name 00409 */ 00410 cur_mapset = G_mapset(); 00411 00412 while (1) { 00413 /* 00414 * print the prompt and input the request 00415 */ 00416 do { 00417 fprintf(stderr, "\n%s\n", prompt); 00418 /* no listing function implemented for old_file and new_file */ 00419 if (type != OLD_FILE && type != NEW_FILE) 00420 fprintf(stderr, 00421 _("Enter 'list' for a list of existing %s files\n"), 00422 desc); 00423 if (lister) { 00424 fprintf(stderr, _("Enter 'list -f' for ")); 00425 if (option && *option) 00426 fprintf(stderr, _("a list %s"), option); 00427 else 00428 fprintf(stderr, _("an extended list")); 00429 fprintf(stderr, "\n"); 00430 } 00431 00432 fprintf(stderr, _("Hit RETURN %s\n"), G_get_ask_return_msg()); 00433 fprintf(stderr, "> "); 00434 } 00435 while (!G_gets(input)); 00436 00437 G_strip(input); 00438 fprintf(stderr, "<%s>\n", input); 00439 00440 /* 00441 * if the user just hit return (or blanks only) 00442 * return NULL 00443 */ 00444 if (*input == 0) 00445 return 0; 00446 00447 if (type == OLD_FILE || type == NEW_FILE) { 00448 int exist; 00449 00450 exist = (access(input, 0) == 0); 00451 if (type == OLD_FILE && !exist) { 00452 fprintf(stderr, _("\n** %s - not found **\n"), input); 00453 continue; 00454 } 00455 if (type == NEW_FILE && exist) { 00456 char question[200]; 00457 00458 sprintf(question, 00459 _("\n** %s exists. ok to overwrite? "), input); 00460 if (!G_yes(question, 0)) 00461 continue; 00462 } 00463 strcpy(name, input); 00464 return G_store(input); 00465 } 00466 /* 00467 * 'list' does a list without extension. if we are looking for a new 00468 * file only list the current mapset. Otherwise list all mapsets 00469 * in the mapset search list 00470 * 00471 * 0 not a list request 00472 * 1 list 00473 * 2 list -f 00474 * 3 list mapset 00475 * 4 list -f mapset 00476 */ 00477 00478 switch (parselist(input, lister ? 1 : 0, tmapset)) { 00479 case 0: 00480 break; 00481 case 1: 00482 G_list_element(element, desc, type == OLD ? "" : cur_mapset, 00483 no_lister); 00484 continue; 00485 case 2: 00486 G_list_element(element, desc, type == OLD ? "" : cur_mapset, 00487 lister); 00488 continue; 00489 case 3: 00490 G_list_element(element, desc, tmapset, no_lister); 00491 continue; 00492 case 4: 00493 G_list_element(element, desc, tmapset, lister); 00494 continue; 00495 default: 00496 fprintf(stderr, "** illegal request **\n"); 00497 continue; 00498 } 00499 00500 if ((name_is_qualified = 00501 G__name_is_fully_qualified(input, xname, xmapset))) 00502 ok = G_legal_filename(xname) >= 0; 00503 else 00504 ok = G_legal_filename(input) >= 0; 00505 if (!ok) { 00506 fprintf(stderr, _("\n**<%s> illegal name **\n"), input); 00507 continue; 00508 } 00509 /* 00510 * now look for the file. 00511 * 00512 * new files must be simple names 00513 * and must not exist in the current mapset 00514 */ 00515 if (type != OLD) { 00516 if (name_is_qualified) { 00517 if (strcmp(cur_mapset, xmapset) != 0) { 00518 fprintf(stderr, _("\n** %s - illegal request **\n"), 00519 input); 00520 continue; 00521 } 00522 strcpy(input, xname); 00523 } 00524 mapset = G_find_file(element, input, cur_mapset); 00525 switch (type) { 00526 case NEW: 00527 00528 if (!mapset) { 00529 strcpy(name, input); 00530 return cur_mapset; 00531 } 00532 fprintf(stderr, 00533 _("\n** %s - exists, select another name **\n"), 00534 input); 00535 break; 00536 00537 case ANY: 00538 case ANY_NW: 00539 00540 if (mapset && type == ANY) { 00541 char question[200]; 00542 00543 sprintf(question, 00544 _("\n** %s exists. ok to overwrite? "), input); 00545 if (!G_yes(question, 0)) 00546 break; 00547 } 00548 strcpy(name, input); 00549 return cur_mapset; 00550 00551 case PRJ: 00552 00553 if (mapset) { 00554 strcpy(name, input); 00555 return cur_mapset; 00556 } 00557 fprintf(stderr, _("\n** %s - not found **\n"), input); 00558 break; 00559 00560 default: 00561 G_fatal_error(_("ask: can't happen")); 00562 } 00563 } 00564 /* 00565 * old names can be simple or qualified 00566 * and must exist 00567 */ 00568 else { 00569 mapset = G_find_file(element, input, ""); 00570 if (mapset) { 00571 if (name_is_qualified) 00572 strcpy(name, xname); 00573 else 00574 strcpy(name, input); 00575 return mapset; 00576 } 00577 fprintf(stderr, _("\n** %s - not found **\n"), input); 00578 } 00579 } 00580 00581 return NULL; 00582 } 00583 00584 static int parselist(const char *input, int option, char *mapset) 00585 { 00586 char list[GNAME_MAX]; 00587 char f1[GMAPSET_MAX]; 00588 char f2[GMAPSET_MAX]; 00589 char f3[GMAPSET_MAX]; 00590 int count; 00591 00592 *list = *f1 = *f2 = 0; 00593 count = sscanf(input, "%s%s%s%s", list, f1, f2, f3); 00594 if (count < 1) 00595 return 0; 00596 if (strcmp(list, "list") != 0) 00597 return 0; 00598 00599 if (count == 1) 00600 return 1; /* list */ 00601 if (count > 3) 00602 return -1; /* illegal */ 00603 00604 if (*f1 == '-') { /* list -f */ 00605 if (!option) 00606 return -1; 00607 if (f1[1] == 0 || f1[1] != 'f' || f1[2] != 0) 00608 return -1; 00609 if (count == 2) 00610 return 2; 00611 strcpy(mapset, f2); 00612 return 4; 00613 } 00614 if (count != 2) 00615 return -1; 00616 strcpy(mapset, f1); 00617 return 3; 00618 }