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