void WMInsertMenu(MenuHandle menuH, short beforeID) { if (!CheckRunningInMainThread("WMInsertMenu")) return; InsertMenu(menuH, beforeID); }
/* FillMenu(theMenu, itemList, itemListLen, afterItem) itemList is a semicolon separated list of items to be put into theMenu. itemListLen is the total number of characters in itemList. afterItem specifies where the items in itemList are to appear in the menu. afterItem = 0 new items appear at beginning of menu afterItem = 10000 new items appear at end of menu afterItem = item number new items appear after specified existing item number. NOTE: You should not call this routine to update the contents of an existing dialog popup menu item. Use FillPopMenu instead. Thread Safety: FillMenu is not thread-safe. */ void FillMenu(MenuHandle theMenu, const char *itemList, int itemListLen, int afterItem) { const char *p1; const char *p2; char item[256]; int len, itemLen; if (!CheckRunningInMainThread("FillMenu")) return; p1 = itemList; while (itemListLen > 0) { if (p2 = strchr(p1, ';')) len = (int)(p2 - p1); else len = itemListLen; /* last one */ itemLen = len; if (itemLen > 255) itemLen = 255; strncpy(item, p1, itemLen); item[itemLen] = 0; insertmenuitem(theMenu, item, afterItem); p1 += len+1; itemListLen -= len+1; afterItem++; } }
/* FillMenuNoMeta(theMenu, itemList, itemListLen, afterItem) This routine works exactly like FillMenu except that it does not honor meta-characters. For example, the Macintosh Menu Manager treats left parenthesis as a meta-character. If you add an item to a menu that contains a left parenthesis, the item is added as a disabled item and the left parenthesis is omitted. This behavior sometimes is not what the programmer intended. Using FillMenuNoMeta instead of FillMenu causes the Macintosh menu manager to skip the special treatment of such characters. itemList is a semicolon separated list of items to be put into theMenu. itemListLen is the total number of characters in itemList. afterItem specifies where the items in itemList are to appear in the menu. afterItem = 0 new items appear at beginning of menu afterItem = 10000 new items appear at end of menu afterItem = item number new items appear after specified existing item number. NOTE: Do not call this routine to update the contents of an existing dialog popup menu item. Use FillPopMenu instead. Thread Safety: FillMenuNoMeta is not thread-safe. */ void FillMenuNoMeta(MenuHandle theMenu, const char *itemList, int itemListLen, int afterItem) { const char *p1; const char *p2; char itemText[256]; int len, itemLen; int newItemNumber; if (!CheckRunningInMainThread("FillMenuNoMeta")) return; newItemNumber = afterItem + 1; if (newItemNumber > 10000) newItemNumber = CountMItems(theMenu) + 1; p1 = itemList; while (itemListLen > 0) { if (p2 = strchr(p1, ';')) len = (int)(p2 - p1); else len = itemListLen; // Last one. itemLen = len; if (itemLen > 255) itemLen = 255; strncpy(itemText, p1, itemLen); itemText[itemLen] = 0; insertmenuitem(theMenu, "x", afterItem); setmenuitemtext(theMenu, newItemNumber, itemText); // This call does not treat certain characters as meta-characters. p1 += len+1; itemListLen -= len+1; afterItem += 1; newItemNumber += 1; } }
void WMDeleteMenu(short menuID) { if (!CheckRunningInMainThread("WMDeleteMenu")) return; DeleteMenu(menuID); }
/* ResourceMenuIDToMenuHandle(int resourceMenuID) Given the ID of a 'MENU' resource in the XOP's resource fork, returns the menu handle for that menu. Returns NULL if XOP did not add this menu. Thread Safety: ResourceMenuIDToMenuHandle is not thread-safe. */ MenuHandle ResourceMenuIDToMenuHandle(int resourceMenuID) { if (!CheckRunningInMainThread("ResourceMenuIDToMenuHandle")) return NULL; return (MenuHandle)CallBack1(XOPMENUHANDLE, (void *)resourceMenuID); }
/* SetIgorMenuItem(message, enable, text, param) Enables or disables a built-in Igor menu item. message is a message code that Igor normally passes to the XOP, such as COPY, CUT, PASTE. enable is 1 to enable the corresponding item, 0 to disable. text is normally NULL. However, if the menu item text is variable and text is not NULL, Igor will set the item to the specified text. param is normally not used and should be 0. However, for the FIND message, param is as follows: 1 to set the 'Find' item 2 to set the 'Find Same' item 3 to set the 'Find Selected Text' item. The function result is 1 if there exists a built-in Igor menu item corresponding to the message or zero otherwise. Normally, you can ignore this result. Thread Safety: SetIgorMenuItem is not thread-safe. */ int SetIgorMenuItem(int message, int enable, const char* text, int param) { if (!CheckRunningInMainThread("SetIgorMenuItem")) return 0; return (int)CallBack4(SETIGORMENUITEM, (void *)message, (void *)enable, (void *)text, (void *)param); }
void WMDrawMenuBar(void) { if (!CheckRunningInMainThread("WMDrawMenuBar")) return; DrawMenuBar(); }
/* ActualToResourceItem(igorMenuID, actualItemNumber) Given the ID of a built-in Igor and the actual number of a menu item in the Igor menu, returns the number of the specification in the 'XMI1' resource in the XOP's resource fork for that item. Item numbers start from 1. Returns 0 if XOP did not add this menu item to Igor menu. Thread Safety: ActualToResourceItem is not thread-safe. */ int ActualToResourceItem(int igorMenuID, int actualItemNumber) { if (!CheckRunningInMainThread("ActualToResourceItem")) return 0; return (int)CallBack2(RESOURCEITEMNUM, (void *)igorMenuID, (void *)actualItemNumber); }
/* ResourceToActualItem(igorMenuID, resourceItemNumber) Given the ID of a built-in Igor and the number of a menu item specification in the 'XMI1' resource in the XOP's resource fork, returns the actual item number of that item in the Igor menu. Item numbers start from 1. Returns 0 if XOP did not add this menu item to Igor menu. Thread Safety: ResourceToActualItem is not thread-safe. */ int ResourceToActualItem(int igorMenuID, int resourceItemNumber) { if (!CheckRunningInMainThread("ResourceToActualItem")) return 0; return (int)CallBack2(ACTUALITEMNUM, (void *)igorMenuID, (void *)resourceItemNumber); }
/* ActualToResourceMenuID(int menuID) Given the ID of a menu in memory, returns the resource ID of the 'MENU' resource in the XOP's resource fork. Returns 0 if XOP did not add this menu to Igor menu. Thread Safety: ActualToResourceMenuID is not thread-safe. */ int ActualToResourceMenuID(int menuID) { if (!CheckRunningInMainThread("ActualToResourceMenuID")) return 0; return (int)CallBack1(RESOURCEMENUID, (void *)menuID); }
/* SetDialogBalloonHelpID(balloonHelpID) Sets the resource ID for the 'hdlg' resource to be used for contextual help. If balloonHelpID is -1, this indicates that no contextual help is to be used. Currently does nothing on Windows. Prior to Carbon, this routine called the Apple Balloon Help Manager HMSetDialogResID routine. With Carbon, Apple dropped support for balloon help. This routine now links with the contextual help functionality inside Igor Pro Carbon. It does nothing if running with a pre-Carbon version of Igor. Thread Safety: SetDialogBalloonHelpID is not thread-safe. */ void SetDialogBalloonHelpID(int balloonHelpID) { if (!CheckRunningInMainThread("SetDialogBalloonHelpID")) return; CallBack2(SET_CONTEXTUAL_HELP_DIALOG_ID, (void *)XOPRefNum(), (void *)balloonHelpID); }
/* ResourceToActualMenuID(int resourceMenuID) Given the ID of a 'MENU' resource in the XOP's resource fork, returns the actual menu ID of that resource in memory. Returns 0 if XOP did not add this menu to Igor menu. Thread Safety: ResourceToActualMenuID is not thread-safe. */ int ResourceToActualMenuID(int resourceMenuID) { if (!CheckRunningInMainThread("ResourceToActualMenuID")) return 0; return (int)CallBack1(ACTUALMENUID, (void *)resourceMenuID); }
/* XOPYesNoCancelAlert(title, message) Returns 1 for yes, 2 for no, -1 for cancel. Thread Safety: XOPYesNoCancelAlert is not thread-safe. */ int XOPYesNoCancelAlert(const char* title, const char* message) { if (!CheckRunningInMainThread("XOPYesNoCancelAlert")) return -1; return DoXOPAlert(IGOR_YES_NO_CANCEL_DLOG, title, message); }
/* GetDataFolderChangeFlags(dataFolderH, flagsP) This routine is for use by the WaveMetrics Data Browser only. Thread Safety: GetDataFolderChangeFlags is not thread-safe. */ int GetDataFolderChangeFlags(DataFolderHandle dataFolderH, int *flagsP) { if (!CheckRunningInMainThread("GetDataFolderChangeFlags")) return 0; return (int)CallBack2(GET_DATAFOLDER_CHANGEFLAGS, dataFolderH, flagsP); }
/* XOPOKAlert(title, message) Thread Safety: XOPOKAlert is not thread-safe. */ void XOPOKAlert(const char* title, const char* message) { if (!CheckRunningInMainThread("XOPOKAlert")) return; DoXOPAlert(IGOR_OK_DLOG, title, message); }
/* GetDataFolderChangesCount() This routine is for use by the WaveMetrics Data Browser only. Thread Safety: GetDataFolderChangesCount is not thread-safe. */ int GetDataFolderChangesCount(void) { if (!CheckRunningInMainThread("GetDataFolderChangesCount")) return 0; return (int)CallBack0(GET_DATAFOLDER_CHANGESCOUNT); }
/* ClearDataFolderFlags() This routine is for use by the WaveMetrics Data Browser only. Thread Safety: ClearDataFolderFlags is not thread-safe. */ void ClearDataFolderFlags(void) { if (!CheckRunningInMainThread("ClearDataFolderFlags")) return; CallBack0(CLEAR_DATAFOLDER_FLAGS); }
/* WMDeleteMenuItems(theMenu, afterItem) Deletes the contents of the existing dialog popup menu after the specified item. afterItem is 1-based. If afterItem is zero, all items are deleted. NOTE: You should not call this routine to delete the contents of an existing dialog popup menu item. Use DeletePopMenuItems instead. HR, 010427: This was previously called WMDeleteMenuItems but Apple usurped that name. Thread Safety: WMDeleteMenuItems is not thread-safe. */ void WMDeleteMenuItems(MenuHandle theMenu, int afterItem) { int item, items; if (!CheckRunningInMainThread("WMDeleteMenuItems")) return; afterItem++; /* # of first item to delete */ items = CountMItems(theMenu); for (item = afterItem; item <= items; item++) DeleteMenuItem(theMenu, afterItem); }
/* FillWinMenu(MenuHandle theMenu, char *match, char *options, int afterItem) Puts names of Igor windows into theMenu. match and options are as for the Igor WinList() function: match = "*" for all windows options = "" for all windows options = "WIN: 1" for all graphs ( bit 0 selects graphs) options = "WIN: 2" for all tables ( bit 1 selects graphs) options = "WIN: 4" for all layouts ( bit 2 selects graphs) options = "WIN: 3" for all graphs and tables afterItem is as for FillMenu, described above. In contrast to Macintosh menu manager routines, this routine does not treat any characters as meta-characters. NOTE: You should not call this routine to update the contents of an existing dialog popup menu item. Use FillWindowPopMenu instead. Thread Safety: FillWinMenu is not thread-safe. */ int FillWinMenu(MenuHandle theMenu, const char *match, const char *options, int afterItem) { Handle listHandle; int result; if (!CheckRunningInMainThread("FillWinMenu")) return NOT_IN_THREADSAFE; listHandle = NewHandle(0L); result = WinList(listHandle, match, ";", options); FillMenuNoMeta(theMenu, *listHandle, (int)GetHandleSize(listHandle), afterItem); DisposeHandle(listHandle); return(result); }
/* WMGetMenu(resourceID) Gets an Igor menu handle from a menu resource stored in the XOP. Returns NULL if there is no such resource or if some other error occurs. Thread Safety: WMGetMenu is not thread-safe. */ MenuHandle WMGetMenu(short resourceID) { MenuHandle mHandle; if (!CheckRunningInMainThread("WMGetMenu")) return NULL; #ifdef MACIGOR mHandle = GetMenu(resourceID); #endif #ifdef WINIGOR mHandle = WMGetMenuFromModule(XOPModule(), resourceID); #endif return mHandle; }
/* XOPSaveFileDialog(prompt, fileFilterStr, fileIndexPtr, initialDir, defaultExtensionStr, filePath) Displays the save file dialog. Returns 0 if the user provides a file name or -1 if the user cancels or another non-zero number in the event of an error. Returns the full path to the file via filePath. filePath is both an input and an output as explained below. In the event of a cancel, filePath is unmodified. filePath is a Macintosh HFS path on Macintosh and a Windows path on Windows. On Windows, prompt sets the dialog caption. On Macintosh, it sets a prompt string in the dialog. fileFilterStr is now used to control the contents of the Format popup menu in the Save File dialog. On Macintosh, if there is only one format in which you can save the file, pass "" for fileFilterStr. This will cause the Format menu to be hidden. If you can save the file in more than one format, pass a string like this: "Plain Text:TEXT:.txt;Igor Text:IGTX:.itx;" This would give you a Format menu like this: Plain Text Igor Text fileFilterStr on Macintosh fileFilterStr consists of sections terminated by a semicolon. For example, here is one section: "Data Files:TEXT:.dat;" Each section consists of three components: a menu item string (e.g., Data Files) to be displayed in the Format popup menu, a Macintosh file type (e.g., TEXT), and an extension (e.g., .dat). At present, only the menu item string and extension are used. The Macintosh file type is currently not used. If there is no meaningful Macintosh file type, leave the file type component empty. If there is no meaningful extension, leave the extension component empty. fileFilterStr on Windows On Windows, fileFilterStr identifies the types of files to display and the types of files that can be created. It is constructed as for the lpstrFilter field of the OPENFILENAME structure for the Windows GetSaveFileName routine. For example, to allow the user to save as a text file or as an Igor Text file, use "Text Files (*.txt)\0*.txt\0Igor Text Files (*.itx)\0*.itx\0\0". Note that the string ends with two null characters (\0\0). If fileFilterStr is "", this behaves the same as "Text Files (*.txt)\0*.txt\0\0". fileIndexPtr it is ignored if it is NULL. If it is not NULL, then *fileIndexPtr is the one-based index of the file type filter to be initially selected. In the example given above, setting *fileIndexPtr to 2 would select the Igor Text file type on entry to the dialog. On exit from the dialog, *fileIndexPtr is set to the index of the file type string that the user last selected. initialDir can be "" or it can point to a full path to a directory. It determines the directory that will be initially displayed in the save file dialog. If "", the directory will be the last directory that was seen in the open or save file dialogs. If initialDir points to a valid path to a directory, then this directory will be initially displayed in the dialog. On Macintosh, initialDir is a Macintosh HFS path. On Windows, it is a Windows path. defaultExtensionStr points to the extension to be added to the file name if the user does not enter an extension. For example, pass "txt" to have ".txt" appended if the user does not enter an extension. If you don't want any extension to be added in this case, pass NULL. Prior to XOP Toolkit 6.00, defaultExtensionStr was ignored on Macintosh. Returns via filePath the full path to the file that the user chose or "" if the user cancelled. The path is a Macintosh HFS path on Macintosh and a Windows path on Windows. filePath must point to a buffer of at least MAX_PATH_LEN+1 bytes. On Windows and Macintosh, the initial value of filePath sets the initial contents of the File Name edit control in the save file dialog. The following values are valid: "" If there is no initial file name a file name a full Mac or Win path to a file In the event of an error other than a cancel, XOPSaveFileDialog displays an error dialog. This should never or rarely happen. WINDOWS NOTES The dialog will appear in the upper left corner of the screen. This is because Windows provides no straight-forward way to set the position of the dialog. Thread Safety: XOPSaveFileDialog is not thread-safe. */ int XOPSaveFileDialog( const char* prompt, const char* fileFilterStr, int* fileIndexPtr, const char* initialDir, const char* defaultExtensionStr, char filePath[MAX_PATH_LEN+1]) { OPENFILENAME ofn; char filePath2[MAX_PATH_LEN+1]; char initialDir2[MAX_PATH_LEN+1]; if (!CheckRunningInMainThread("XOPSaveFileDialog")) return NOT_IN_THREADSAFE; if (*fileFilterStr == 0) fileFilterStr = "Text Files (*.txt)\0*.txt\0\0"; if (*initialDir == 0) { GetStandardFileWinPath(initialDir2); // Get Igor's save file dialog directory. } else { strcpy(initialDir2, initialDir); SetStandardFileWinPath(initialDir); // Sets initial directory for next save file dialog. This will be overridden below, but not if the user cancels. } /* HR, 040928, XOP Toolkit 5.04 Previously this copied filePath to filePath2. This was correct because the filePath parameter was supposed to be either "" or just the proposed file name. However, I incorrectly passed a full path for the filePath parameter in all of the sample XOPs. This mistake undoubtedly leaked into users' XOPs. Therefore I now allow filePath to be either "", just a file name, or a full path. */ // strcpy(filePath2, filePath); // HR, 010815: Previously filePath2 was set to "" which prevented the File Name item in the Windows Open File dialog from being preset as the comment above says it should be. GetLeafName(filePath, filePath2); MemClear(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = IgorClientHWND(); ofn.lpstrFile = filePath2; ofn.nMaxFile = MAX_PATH_LEN+1; ofn.lpstrFilter = fileFilterStr; ofn.nFilterIndex = fileIndexPtr==NULL ? 1 : *fileIndexPtr; ofn.lpstrDefExt = defaultExtensionStr; ofn.lpstrTitle = prompt; ofn.lpstrFileTitle = NULL; ofn.lpstrInitialDir = initialDir2; ofn.lpfnHook = OpenOrSaveFileNameHook; // Needed to set position of the dialog. Otherwise, it is in top/left corner of screen. ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; ofn.Flags |= OFN_EXPLORER; ofn.Flags |= OFN_ENABLEHOOK; // Needed so that hook will be called. ofn.Flags |= OFN_ENABLESIZING; // HR, 090121: Added this to get resizeable dialog. ofn.Flags |= OFN_HIDEREADONLY; ofn.Flags |= OFN_NOCHANGEDIR; // Changing the current directory causes problems. e.g., if set to floppy disk and the floppy is removed, the system slows down. if (GetSaveFileName(&ofn) == 0) { int err; err = CommDlgExtendedError(); // err will be zero if cancel. if (err == 0) return -1; // We got an error other than cancel. *filePath2 = 0; // HR, 021114: Clear possible bad fields *initialDir2 = 0; // and try again. if (GetSaveFileName(&ofn) != 0) { // Succeeded this time? err = 0; } else { if (CommDlgExtendedError() == 0) return -1; // User canceled. // Report the original error. err = WindowsErrorToIgorError(err); IgorError("XOPSaveFileDialog", err); return err; } } if (fileIndexPtr != NULL) *fileIndexPtr = ofn.nFilterIndex; strcpy(filePath, filePath2); SetStandardFileWinPath(filePath); // Update Igor's open file dialog directory. return 0; }