📄 file.c
字号:
/* Check that the length that the buffer thinks it has is the same as what we gave it. If not, there were probably nuls in the file. Substitute them with another character. If that is impossible, warn the user, make the file read-only, and force a substitution */ if (window->buffer->length != readLen) { if (!BufSubstituteNullChars(fileString, readLen, window->buffer)) { resp = DialogF(DF_ERR, window->shell, 2, "Error while opening File", "Too much binary data in file. You may view\n" "it, but not modify or re-save its contents.", "View", "Cancel"); if (resp == 2) { return FALSE; } SET_TMBD_LOCKED(window->lockReasons, TRUE); for (c = fileString; c < &fileString[readLen]; c++) { if (*c == '\0') { *c = 0xfe; } } window->buffer->nullSubsChar = 0xfe; } window->ignoreModify = True; BufSetAll(window->buffer, fileString); window->ignoreModify = False; } /* Release the memory that holds fileString */ free(fileString); /* Set window title and file changed flag */ if ((flags & PREF_READ_ONLY) != 0) { SET_USER_LOCKED(window->lockReasons, TRUE); } if (IS_PERM_LOCKED(window->lockReasons)) { window->fileChanged = FALSE; UpdateWindowTitle(window); } else { SetWindowModified(window, FALSE); if (IS_ANY_LOCKED(window->lockReasons)) { UpdateWindowTitle(window); } } UpdateWindowReadOnly(window); return TRUE;} int IncludeFile(WindowInfo *window, const char *name){ struct stat statbuf; int fileLen, readLen; char *fileString; FILE *fp = NULL; /* Open the file */ fp = fopen(name, "rb"); if (fp == NULL) { DialogF(DF_ERR, window->shell, 1, "Error opening File", "Could not open %s:\n%s", "Dismiss", name, errorString()); return FALSE; } /* Get the length of the file */ if (fstat(fileno(fp), &statbuf) != 0) { DialogF(DF_ERR, window->shell, 1, "Error opening File", "Error opening %s", "Dismiss", name); fclose(fp); return FALSE; } if (S_ISDIR(statbuf.st_mode)) { DialogF(DF_ERR, window->shell, 1, "Error opening File", "Can't open directory %s", "Dismiss", name); fclose(fp); return FALSE; } fileLen = statbuf.st_size; /* allocate space for the whole contents of the file */ fileString = (char *)malloc(fileLen+1); /* +1 = space for null */ if (fileString == NULL) { DialogF(DF_ERR, window->shell, 1, "Error opening File", "File is too large to include", "Dismiss"); fclose(fp); return FALSE; } /* read the file into fileString and terminate with a null */ readLen = fread(fileString, sizeof(char), fileLen, fp); if (ferror(fp)) { DialogF(DF_ERR, window->shell, 1, "Error opening File", "Error reading %s:\n%s", "Dismiss", name, errorString()); fclose(fp); free(fileString); return FALSE; } fileString[readLen] = 0; /* Detect and convert DOS and Macintosh format files */ switch (FormatOfFile(fileString)) { case DOS_FILE_FORMAT: ConvertFromDosFileString(fileString, &readLen, NULL); break; case MAC_FILE_FORMAT: ConvertFromMacFileString(fileString, readLen); break; } /* If the file contained ascii nulls, re-map them */ if (!BufSubstituteNullChars(fileString, readLen, window->buffer)) { DialogF(DF_ERR, window->shell, 1, "Error opening File", "Too much binary data in file", "Dismiss"); } /* close the file */ if (fclose(fp) != 0) { /* unlikely error */ DialogF(DF_WARN, window->shell, 1, "Error opening File", "Unable to close file", "Dismiss"); /* we read it successfully, so continue */ } /* insert the contents of the file in the selection or at the insert position in the window if no selection exists */ if (window->buffer->primary.selected) BufReplaceSelected(window->buffer, fileString); else BufInsert(window->buffer, TextGetCursorPos(window->lastFocus), fileString); /* release the memory that holds fileString */ free(fileString); return TRUE;}/*** Close all files and windows, leaving one untitled window*/int CloseAllFilesAndWindows(void){ while (WindowList->next != NULL || WindowList->filenameSet || WindowList->fileChanged) { if (!CloseFileAndWindow(WindowList, PROMPT_SBC_DIALOG_RESPONSE)) return FALSE; } return TRUE;}int CloseFileAndWindow(WindowInfo *window, int preResponse){ int response, stat; /* Make sure that the window is not in iconified state */ RaiseShellWindow(window->shell); /* If the window is a normal & unmodified file or an empty new file, or if the user wants to ignore external modifications then just close it. Otherwise ask for confirmation first. */ if (!window->fileChanged && /* Normal File */ ((!window->fileMissing && window->lastModTime > 0) || /* New File*/ (window->fileMissing && window->lastModTime == 0) || /* File deleted/modified externally, ignored by user. */ !GetPrefWarnFileMods())) { CloseWindow(window); /* up-to-date windows don't have outstanding backup files to close */ } else { if (preResponse == PROMPT_SBC_DIALOG_RESPONSE) { response = DialogF(DF_WARN, window->shell, 3, "Save File", "Save %s before closing?", "Yes", "No", "Cancel", window->filename); } else { response = preResponse; } if (response == YES_SBC_DIALOG_RESPONSE) { /* Save */ stat = SaveWindow(window); if (stat) { CloseWindow(window); } else { return FALSE; } } else if (response == NO_SBC_DIALOG_RESPONSE) { /* Don't Save */ RemoveBackupFile(window); CloseWindow(window); } else /* 3 == Cancel */ { return FALSE; } } return TRUE;}int SaveWindow(WindowInfo *window){ int stat; /* Try to ensure our information is up-to-date */ CheckForChangesToFile(window); /* Return success if the file is normal & unchanged or is a read-only file. */ if ( (!window->fileChanged && !window->fileMissing && window->lastModTime > 0) || IS_ANY_LOCKED_IGNORING_PERM(window->lockReasons)) return TRUE; /* Prompt for a filename if this is an Untitled window */ if (!window->filenameSet) return SaveWindowAs(window, NULL, False); /* Check for external modifications and warn the user */ if (GetPrefWarnFileMods() && fileWasModifiedExternally(window)) { stat = DialogF(DF_WARN, window->shell, 2, "Save File", "%s has been modified by another program.\n\n" "Continuing this operation will overwrite any external\n" "modifications to the file since it was opened in NEdit,\n" "and your work or someone else's may potentially be lost.\n\n" "To preserve the modified file, cancel this operation and\n" "use Save As... to save this file under a different name,\n" "or Revert to Saved to revert to the modified version.", "Continue", "Cancel", window->filename); if (stat == 2) { /* Cancel and mark file as externally modified */ window->lastModTime = 0; window->fileMissing = FALSE; return FALSE; } } #ifdef VMS RemoveBackupFile(window); stat = doSave(window);#else if (writeBckVersion(window)) return FALSE; stat = doSave(window); if (stat) RemoveBackupFile(window);#endif /*VMS*/ return stat;} int SaveWindowAs(WindowInfo *window, const char *newName, int addWrap){ int response, retVal, fileFormat; char fullname[MAXPATHLEN], filename[MAXPATHLEN], pathname[MAXPATHLEN]; WindowInfo *otherWindow; /* Get the new name for the file */ if (newName == NULL) { response = PromptForNewFile(window, "Save File As", fullname, &fileFormat, &addWrap); if (response != GFN_OK) return FALSE; window->fileFormat = fileFormat; } else strcpy(fullname, newName); /* Add newlines if requested */ if (addWrap) addWrapNewlines(window); /* If the requested file is this file, just save it and return */ if (ParseFilename(fullname, filename, pathname) != 0) { return FALSE; } if (!strcmp(window->filename, filename) && !strcmp(window->path, pathname)) { if (writeBckVersion(window)) return FALSE; return doSave(window); } /* If the file is open in another window, make user close it. Note that it is possible for user to close the window by hand while the dialog is still up, because the dialog is not application modal, so after doing the dialog, check again whether the window still exists. */ otherWindow = FindWindowWithFile(filename, pathname); if (otherWindow != NULL) { response = DialogF(DF_WARN, window->shell, 2, "File open", "%s is open in another NEdit window", "Cancel", "Close Other Window", filename); if (response == 1) { return FALSE; } if (otherWindow == FindWindowWithFile(filename, pathname)) { if (!CloseFileAndWindow(otherWindow, PROMPT_SBC_DIALOG_RESPONSE)) { return FALSE; } } } /* Destroy the file closed property for the original file */ DeleteFileClosedProperty(window); /* Change the name of the file and save it under the new name */ RemoveBackupFile(window); strcpy(window->filename, filename); strcpy(window->path, pathname); window->filenameSet = TRUE; window->fileMode = 0; CLEAR_ALL_LOCKS(window->lockReasons); retVal = doSave(window); UpdateWindowTitle(window); UpdateWindowReadOnly(window); /* Add the name to the convenience menu of previously opened files */ AddToPrevOpenMenu(fullname); /* If name has changed, language mode may have changed as well */ DetermineLanguageMode(window, False); /* Update the stats line with the new filename */ UpdateStatsLine(window); return retVal;}static int doSave(WindowInfo *window){ char *fileString = NULL; char fullname[MAXPATHLEN]; struct stat statbuf; FILE *fp; int fileLen, result; /* Get the full name of the file */ strcpy(fullname, window->path); strcat(fullname, window->filename);#ifdef VMS /* strip the version number from the file so VMS will begin a new one */ removeVersionNumber(fullname);#endif /* add a terminating newline if the file doesn't already have one for Unix utilities which get confused otherwise NOTE: this must be done _before_ we create/open the file, because the (potential) buffer modification can trigger a check for file changes. If the file is created for the first time, it has zero size on disk, and the check would falsely conclude that the file has changed on disk, and would pop up a warning dialog */ if (BufGetCharacter(window->buffer, window->buffer->length - 1) != '\n' && window->buffer->length != 0 && GetPrefAppendLF()) { BufInsert(window->buffer, window->buffer->length, "\n"); } /* open the file */#ifdef VMS fp = fopen(fullname, "w", "rfm = stmlf");#else fp = fopen(fullname, "wb");#endif /* VMS */ if (fp == NULL) { result = DialogF(DF_WARN, window->shell, 2, "Error saving File", "Unable to save %s:\n%s\n\nSave as a new file?", "Save As...", "Dismiss", window->filename, errorString()); if (result == 1) { return SaveWindowAs(window, NULL, 0); } return FALSE; }#ifdef VMS /* get the complete name of the file including the new version number */ fgetname(fp, fullname);#endif /* get the text buffer contents and its length */ fileString = BufGetAll(window->buffer); fileLen = window->buffer->length; /* If null characters are substituted for, put them back */ BufUnsubstituteNullChars(fileString, window->buffer); /* If the file is to be saved in DOS or Macintosh format, reconvert */ if (window->fileFormat == DOS_FILE_FORMAT) { if (!ConvertToDosFileString(&fileString, &fileLen)) { DialogF(DF_ERR, window->shell, 1, "Out of Memory", "Out of memory! Try\nsaving in Unix format", "Dismiss"); return FALSE; } } else if (window->fileFormat == MAC_FILE_FORMAT) { ConvertToMacFileString(fileString, fileLen); } /* write to the file */#ifdef IBM_FWRITE_BUG write(fileno(fp), fileString, fileLen);#else fwrite(fileString, sizeof(char), fileLen, fp);#endif if (ferror(fp)) { DialogF(DF_ERR, window->shell, 1, "Error saving File", "%s not saved:\n%s", "Dismiss", window->filename, errorString()); fclose(fp); remove(fullname); XtFree(fileString); return FALSE; } /* close the file */ if (fclose(fp) != 0) { DialogF(DF_ERR, window->shell, 1, "Error closing File", "Error closing file:\n%s", "Dismiss", errorString()); XtFree(fileString); return FALSE; } /* free the text buffer copy returned from XmTextGetString */ XtFree(fileString); #ifdef VMS /* reflect the fact that NEdit is now editing a new version of the file */ ParseFilename(fullname, window->filename, window->path);#endif /*VMS*/ /* success, file was written */ SetWindowModified(window, FALSE); /* update the modification time */ if (stat(fullname, &statbuf) == 0) { window->lastModTime = statbuf.st_mtime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -