/**************************************************************** * These routines prompt the user for names of GIS data files * * G_ask_new (prompt, name, element, desc) * G_ask_old (prompt, name, element, desc) * G_ask_any (prompt, name, element, desc, warn) * G_ask_in_mapset (prompt, name, element, desc) * G_ask_new_file (prompt, name, element, desc) * G_ask_old_file (prompt, name, element, desc) * * G_ask_new_ext (prompt, name, element, desc, option, lister) * G_ask_old_ext (prompt, name, element, desc, option, lister) * G_ask_any_ext (prompt, name, element, desc, warn, option, lister) * G_ask_in_mapset_ext (prompt, name, element, desc, option, lister) * * char *prompt prompt to be printed. can be "" in which * case an appropriate prompt will be printed. * char *name buffer to hold the name input by the user * char *element GIS data element - "cell", "vect", etc. * char *desc a description of element. Used for prompting * and listing. Will be set to element if given as "" * (eg, if element is "vect", set desc = "vector") * char *option list option. a description of the option. * (eg, "with utms" will prompt as follows: * list -f for a list with utms) * int (*lister)() subroutine to return text for -f option. * * * G_ask_new() requires the user to enter the name of a file * which does not exist in the current mapset * (but which may exist in other mapsets). * * G_ask_old() requires the user to enter the name of a file * which already exists. * * G_ask_in_mapset() requires the user to enter the name of a file * which exists in the current mapset * * G_ask_any() accepts any legal filename. Optionally warns user * if the file exists in the current mapset. * * G_ask_new_file() requires the user to enter the name of a new file. * * G_ask_old_file() requires the user to enter the name of any existing file. * * returns: * char * mapset where file was found, or * mapset where file is to be created * NULL user hit RETURN to cancel the request * * note: * These routines have a 'list' function built in. If a list -f * option is also desired, create a lister() routine, and * use G_ask_xxx_ext(). The lister() routine will be called as * follows: * * lister (name, mapset, buf) * * char *name name of file * char *mapset mapset to where file lives * char *buf buffer to hold description. * lister() should copy into buf. * buf will be large (about 400 bytes) * but only first 60 chars will be displayed * * * for each mapset, lister() will be called once with * name set to the empty string "" in order to get an title for the * list. Set buf to null to suppress title, otherwise copy title * into buf. The title will start above the text for the files. * * then for each file in each mapset, lister() will be called * to obtain infomation about the file. * * also: * G_set_ask_return_msg (msg) char *msg; * can be used to change the hit RETURN to cancel request message * displayed during the ask prompting. * * G_get_ask_return_msg() will return the msg. ******************************************************************/ #include #include #include #include #include /* * OLD references any mapset * NEW, ANY, PRJ are for the current mapset only * * OLD means must exist in some mapset * NEW means must not exist in current mapset * ANY means just get a name. If file exists, (optionally) warn user. * PRJ means must exist in current mapset */ #define OLD 0 #define NEW 1 #define PRJ 2 #define ANY 3 #define ANY_NW 4 #define OLD_FILE 5 #define NEW_FILE 6 static char *ask_return_msg = 0; static char clear_return_msg = 0; static int (*no_lister) () = 0; static int parselist(const char *, int, char *); static char *ask(const char *, char *, char *, char *, char *, int (*)(), int); /*! * \brief prompt for new database file * * The user is asked to enter the name of * a new file which does not exist in the current mapset. * Note. The file chosen by the user may exist in other mapsets. This * routine does not look in other mapsets, since the assumption is that * name will be used to create a new file. New files are always created * in the current mapset. * * \param prompt * \param name * \param element * \param desc * \return char * */ char *G_ask_new(const char *prompt, char *name, char *element, char *desc) { return ask(prompt, name, element, desc, (char *)NULL, no_lister, NEW); } char *G_ask_new_ext(const char *prompt, char *name, char *element, char *desc, char *option, int (*lister) ()) { return ask(prompt, name, element, desc, option, lister, NEW); } /*! * \brief prompt for existing database file * * The user is asked to enter the * name of an existing database file. * Note. This routine looks for the file in the current mapset as well * as other mapsets. The mapsets that are searched are determined from the user's * mapset search path. See Mapset_Search_Path for some more details * about the search path. * * \param prompt * \param name * \param element * \param label * \return char * */ char *G_ask_old(const char *prompt, char *name, char *element, char *desc) { return ask(prompt, name, element, desc, (char *)NULL, no_lister, OLD); } char *G_ask_old_ext(const char *prompt, char *name, char *element, char *desc, char *option, int (*lister) ()) { return ask(prompt, name, element, desc, option, lister, OLD); } /*! * \brief prompt for any valid file name * * The user is asked to enter * any leg al file name. If warn is 1 and the file chosen exists in the * current mapset, then the user is asked if it is ok to overwrite the file. If * warn is 0, then any leg al name is accepted and no warning is issued * to the user if the file exists. * * \param prompt * \param name * \param element * \param label * \param warn * \return char * */ char *G_ask_any(const char *prompt, char *name, char *element, char *desc, int warn) { return ask(prompt, name, element, desc, (char *)NULL, no_lister, warn ? ANY : ANY_NW); } char *G_ask_any_ext(const char *prompt, char *name, char *element, char *desc, int warn, char *option, int (*lister) ()) { return ask(prompt, name, element, desc, option, lister, warn ? ANY : ANY_NW); } /*! * \brief prompt for existing database file * * The user is asked to enter the * name of an file which exists in the current mapset. * Note. The file chosen by the user may or may not exist in other * mapsets. This routine does not look in other mapsets, since the assumption is * that name will be used to modify a file. GRASS only permits users to * modify files in the current mapset. * * \param prompt * \param name * \param element * \param label * \return char * */ char *G_ask_in_mapset(const char *prompt, char *name, char *element, char *desc) { return ask(prompt, name, element, desc, (char *)NULL, no_lister, PRJ); } char *G_ask_in_mapset_ext(const char *prompt, char *name, char *element, char *desc, char *option, int (*lister) ()) { return ask(prompt, name, element, desc, option, lister, PRJ); } /*! * \brief prompt for new file * * The user is asked to enter the name of an file which doesn't exist. * * \param prompt * \param name * \param element * \param label * \return char * */ char *G_ask_new_file(const char *prompt, char *name, char *element, char *desc) { /* element is a dummy parameter for this function */ return ask(prompt, name, element, desc, (char *)NULL, no_lister, NEW_FILE); } /* do we need this function? char * G_ask_new_file_ext (prompt, name, element, desc, option, lister) char *prompt; char *name; char *element; char *desc; char *option; int (*lister)(); { return ask (prompt, name, element, desc, option, lister, NEW_FILE); } */ /*! * \brief prompt for existing file * * The user is asked to enter the name of an file which exists. * * \param prompt * \param name * \param element * \param label * \return char * */ char *G_ask_old_file(const char *prompt, char *name, char *element, char *desc) { /* element is a dummy parameter for this function */ return ask(prompt, name, element, desc, (char *)NULL, no_lister, OLD_FILE); } /* do we need this function? char * G_ask_old_file_ext (prompt, name, element, desc, option, lister) char *prompt; char *name; char *element; char *desc; char *option; int (*lister)(); { return ask (prompt, name, element, desc, option, lister, OLD_FILE); } */ /*! * \brief set Hit RETURN msg * * The "Hit * RETURN to cancel request" part of the prompt in the prompting routines * described above, is modified to "Hit RETURN msg." * * \param msg * \return int */ int G_set_ask_return_msg(const char *msg) { if (ask_return_msg) G_free(ask_return_msg); ask_return_msg = G_store(msg); clear_return_msg = 0; return 0; } /*! * \brief get Hit RETURN msg * * The current * msg (as set by G_set_ask_return_msg) is returned. * * \param void * \return char * */ char *G_get_ask_return_msg() { static char none[80]; strcpy(none, _("to cancel request")); return (ask_return_msg == NULL ? none : ask_return_msg); } static char *ask(const char *prompt, char *name, char *element, char *desc, char *option, int (*lister) (), int type) { char tmapset[GMAPSET_MAX]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; int name_is_qualified; int ok; char tprompt[256]; char input[256]; char *mapset; char *cur_mapset; G__check_gisinit(); fflush(stdout); /* RETURN msg */ if (clear_return_msg) { G_free(ask_return_msg); ask_return_msg = 0; } clear_return_msg = ask_return_msg ? 1 : 0; /* make sure option is valid */ if (lister && (option == 0 || *option == 0)) lister = 0; /* set name to NO NAME at outset */ *name = 0; /* * if element description not given, make it the same as the * element name */ if (desc == 0 || *desc == 0) desc = element; /* * if no prompt is given, build an approriate prompt */ if (prompt == 0 || *prompt == 0) { switch (type) { case NEW: case NEW_FILE: sprintf(tprompt, _("Enter a new %s file name"), desc); prompt = tprompt; break; case OLD: case PRJ: case OLD_FILE: sprintf(tprompt, _("Enter the name of an existing %s file"), desc); prompt = tprompt; break; default: sprintf(tprompt, _("Enter %s file name"), desc); prompt = tprompt; break; } } /* * get the current mapset name */ cur_mapset = G_mapset(); while (1) { /* * print the prompt and input the request */ do { fprintf(stderr, "\n%s\n", prompt); /* no listing function implemented for old_file and new_file */ if (type != OLD_FILE && type != NEW_FILE) fprintf(stderr, _("Enter 'list' for a list of existing %s files\n"), desc); if (lister) { fprintf(stderr, _("Enter 'list -f' for ")); if (option && *option) fprintf(stderr, _("a list %s"), option); else fprintf(stderr, _("an extended list")); fprintf(stderr, "\n"); } fprintf(stderr, _("Hit RETURN %s\n"), G_get_ask_return_msg()); fprintf(stderr, "> "); } while (!G_gets(input)); G_strip(input); fprintf(stderr, "<%s>\n", input); /* * if the user just hit return (or blanks only) * return NULL */ if (*input == 0) return 0; if (type == OLD_FILE || type == NEW_FILE) { int exist; exist = (access(input, 0) == 0); if (type == OLD_FILE && !exist) { fprintf(stderr, _("\n** %s - not found **\n"), input); continue; } if (type == NEW_FILE && exist) { char question[200]; sprintf(question, _("\n** %s exists. ok to overwrite? "), input); if (!G_yes(question, 0)) continue; } strcpy(name, input); return G_store(input); } /* * 'list' does a list without extension. if we are looking for a new * file only list the current mapset. Otherwise list all mapsets * in the mapset search list * * 0 not a list request * 1 list * 2 list -f * 3 list mapset * 4 list -f mapset */ switch (parselist(input, lister ? 1 : 0, tmapset)) { case 0: break; case 1: G_list_element(element, desc, type == OLD ? "" : cur_mapset, no_lister); continue; case 2: G_list_element(element, desc, type == OLD ? "" : cur_mapset, lister); continue; case 3: G_list_element(element, desc, tmapset, no_lister); continue; case 4: G_list_element(element, desc, tmapset, lister); continue; default: fprintf(stderr, "** illegal request **\n"); continue; } if ((name_is_qualified = G__name_is_fully_qualified(input, xname, xmapset))) ok = G_legal_filename(xname) >= 0; else ok = G_legal_filename(input) >= 0; if (!ok) { fprintf(stderr, _("\n**<%s> illegal name **\n"), input); continue; } /* * now look for the file. * * new files must be simple names * and must not exist in the current mapset */ if (type != OLD) { if (name_is_qualified) { if (strcmp(cur_mapset, xmapset) != 0) { fprintf(stderr, _("\n** %s - illegal request **\n"), input); continue; } strcpy(input, xname); } mapset = G_find_file(element, input, cur_mapset); switch (type) { case NEW: if (!mapset) { strcpy(name, input); return cur_mapset; } fprintf(stderr, _("\n** %s - exists, select another name **\n"), input); break; case ANY: case ANY_NW: if (mapset && type == ANY) { char question[200]; sprintf(question, _("\n** %s exists. ok to overwrite? "), input); if (!G_yes(question, 0)) break; } strcpy(name, input); return cur_mapset; case PRJ: if (mapset) { strcpy(name, input); return cur_mapset; } fprintf(stderr, _("\n** %s - not found **\n"), input); break; default: G_fatal_error(_("ask: can't happen")); } } /* * old names can be simple or qualified * and must exist */ else { mapset = G_find_file(element, input, ""); if (mapset) { if (name_is_qualified) strcpy(name, xname); else strcpy(name, input); return mapset; } fprintf(stderr, _("\n** %s - not found **\n"), input); } } return NULL; } static int parselist(const char *input, int option, char *mapset) { char list[GNAME_MAX]; char f1[GMAPSET_MAX]; char f2[GMAPSET_MAX]; char f3[GMAPSET_MAX]; int count; *list = *f1 = *f2 = 0; count = sscanf(input, "%s%s%s%s", list, f1, f2, f3); if (count < 1) return 0; if (strcmp(list, "list") != 0) return 0; if (count == 1) return 1; /* list */ if (count > 3) return -1; /* illegal */ if (*f1 == '-') { /* list -f */ if (!option) return -1; if (f1[1] == 0 || f1[1] != 'f' || f1[2] != 0) return -1; if (count == 2) return 2; strcpy(mapset, f2); return 4; } if (count != 2) return -1; strcpy(mapset, f1); return 3; }