frefid_t glk_fileref_create_by_path(glui32 usage, const char *path, glui32 rock) { fileref_t *fref = gli_new_fileref(path, usage, rock); if (!fref) gli_strict_warning("fileref_create_by_name: unable to create fileref."); return fref; }
frefid_t glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) { fileref_t *fref; char buf[256]; int val, filter; char *prompt; strcpy(buf, ""); switch (usage & fileusage_TypeMask) { case fileusage_SavedGame: prompt = "Saved game"; filter = FILTER_SAVE; break; case fileusage_Transcript: prompt = "Transcript file"; filter = FILTER_TEXT; break; case fileusage_InputRecord: prompt = "Command record file"; filter = FILTER_TEXT; break; case fileusage_Data: default: prompt = "Data file"; filter = FILTER_ALL; break; } if (fmode == filemode_Read) winopenfile(prompt, buf, sizeof buf, filter); else winsavefile(prompt, buf, sizeof buf, filter); val = strlen(buf); if (!val) { /* The player just hit return. It would be nice to provide a default value, but this implementation is too cheap. */ return NULL; } fref = gli_new_fileref(buf, usage, rock); if (!fref) { gli_strict_warning("fileref_create_by_prompt: unable to create fileref."); return NULL; } return fref; }
frefid_t glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) { fileref_t *fref; char buf[BUFLEN]; char buf2[2*BUFLEN+10]; int len; char *cx; char *suffix; /* The new spec recommendations: delete all characters in the string "/\<>:|?*" (including quotes). Truncate at the first period. Change to "null" if there's nothing left. Then append an appropriate suffix: ".glkdata", ".glksave", ".txt". */ for (cx=name, len=0; (*cx && *cx!='.' && len<BUFLEN-1); cx++) { switch (*cx) { case '"': case '\\': case '/': case '>': case '<': case ':': case '|': case '?': case '*': break; default: buf[len++] = *cx; } } buf[len] = '\0'; if (len == 0) { strcpy(buf, "null"); len = strlen(buf); } suffix = gli_suffix_for_usage(usage); sprintf(buf2, "%s/%s%s", workingdir, buf, suffix); fref = gli_new_fileref(buf2, usage, rock); if (!fref) { gli_strict_warning(L"fileref_create_by_name: unable to create fileref."); return NULL; } return fref; }
frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock) { fileref_t *fref; char buf[256]; char buf2[256]; int len; char *cx; len = strlen(name); if (len > 255) len = 255; /* Take out all dangerous characters, and make sure the length is greater than zero. The overall goal is to make a legal platform-native filename, without any extra directory components. Suffixes are another sore point. Really, the game program shouldn't have a suffix on the name passed to this function. So in DOS/Windows, this function should chop off dot-and-suffix, if there is one, and then add a dot and a three-letter suffix appropriate to the file type (as gleaned from the usage argument.) */ memcpy(buf, name, len); if (len == 0) { buf[0] = 'X'; len++; } buf[len] = '\0'; for (cx=buf; *cx; cx++) { if (*cx == '/' || *cx == '\\' || *cx == ':') *cx = '-'; } sprintf(buf2, "%s/%s", gli_workdir, buf); fref = gli_new_fileref(buf2, usage, rock); if (!fref) { gli_strict_warning("fileref_create_by_name: unable to create fileref."); return NULL; } return fref; }
frefid_t glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) { fileref_t *fref; char buf[256]; char buf2[256]; int len; char *cx; len = strlen(name); if (len > 255) len = 255; /* Take out all '/' characters, and make sure the length is greater than zero. Again, this is the right behavior in Unix. DOS/Windows might want to take out '\' instead, unless the stdio library converts slashes for you. They'd also want to trim to 8 characters. Remember, the overall goal is to make a legal platform-native filename, without any extra directory components. Suffixes are another sore point. Really, the game program shouldn't have a suffix on the name passed to this function. So in DOS/Windows, this function should chop off dot-and-suffix, if there is one, and then add a dot and a three-letter suffix appropriate to the file type (as gleaned from the usage argument.) */ memcpy(buf, name, len); if (len == 0) { buf[0] = 'X'; len++; } buf[len] = '\0'; for (cx=buf; *cx; cx++) { if (*cx == '/') *cx = '-'; } sprintf(buf2, "%s/%s", workingdir, buf); fref = gli_new_fileref(buf2, usage, rock); if (!fref) { gli_strict_warning("fileref_create_by_name: unable to create fileref."); return 0; } return fref; }
frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock) { char *filename; fileref_t *fref; char *tempdir = getenv("TEMP"); if (tempdir == NULL) tempdir = "."; filename = tempnam(tempdir, "gargtmp"); fref = gli_new_fileref(filename, usage, rock); if (!fref) { gli_strict_warning("fileref_create_temp: unable to create fileref."); return NULL; } return fref; }
frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t oldfref, glui32 rock) { fileref_t *fref; if (!oldfref) { gli_strict_warning(L"fileref_create_from_fileref: invalid ref"); return NULL; } fref = gli_new_fileref(oldfref->filename, usage, rock); if (!fref) { gli_strict_warning(L"fileref_create_from_fileref: unable to create fileref."); return NULL; } return fref; }
frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock) { char *filename; fileref_t *fref; /* This is a pretty good way to do this on Unix systems. I have no idea about the DOS/Windows world. */ filename = tmpnam(NULL); fref = gli_new_fileref(filename, usage, rock); if (!fref) { gli_strict_warning("fileref_create_temp: unable to create fileref."); return 0; } return fref; }
frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock) { char *filename; fileref_t *fref; /* This is a pretty good way to do this on Unix systems. On Macs, it's pretty bad, but this library won't be used much on the Mac -- I hope. I have no idea about the DOS/Windows world. */ filename = tmpnam(NULL); fref = gli_new_fileref(filename, usage, rock); if (!fref) { gli_strict_warning("fileref_create_temp: unable to create fileref."); return NULL; } return fref; }
frefid_t glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) { fileref_t *fref; // struct stat sbuf; char buf[BUFLEN], newbuf[BUFLEN]; char *cx; int ix, val; char *prompt, *prompt2, *lastbuf; int ipflag = FILE_RESTORE; switch (usage & fileusage_TypeMask) { case fileusage_SavedGame: prompt = "Enter saved game"; ipflag = fmode == filemode_Read ? FILE_RESTORE : FILE_SAVE; lastbuf = lastsavename; break; case fileusage_Transcript: prompt = "Enter transcript file"; ipflag = FILE_SCRIPT; lastbuf = lastscriptname; break; case fileusage_InputRecord: prompt = "Enter command record file"; ipflag = fmode == filemode_Read ? FILE_PLAYBACK : FILE_RECORD; lastbuf = lastcmdname; break; case fileusage_Data: default: prompt = "Enter data file"; ipflag = fmode == filemode_Read ? FILE_LOAD_AUX : FILE_SAVE_AUX; lastbuf = lastdataname; break; } if (fmode == filemode_Read) prompt2 = "to load"; else prompt2 = "to store"; sprintf(newbuf, "%s %s: ", prompt, prompt2); ix = iosif_prompt_file_name(buf, "", ipflag); if (!ix) { /* The player cancelled input. */ return NULL; } val = strlen(buf); while (val && (buf[val-1] == '\n' || buf[val-1] == '\r' || buf[val-1] == ' ')) val--; buf[val] = '\0'; for (cx = buf; *cx == ' '; cx++) { } val = strlen(cx); if (!val) { /* The player just hit return. */ return NULL; } if (cx[0] == '/') { strcpy(newbuf, cx); cx = newbuf; } else { if (strlen(workingdir) + 1 + strlen(cx) >= BUFLEN) { gli_strict_warning(L"fileref_create_by_name: filename too long."); return NULL; } sprintf(newbuf, "%s/%s", workingdir, cx); cx = newbuf + strlen(workingdir) + 1; } strcpy(lastbuf, cx); fref = gli_new_fileref(newbuf, usage, rock); if (!fref) { gli_strict_warning(L"fileref_create_by_prompt: unable to create fileref."); return NULL; } return fref; }
static glsi32 classes_restore(glk_object_save_t *objects, glui32 objects_count, int versionNum) { glk_object_save_t *cur; int found; classtable_t *ctab; classref_t *cref, *cref_id; int i, j; window_t *win = NULL, *splitwin = NULL; struct glk_window_autosave *foundwin = NULL; stream_t *str = NULL; struct glk_stream_autosave *foundstr = NULL; glui32 id; int winct = 0, winct2 = 0; t_winid winid[kMaxGlkViews]; stream_t *cur_str = NULL; char errbuf[256]; for (i = 0; i < kMaxGlkViews; i++) { winid[i].win = NULL; winid[i].id = 0; } int winLastId = classes[gidisp_Class_Window]->lastid; for (i = 0; i < objects_count; i++) { cur = objects + i; if (cur->type == gidisp_Class_Window && cur->id+1 > winLastId) winLastId = cur->id+1; } classes[gidisp_Class_Window]->lastid = winLastId; // make sure ids of new windows don't overlap orig ids for (i = 0; i < objects_count; i++) { found = FALSE; // windows come first, in the correct order, alternated with their streams/hints cur = objects + i; // don't bother iterating through current - there are none at autoload if (cur->type == gidisp_Class_Window) { winct++; foundwin = &cur->obj.win; classes_denormalize_pointers(gidisp_Class_Window, foundwin); winid[winct-1].id = cur->id; // fill this in for a pair, too if (foundwin->type != wintype_Pair) { splitwin = NULL; if (foundwin->splitwin != kInvalidSplitWin) { // this had no splitwin going in for (j = 0; j < kMaxGlkViews; j++) { if (winid[j].id == foundwin->splitwin) { splitwin = winid[j].win; break; } } } win = (window_t *)glk_window_open(splitwin, foundwin->method, foundwin->size, foundwin->type, foundwin->rock); if (!win) { sprintf(errbuf, "\nCould not create %s window with id %ld. Aborting restore.\n", foundwin->type == wintype_TextBuffer ? "textbuffer" : foundwin->type == wintype_TextGrid ? "textgrid" : foundwin->type == wintype_Blank ? "blank" : "graphics", (long)cur->id); iosif_win_puts(0, errbuf); return FALSE; } winid[winct-1].win = win; // check id, set id if necessary id = classes_find_id_for_object(gidisp_Class_Window, win); if (id != cur->id) { cref_id = classes_pop_cref(gidisp_Class_Window, id); cref_id->id = cur->id; // auto-awarding should ensure that an id has not been reused classes_push_cref(gidisp_Class_Window, cref_id); } if (versionNum == FrotzGlkClassChunkVersionNumV1) { win->line_request = foundwin->requ.v1.line_request; win->char_request = foundwin->requ.v1.char_request; win->line_request_uni = foundwin->requ.v1.line_request_uni; win->char_request_uni = foundwin->requ.v1.char_request_uni; } else { int req = foundwin->requ.v2.reqFlags; win->line_request = (req & kGlkReqLine) != 0; win->line_request_uni = (req & kGlkReqLineUni) != 0; win->char_request = (req & kGlkReqChar) != 0; win->mouse_request = (req & kGlkReqMouse) != 0; win->hyper_request = (req & kGlkReqHyper) != 0; win->echo_line_input = (req & kGlkReqNoEchoLine) == 0; if (win->type == wintype_TextBuffer) { window_textbuffer_t *wtb = (window_textbuffer_t*)win->data; wtb->inecho = win->echo_line_input; } if (win->mouse_request && (win->type == wintype_Graphics || win->type == wintype_TextGrid)) iosif_enable_tap(win->iosif_glkViewNum); if (win->hyper_request && (win->type == wintype_TextGrid || win->type == wintype_TextBuffer)) iosif_enable_tap(win->iosif_glkViewNum); } if (foundwin->inbuf) { window_textbuffer_t *wtb = (window_textbuffer_t*)win->data; wtb->inbuf = foundwin->inbuf; wtb->inmax = foundwin->inmax; } found = TRUE; } if (found && (win->type == wintype_TextBuffer || win->type == wintype_TextGrid)) { // read STREAM chunk i++; cur = objects + i; if (cur->type != gidisp_Class_Stream) { sprintf(errbuf, "\nUnexpected window stream type %d. Aborting restore.\n", cur->type); iosif_win_puts(0, errbuf); return FALSE; } else { foundstr = &cur->obj.str; str = win->str; id = classes_find_id_for_object(gidisp_Class_Stream, str); if (id != cur->id) { cref_id = classes_pop_cref(gidisp_Class_Stream, id); cref_id->id = cur->id; // auto-awarding should verify that an id has not been reused classes_push_cref(gidisp_Class_Stream, cref_id); } classes_denormalize_pointers(gidisp_Class_Stream, foundstr); str->rock = foundstr->rock; str->readcount = foundstr->readcount; str->writecount = foundstr->writecount; str->readable = foundstr->readable; str->writable = foundstr->writable; if (!str->buf && foundstr->buf) { str->buf = foundstr->buf; str->bufptr = foundstr->bufptr; str->bufend = foundstr->bufend; str->bufeof = foundstr->bufeof; str->buflen = foundstr->buflen; } if (cur->iscurrent) { cur_str = str; } } // read STYLE chunk i++; cur = objects + i; if (cur->type != type_Style) { sprintf(errbuf, "\nUnexpected stream type %d. Aborting restore.\n", cur->type); iosif_win_puts(0, errbuf); return FALSE; } else { gli_window_set_stylehints(win, (GLK_STYLE_HINTS *)&cur->obj.style); } iosif_set_glk_default_colors(win->iosif_glkViewNum); } else if (found && win->type == wintype_Graphics) { if (i+1 < objects_count && objects[i+1].type == type_Graphics) { i++; cur = objects + i; window_graphics_t *wgp = (window_graphics_t*)win->data; wgp->width = cur->obj.gfx.width; wgp->height = cur->obj.gfx.height; wgp->backcolor = cur->obj.gfx.backcolor; iosif_set_background_color(win->iosif_glkViewNum, wgp->backcolor); iosif_restore_glk_win_graphics_img(wingfxcount++, win->iosif_glkViewNum); } } else if (found && win->type == wintype_Pair) { // this will never happen i++; } } else if (cur->type == gidisp_Class_Stream) { break; } else if (cur->type == type_Pair) { struct glk_winpair_autosave *pairwin = &cur->obj.pair; // find the children; if they exist, make sure that this window is registered under the correct id glui32 id1 = (glui32)pairwin->child1; glui32 id2 = (glui32)pairwin->child2; window_t *win1 = NULL; window_t *win2 = NULL; for (j = 0; j < kMaxGlkViews; j++) { if (winid[j].id == id1) { win1 = winid[j].win; } else if (winid[j].id == id2) { win2 = winid[j].win; } if (win1 && win2) break; } if (win1 && win2) { // we found it // check id, set id if necessary id = classes_find_id_for_object(gidisp_Class_Window, win1->parent); // get the parent if (id != cur->id) { cref_id = classes_pop_cref(gidisp_Class_Window, id); cref_id->id = cur->id; // auto-awarding should ensure that an id has not been reused classes_push_cref(gidisp_Class_Window, cref_id); } // enter window in the window id list, so other windows can find it, too, if it's being used as a splitwin for (j = 0; j < kMaxGlkViews; j++) { if (winid[j].id == cur->id) { winid[j].win = win1->parent; break; } } } } else if (cur->type == gidisp_Class_Fileref) ; } // verify window count if ((ctab = classes[gidisp_Class_Window])) { for (j = 0; j < CLASSHASH_SIZE; j++) { cref = ctab->bucket[j]; for ( ; cref; cref = cref->next) { winct2++; } } } if (winct != winct2) { sprintf(errbuf, "\n[Autorestore warning: window count mismatch %d!=%d]\n", winct, winct2); iosif_win_puts(0, errbuf); } // freakin' great, so let's re-iterate, simultaneously doing an iteration and compare // start over, verify all window ids, including pairs win = NULL; for (i = 0; i < objects_count; i++) { // windows come first, in the correct order, alternated with their streams cur = objects + i; if (cur->type == gidisp_Class_Window) { foundwin = &cur->obj.win; win = gli_window_iterate_backward(win, NULL); if (win->type == foundwin->type) { win->rock = foundwin->rock; id = classes_find_id_for_object(gidisp_Class_Window, win); if (id != cur->id) { cref_id = classes_pop_cref(gidisp_Class_Window, id); cref_id->id = cur->id; // auto-awarding should verify that an id has not been reused classes_push_cref(gidisp_Class_Window, cref_id); } //break; // This incorrect break was in cellardoor impl -- } else { iosif_win_puts(0, "\nCould not restore saved state. Sorry. Aborting restore.\n"); return FALSE; } // restore RECT win->bbox = foundwin->bbox; if (win->type == wintype_TextBuffer || win->type == wintype_TextGrid) { // read STREAM chunk i++; cur = objects + i; if (cur->type != gidisp_Class_Stream) { iosif_win_puts(0, "\nMissing stream. Aborting restore.\n"); return FALSE; } else { foundstr = &cur->obj.str; str = win->str; str->rock = foundstr->rock; id = classes_find_id_for_object(gidisp_Class_Stream, str); if (id != cur->id) { cref_id = classes_pop_cref(gidisp_Class_Stream, id); cref_id->id = cur->id; // auto-awarding should verify that an id has not been reused classes_push_cref(gidisp_Class_Stream, cref_id); } } // read STYLE chunk i++; cur = objects + i; if (cur->type != type_Style) { // style chunk is not where it should be iosif_win_puts(0, "\nMissing style chunk. Aborting restore.\n"); return FALSE; } } else if (win->type == wintype_Pair) { // read PAIR chunk i++; cur = objects + i; if (cur->type != type_Pair) { iosif_win_puts(0, "\nCorrupt win pair. Aborting restore.\n"); return FALSE; } else { struct glk_winpair_autosave *foundpair = &cur->obj.pair; window_pair_t *pair = (window_pair_t *)win->data; pair->splitpos = foundpair->splitpos; pair->splitwidth = foundpair->splitwidth; pair->dir = foundpair->dir; pair->vertical = foundpair->vertical; pair->backward = foundpair->backward; pair->size = foundpair->size; } } } else if (cur->type == gidisp_Class_Stream) { // now do the streams #if 0 // this doesn't work and seems to corrupt autorestore, e.g. Counterfeit Monkey stream_t *tempstr; found = FALSE; foundstr = &cur->obj.str; if ((ctab = classes[gidisp_Class_Stream])) { for (j = 0; j < CLASSHASH_SIZE; j++) { cref = ctab->bucket[j]; for ( ; cref; cref = cref->next) { tempstr = (stream_t *)cref->obj; if (tempstr->type == foundstr->type && tempstr->rock == foundstr->rock) { // this id should be clearer id = classes_find_id_for_object(gidisp_Class_Stream, tempstr); if (id != cur->id) { cref_id = classes_pop_cref(gidisp_Class_Stream, id); cref_id->id = cur->id; // auto-awarding should verify that an id has not been reused classes_push_cref(gidisp_Class_Stream, cref_id); } classes_denormalize_pointers(gidisp_Class_Stream, foundstr); tempstr->rock = foundstr->rock; if (tempstr->type != strtype_File && !tempstr->buf && foundstr->buf) { tempstr->readcount = foundstr->readcount; tempstr->writecount = foundstr->writecount; tempstr->readable = foundstr->readable; tempstr->writable = foundstr->writable; tempstr->buf = foundstr->buf; tempstr->bufptr = foundstr->bufptr; tempstr->bufend = foundstr->bufend; tempstr->bufeof = foundstr->bufeof; tempstr->buflen = foundstr->buflen; if (cur->iscurrent) { cur_str = tempstr; } } else if (tempstr->type == strtype_File) { //fd("not touching file info for the moment"); } found = TRUE; break; } } if (found) break; } } if (!found) { // we're here because nothing matched; make a new stream sprintf(errbuf, "\n[Autorestore warning: a stream of type %s is missing: id %d]\n", (cur->type == strtype_File) ? "strtype_File" : (cur->type == strtype_Window) ? "strtype_Window" : (cur->type == strtype_Memory) ? "strtype_Memory" : "UNKNOWN", (int)cur->id); iosif_win_puts(0, errbuf); } #endif } else if (cur->type == gidisp_Class_Fileref) { // iosif_win_puts(0, "\n[Autorestore warning: missing file stream]\n"); if (*cur->obj.fref.filename && strcmp(cur->obj.fref.filename, kFrotzAutoSaveFile)!=0) { glui32 usage = (cur->obj.fref.textmode ? fileusage_TextMode : 0) | (cur->obj.fref.filetype & fileusage_TypeMask); fileref_t *fref = gli_new_fileref(cur->obj.fref.filename, usage, cur->obj.fref.rock); id = classes_find_id_for_object(gidisp_Class_Fileref, fref); if (id != cur->id) { cref_id = classes_pop_cref(gidisp_Class_Fileref, id); cref_id->id = cur->id; // auto-awarding should verify that an id has not been reused classes_push_cref(gidisp_Class_Fileref, cref_id); } } } else if (cur->type == type_Style) { if (cur->id == STYLEHINT_TEXT_BUFFER) { gli_window_set_stylehints((winid_t)STYLEHINT_TEXT_BUFFER, (GLK_STYLE_HINTS *)&cur->obj.style); } else if (cur->id == STYLEHINT_TEXT_GRID) { gli_window_set_stylehints((winid_t)STYLEHINT_TEXT_GRID, (GLK_STYLE_HINTS *)&cur->obj.style); } } } // restore current output stream if (cur_str) { glk_stream_set_current(cur_str); } return TRUE; }
frefid_t glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) { fileref_t *fref; char buf[256], newbuf[256]; char *cx; int val; char *prompt, *prompt2; switch (usage & fileusage_TypeMask) { case fileusage_SavedGame: prompt = "Enter saved game"; break; case fileusage_Transcript: prompt = "Enter transcript file"; break; case fileusage_InputRecord: prompt = "Enter command record file"; break; case fileusage_Data: default: prompt = "Enter data file"; break; } if (fmode == filemode_Read) prompt2 = "to load"; else prompt2 = "to store"; printf("%s %s: ", prompt, prompt2); fgets(buf, 255, stdin); val = strlen(buf); while (val && (buf[val-1] == '\n' || buf[val-1] == '\r' || buf[val-1] == ' ')) val--; buf[val] = '\0'; for (cx = buf; *cx == ' '; cx++) { } val = strlen(cx); if (!val) { /* The player just hit return. It would be nice to provide a default value, but this implementation is too cheap. */ return NULL; } if (cx[0] == '/') strcpy(newbuf, cx); else sprintf(newbuf, "%s/%s", workingdir, cx); fref = gli_new_fileref(newbuf, usage, rock); if (!fref) { gli_strict_warning("fileref_create_by_prompt: unable to create fileref."); return NULL; } return fref; }
frefid_t glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) { fileref_t *fref; struct stat sbuf; char buf[256], prbuf[256], newbuf[256]; char *cx; int ix, val; char *prompt, *prompt2, *lastbuf; switch (usage & fileusage_TypeMask) { case fileusage_SavedGame: prompt = "Enter saved game"; lastbuf = lastsavename; break; case fileusage_Transcript: prompt = "Enter transcript file"; lastbuf = lastscriptname; break; case fileusage_InputRecord: prompt = "Enter command record file"; lastbuf = lastcmdname; break; case fileusage_Data: default: prompt = "Enter data file"; lastbuf = lastdataname; break; } if (fmode == filemode_Read) prompt2 = "to load"; else prompt2 = "to store"; sprintf(prbuf, "%s %s: ", prompt, prompt2); if (prefs.prompt_defaults) { strcpy(buf, lastbuf); val = strlen(buf); } else { buf[0] = 0; val = 0; } ix = xmsg_getline(prbuf, buf, 255, &val); if (!ix) { /* The player cancelled input. */ return 0; } buf[val] = '\0'; while (val && (buf[val-1] == '\n' || buf[val-1] == '\r' || buf[val-1] == ' ')) val--; buf[val] = '\0'; for (cx = buf; *cx == ' '; cx++) { } val = strlen(cx); if (!val) { /* The player just hit return. */ return 0; } if (cx[0] == '/') strcpy(newbuf, cx); else sprintf(newbuf, "%s/%s", workingdir, cx); if (fmode != filemode_Read) { if (!stat(newbuf, &sbuf) && S_ISREG(sbuf.st_mode)) { sprintf(prbuf, "Overwrite \"%s\"? [y/n] ", cx); while (1) { ix = xmsg_getchar(prbuf); if (ix == 'n' || ix == 'N' || ix == '\033' || ix == '\007') { return 0; } if (ix == 'y' || ix == 'Y') { break; } } } } strcpy(lastbuf, cx); fref = gli_new_fileref(newbuf, usage, rock); if (!fref) { gli_strict_warning("fileref_create_by_prompt: unable to create fileref."); return 0; } return fref; }