📄 getfiles.c
字号:
/* Typing in the directory list is dependent on the list being in the same form of alphabetical order expected by the character processing routines. As of about 1.2.3, some Motif libraries seem to have a different idea of ordering than is usual for Unix directories. To sort them properly, we have to patch the directory and file searching routines to re-sort the lists when they change */ XtVaGetValues(existFileSB, XmNdirSearchProc, &OrigDirSearchProc, XmNfileSearchProc, &OrigFileSearchProc, NULL); XtVaSetValues(existFileSB, XmNdirSearchProc, replacementDirSearchProc, XmNfileSearchProc, replacementFileSearchProc, NULL); sortWidgetList(XmFileSelectionBoxGetChild(existFileSB, XmDIALOG_DIR_LIST)); sortWidgetList(XmFileSelectionBoxGetChild(existFileSB, XmDIALOG_LIST));#if XmVersion < 1002 /* To give file list initial focus, revoke default button status for the "OK" button. Dynamic defaulting will restore it as the default button after the keyboard focus is established. Note the voodoo below: calling XmProcess traversal extra times (a recommendation from OSF technical support) somehow succeedes in giving the file list focus */ XtVaSetValues(existFileSB, XmNdefaultButton, NULL, NULL); for (i=1; i<30; i++) XmProcessTraversal(XmFileSelectionBoxGetChild(existFileSB, XmDIALOG_LIST), XmTRAVERSE_CURRENT);#endif#endif /* SGI_CUSTOM */ while (!done_with_dialog) XtAppProcessEvent(XtWidgetToApplicationContext(existFileSB), XtIMAll); if (SelectResult == GFN_OK) { XtVaGetValues(existFileSB, XmNdirSpec, &cFileString, XmNdirectory, &cDir, XmNpattern, &cPattern, NULL); /* Undocumented: file selection box widget allocates copies of these strings on getValues calls. I have risked freeing them to avoid memory leaks, since I assume other developers have made this same realization, therefore OSF can't easily go back and change it */ if (DefaultDirectory != NULL) XmStringFree(DefaultDirectory); if (DefaultPattern != NULL) XmStringFree(DefaultPattern); DefaultDirectory = cDir; DefaultPattern = cPattern; XmStringGetLtoR(cFileString, XmSTRING_DEFAULT_CHARSET, &fileString); /* Motif 2.x seem to contain a bug that causes it to return only the relative name of the file in XmNdirSpec when XmNpathMode is set to XmPATH_MODE_RELATIVE (through X resources), although the man page states that it always returns the full path name. We can easily work around this by checking that the first character of the file name is a `/'. */#ifdef VMS /* VMS won't return `/' as the 1st character of the full file spec. `:' terminates the device name and is not allowed elsewhere */ if (strchr(fileString, ':') != NULL) {#else if (fileString[0] == '/') {#endif /* VMS */ /* The directory name is already present in the file name or the user entered a full path name. */ strcpy(filename, fileString); } else { /* Concatenate the directory name and the file name */ XmStringGetLtoR(cDir, XmSTRING_DEFAULT_CHARSET, &dirString); strcpy(filename, dirString); strcat(filename, fileString); XtFree(dirString); } XmStringFree(cFileString); XtFree(fileString); } /* Destroy the dialog _shell_ iso. the dialog. Normally, this shouldn't be necessary as the shell is destroyed automatically when the dialog is. However, due to a bug in various Lesstif versions, the latter messes up the grab cascades and leaves new windows without grabs, such that they appear to be frozen. */ XtDestroyWidget(XtParent(existFileSB)); return SelectResult;}/*** HandleCustomNewFileSB**** Manage a customized file selection box for opening new files.**** Arguments:**** Widget newFileSB - your custom file selection box widget id** char * filename - a string to receive the selected filename** (this string will not be altered if the** user pressed the cancel button) ** char* defaultName - default name to be pre-entered in filename** text field.**** Returns: GFN_OK - file was selected and OK button pressed ** GFN_CANCEL - Cancel button pressed and no returned file***/int HandleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName){ Boolean done_with_dialog=False; /* ok to destroy dialog flag */ Widget help; /* help window form dialog */ XmString cFileString; /* compound string for file selected */ XmString cDir; /* compound directory selected */ XmString cPattern; /* compound filter pattern */ char *fileString; /* C string for file selected */ char *dirString; /* C string for dir of file selected */#if XmVersion < 1002 int i;#endif XtAddCallback(newFileSB, XmNokCallback, (XtCallbackProc)newFileOKCB, &done_with_dialog); XtAddCallback(newFileSB, XmNcancelCallback, (XtCallbackProc)newFileCancelCB, &done_with_dialog);#ifndef SGI_CUSTOM makeListTypeable(XmFileSelectionBoxGetChild(newFileSB,XmDIALOG_LIST)); makeListTypeable(XmFileSelectionBoxGetChild(newFileSB,XmDIALOG_DIR_LIST));#endif if (DefaultDirectory != NULL || DefaultPattern != NULL) XtVaSetValues(newFileSB, XmNdirectory, DefaultDirectory, XmNpattern, DefaultPattern, NULL); help = createPanelHelp(newFileSB, HelpNew, "Saving a File"); createYesNoDialog(newFileSB); createErrorDialog(newFileSB); XtAddCallback(newFileSB, XmNhelpCallback, (XtCallbackProc)newHelpCB, (char *)help); if (defaultName != NULL) { Widget nameField = XmFileSelectionBoxGetChild(newFileSB, XmDIALOG_TEXT); XmTextInsert(nameField, XmTextGetLastPosition(nameField), defaultName); }#if XmVersion >= 1002#ifndef SGI_CUSTOM XtVaSetValues(newFileSB, XmNinitialFocus, XmFileSelectionBoxGetChild(newFileSB, XmDIALOG_TEXT), NULL);#else /* SGI_CUSTOM */ { Widget finder = XmFileSelectionBoxGetChild(newFileSB, SgDIALOG_FINDER); if ( finder != NULL ) XtVaSetValues(newFileSB, XmNinitialFocus, finder, NULL); }#endif#endif ManageDialogCenteredOnPointer(newFileSB);#ifndef SGI_CUSTOM#if XmVersion < 1002 /* To give filename text initial focus, revoke default button status for the "OK" button. Dynamic defaulting will restore it as the default button after the keyboard focus is established. Note the voodoo below: calling XmProcess traversal FOUR times (a recommendation from OSF technical support) somehow succeedes in changing the focus */ XtVaSetValues(newFileSB, XmNdefaultButton, NULL, NULL); for (i=1; i<30; i++) XmProcessTraversal(XmFileSelectionBoxGetChild(newFileSB, XmDIALOG_TEXT), XmTRAVERSE_CURRENT);#endif /* Typing in the directory list is dependent on the list being in the same form of alphabetical order expected by the character processing routines. As of about 1.2.3, some Motif libraries seem to have a different idea of ordering than is usual for Unix directories. To sort them properly, we have to patch the directory and file searching routines to re-sort the lists when they change */ XtVaGetValues(newFileSB, XmNdirSearchProc, &OrigDirSearchProc, XmNfileSearchProc, &OrigFileSearchProc, NULL); XtVaSetValues(newFileSB, XmNdirSearchProc, replacementDirSearchProc, XmNfileSearchProc, replacementFileSearchProc, NULL); sortWidgetList(XmFileSelectionBoxGetChild(newFileSB, XmDIALOG_DIR_LIST)); sortWidgetList(XmFileSelectionBoxGetChild(newFileSB, XmDIALOG_LIST));#endif /* SGI_CUSTOM */ while (!done_with_dialog) XtAppProcessEvent (XtWidgetToApplicationContext(newFileSB), XtIMAll); if (SelectResult == GFN_OK) { /* See note in existing file routines about freeing the values obtained in the following call */ XtVaGetValues(newFileSB, XmNdirSpec, &cFileString, XmNdirectory, &cDir, XmNpattern, &cPattern, NULL); if (DefaultDirectory != NULL) XmStringFree(DefaultDirectory); if (DefaultPattern != NULL) XmStringFree(DefaultPattern); DefaultDirectory = cDir; DefaultPattern = cPattern; XmStringGetLtoR(cFileString, XmSTRING_DEFAULT_CHARSET, &fileString); /* See note in existing file routines about Motif 2.x bug. */#ifdef VMS /* VMS won't return `/' as the 1st character of the full file spec. `:' terminates the device name and is not allowed elsewhere */ if (strchr(fileString, ':') != NULL) {#else if (fileString[0] == '/') {#endif /* VMS */ /* The directory name is already present in the file name or the user entered a full path name. */ strcpy(filename, fileString); } else { /* Concatenate the directory name and the file name */ XmStringGetLtoR(cDir, XmSTRING_DEFAULT_CHARSET, &dirString); strcpy(filename, dirString); strcat(filename, fileString); XtFree(dirString); } XmStringFree(cFileString); XtFree(fileString); } XtDestroyWidget(newFileSB); return SelectResult;}/*** Return current default directory used by GetExistingFilename.** Can return NULL if no default directory has been set (meaning** use the application's current working directory) String must** be freed by the caller using XtFree.*/char *GetFileDialogDefaultDirectory(void){ char *string; if (DefaultDirectory == NULL) return NULL; XmStringGetLtoR(DefaultDirectory, XmSTRING_DEFAULT_CHARSET, &string); return string;}/*** Return current default match pattern used by GetExistingFilename.** Can return NULL if no default pattern has been set (meaning use** a pattern matching all files in the directory) String must be** freed by the caller using XtFree.*/char *GetFileDialogDefaultPattern(void){ char *string; if (DefaultPattern == NULL) return NULL; XmStringGetLtoR(DefaultPattern, XmSTRING_DEFAULT_CHARSET, &string); return string;}/*** Set the current default directory to be used by GetExistingFilename.** "dir" can be passed as NULL to clear the current default directory** and use the application's working directory instead.*/void SetFileDialogDefaultDirectory(char *dir){ if (DefaultDirectory != NULL) XmStringFree(DefaultDirectory); DefaultDirectory = dir==NULL ? NULL : XmStringCreateSimple(dir);}/*** Set the current default match pattern to be used by GetExistingFilename.** "pattern" can be passed as NULL as the equivalent a pattern matching** all files in the directory.*/void SetFileDialogDefaultPattern(char *pattern){ if (DefaultPattern != NULL) XmStringFree(DefaultPattern); DefaultPattern = pattern==NULL ? NULL : XmStringCreateSimple(pattern);}/*** Turn on or off the text fiend in the GetExistingFilename file selection** box, where users can enter the filename by typing. This is redundant** with typing in the list, and leads users who are new to nedit to miss** the more powerful feature in favor of changing the focus and typing** in the text field.*/void SetGetEFTextFieldRemoval(int state){ RemoveRedundantTextField = state;}/*** createYesNoDialog, createErrorDialog, doYesNoDialog, doErrorDialog**** Error Messages and question dialogs to be used with the file selection** box. Due to a crash bug in Motif 1.1.1 thru (at least) 1.1.5** getfiles can not use DialogF. According to OSF, there is an error** in the creation of pushButtonGadgets involving the creation and** destruction of some sort of temporary object. These routines create** the dialogs along with the file selection dialog and manage them** to display messages. This somehow avoids the problem*/static void createYesNoDialog(Widget parent){ XmString buttonString; /* compound string for dialog buttons */ int n; /* number of arguments */ Arg args[MAX_ARGS]; /* arg list */ n = 0; XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++; XtSetArg(args[n], XmNtitle, " "); n++; YesNoDialog = CreateQuestionDialog(parent, "yesNo", args, n); XtAddCallback (YesNoDialog, XmNokCallback, (XtCallbackProc)yesNoOKCB, NULL); XtAddCallback (YesNoDialog, XmNcancelCallback, (XtCallbackProc)yesNoCancelCB, NULL); XtUnmanageChild(XmMessageBoxGetChild (YesNoDialog, XmDIALOG_HELP_BUTTON)); buttonString = XmStringCreateSimple("Yes"); SET_ONE_RSRC(YesNoDialog, XmNokLabelString, buttonString); XmStringFree(buttonString); buttonString = XmStringCreateSimple("No"); SET_ONE_RSRC(YesNoDialog, XmNcancelLabelString, buttonString); XmStringFree(buttonString);}static void createErrorDialog(Widget parent){ XmString buttonString; /* compound string for dialog button */ int n; /* number of arguments */ Arg args[MAX_ARGS]; /* arg list */ n = 0; XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++; XtSetArg(args[n], XmNtitle, " "); n++; ErrorDialog = CreateErrorDialog(parent, "error", args, n); XtAddCallback(ErrorDialog, XmNcancelCallback, (XtCallbackProc)errorOKCB, NULL); XtUnmanageChild(XmMessageBoxGetChild(ErrorDialog, XmDIALOG_OK_BUTTON)); XtUnmanageChild(XmMessageBoxGetChild(ErrorDialog, XmDIALOG_HELP_BUTTON)); buttonString = XmStringCreateLtoR ("Dismiss", XmSTRING_DEFAULT_CHARSET); XtVaSetValues(ErrorDialog, XmNcancelLabelString, buttonString, NULL); XmStringFree(buttonString);}static int doYesNoDialog(const char *filename){ char string[255]; XmString mString; YesNoResult = ynNone; sprintf(string, "File %s already exists,\nOk to overwrite?", filename); mString = XmStringCreateLtoR(string, XmSTRING_DEFAULT_CHARSET); SET_ONE_RSRC(YesNoDialog, XmNmessageString, mString); XmStringFree(mString); ManageDialogCenteredOnPointer(YesNoDialog); while (YesNoResult == ynNone) XtAppProcessEvent(XtWidgetToApplicationContext(YesNoDialog), XtIMAll); XtUnmanageChild(YesNoDialog); /* Nasty motif bug here, patched around by waiting for a ReparentNotify event (with timeout) before allowing file selection dialog to pop down. If this routine returns too quickly, and the file selection dialog (and thereby, this dialog as well) are destroyed while X is still sorting through the events generated by the pop-down, something bad happens and we get a crash */ if (YesNoResult == ynYes) PopDownBugPatch(YesNoDialog); return YesNoResult == ynYes;}static void doErrorDialog(const char *errorString, const char *filename){ char string[255]; XmString mString; ErrorDone = False; sprintf(string, errorString, filename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -