123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- /****************************************************************
- * 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 <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- /*
- * 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.
- * <b>Note.</b> The file chosen by the user may exist in other mapsets. This
- * routine does not look in other mapsets, since the assumption is that
- * <b>name</b> 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.
- * <b>Note.</b> 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 <b>warn</b> 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
- * <b>warn</b> 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.
- * <b>Note.</b> 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 <b>name</b> 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 <b>msg.</b>"
- *
- * \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
- * <i>msg</i> (as set by <i>G_set_ask_return_msg</i>) 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;
- }
|