Frequently Asked Questions
General questions
- How can I hide the cursor?
- How can I put it to the required position?
- How should I set the flags for plugin to work in the editor as well as in the panels: Info->Flags=?????;
- Is dynamic plugin connection/disconnection possible without FAR restart?
- Are plugins in the editor operable after activation only? Can I make a plugin work in the background mode?
- Can I merge several plugins (or functions) into one DLL module?...
- ...and then recognize the user's choice using the Item parameter of OpenPlugin function? Am I right?
- Can I make a plugin that works in the background mode using the current API?
- I have a file that can be processed by a plugin. How can I find that out?...
- How can I get the full plugin module path from within it?
- Can I switch FAR background screens from the plugin?
- How does FAR determine that the block in the Clipboard is a vertical block?
- Is it possible to recognize where the cursor is set on the current panel?...
- Can I redraw the window caption while redrawing any panel?...
- Where does FAR get the procedures from for file copying/deletion/... ?
- How can I get the name of the folder from which FAR was started?
- How can I reduce the size of the DLL?...
- There are dupes in the Clipboard, why should FAR put there the same stuff several times?
- How can I determine what is the "symbolic link"?...
- ...what '\\?\Volume{...' hides inside?
- Can I get some more useful info about symbolic links?
- Can I get the changed/unchanged flags for the file being edited?...
- How can I get the name of the file loaded in viewer?
- Is it possible in FSF.ProcessName to get TRUE, when comparing...
- How does Windows dump the file name from the Explorer to the console window?
- ProcessKey doesn't work for some reason...
- How can a plugin position the cursor on a specific file?
- How can a plugin run a program? And show its output under the panels?
Dialogs
- Can I somehow overcome the edit window limitation, where the macro sequence is limited to 512 characters?
- If I don't use the Dialog function to work with dialog, how can I handle the data input? Should I write that myself?
- If I use the Dialog function and an input line within it, will the ProcessEditorInput and ProcessEditorEvent functions work for this control element?
- Can I change elements like Static (their captions) dynamically in a dialog?
- The set of control elements handled by FAR isn't sufficient for me...
- Why the ListBox and ComboBox are so crude?...
- Why the buttons for closing the window don't work in the "new-style" dialog?
- Should I close the dialog myself from now on?
- If I use the mouse, should I catch the DN_MOUSECLICK?
- Should I handle the DefaultButton myself as well?
- In no way the SEPARATOR can reach the frame right edge...
- Can I somehow disable the automatic selection of elements using mouse in lists?...
General questions
- Q: How can I hide the cursor?
A: Win32 console API: SetConsoleCursorInfo
, but don't forget to bring it back.
- Q: How can I put it to the required position?
A: There: SetConsoleCursorPosition
- Q: How should I set the flags for plugin to work in the editor as well as in the panels: Info->Flags=?????;
A: PF_EDITOR
- Q: Is dynamic plugin connection/disconnection possible without FAR restart?
A: Disconnection is impossible. Why do you want to disconnect it? Connections are handled by FAR itself. You can still ask FAR not to cache the configuration of that plugin, but to load it to memory every time FAR starts by specifying the PF_PRELOAD flag. But it will be better for you not to do that since it leads to delays and extra memory consumption.
- Q: Are plugins in the editor operable after activation only? Can I make a plugin work in the background mode?
A: Yes, you can. Export the ProcessEditorInput, and it will intercept all keyboard events in the editor.
- Q: Can I merge several plugins (or functions) into one DLL module? And call each of them as if it was in a separate DLL-file (even if I load that DLL every time)...
A: Yes, you can. In the PluginInfo you can specify several strings that will be added to the Plugins menu. But it violates the rules of professional ethics.
- Q: ...and then recognize the user's choice using the Item parameter of OpenPlugin function? Am I right?
A: You're right.
- Q: Can I make a plugin that works in the background mode using the current API?
A: In the editor only. There's no support for doing that in panels.
- Q: I have a file that can be processed by a plugin. How can I find that out? I think it would be better to send the cd command there and get the answer - was it able to do that or not.
A: You can't do this since there's no API for plugin interaction in FAR. A simple check for file belonging to a plugin is not sufficient.
- Q: How can I get the full plugin module path from within it?
A: FAR passes the pointer in the PluginStartupInfo structure to the SetStartupInfo function. Full module path is in the ModuleName field of that structure.
- Q: Can I switch FAR background screens from the plugin?
A: You can do it beginning from the FAR Manager 1.70 beta 4.
- Q: How does FAR determine that the block in the Clipboard is a vertical block?
A: Vertical block has "FAR_VerticalBlock" Clipboard format.
- Q: Is it possible to recognize where the cursor is set on the current panel? In particular, at the folder or at the file...
A:Control(FCTL_GETANOTHERPANELINFO); Control(FCTL_GETPANELINFO); PanelInfo.PanelItems[PanelInfo.CurrentItem].FindData.dwFileAttributes
- Q: Can I redraw the window caption while redrawing any panel? I think it would be easier and faster than calling FCTL_REDRAWPANEL.
A: It won't necessarily be faster. If the caption was not changed by the plugin (it's usual practice), there's no need to redraw it.
- Q: Where does FAR get the procedures from for file copying/deletion/... ?
A: It gets them from Win32 API.
Copying: CreateFile+ReadFile +WriteFile +CloseHandle or CopyFile (Ex), depending on the operating system and the "Use system copy routine" option.
Deletion: DeleteFileor SHFileOperation , depending on the "Delete to Recycle Bin" option.
- Q: How can I get the name of the folder from which FAR was started?
A:char lpName[_MAX_PATH], lpFullPath[_MAX_PATH]; LPTSTR lpFile; GetModuleFileName
(NULL,lpName,sizeof(lpName)); GetFullPathName (lpName,sizeof(lpFullPath),lpFullPath,&lpFile); *lpFile='\0';
- Q: How can I reduce the size of the DLL - the module is so heavy?
A:- There are some notes regarding that in the "Articles" topic.
- The writers of plugins who use Visual C++ and want to reduce the plugin module size are strongly advised to read this: http://msdn.microsoft.com/msdnmag/issues/01/01/hood/default.aspx (local copy is here)
- Q: There are dupes in the Clipboard, why should FAR put there the same stuff several times?
A: If the text in the Clipboard is in any particular format, but the program wants another one, Windows does the conversion itself, and sometimes does this incorrectly. The pseudographics gets corrupted in this case, russian symbols are converted into '?' sometimes. The bugs depend on the Windows version and initial/final formats combination. If all the formats are in the Clipboard together, Windows finds the necessary one and uses it without any conversions.
- Q: How can I determine what is the "symbolic link" - a simple directory link or a mounted volume?
A: The main rule: symbolic links on Win2K are FOR DIRECTORIES ONLY! So, we need to know - "Is THIS a directory?". We can useFA_DIREC
(orFILE_ATTRIBUTE_DIRECTORY
) file attribute to do that.
Let's continue.
We know for sure that any symbolic link (or reparse point) in Win2K has aFILE_ATTRIBUTE_REPARSE_POINT
attribute - so let's check it.
Call
FSF.GetReparsePointInfo(FullFolderName,DestName,sizeof(DestName))
This function returns real "DestName" for specified "FullFolderName", specifically:"\??\D:\Junc..."
directory junction."\\?\Volume{..."
mounted volume.
Moreover, the first 4 symbols are irrelevant for us! Therefore it is enough to check 7 symbols beginning from the 4th:if(!strncmp(JuncName+4,"Volume{",7)) { // obviously, this is a mounted volume! } else { // an ordinary directory junction. }
- Q: But it's interesting what '\\?\Volume{...' hides inside?
A: It's easy as a pie. Call theFSF.GetPathRoot(JuncName,Root);
function that returns the real root directory in one of two forms:"D:\"
"\\?\Volume{..."
The second case is turbid :-) - apparently at the system level (from the disk manager) someone has deleted the letter assigned to this disk... One might say, in order not to see it ;-) - Q: Can I get some more useful info about symbolic links?
A: Of course you can :-) Really, not entirely about symbolic links, but...
We can, for example, get a portion of information about the mounted volumes. It's simple - call the standard GetVolumeInformation()function.
In other words, we know the root already -"GetPathRoot(JuncName,Root);"
, it remained only to get the information (e.g., file system extended attributes support - compression, encryption, and file system type):DWORD FileSystemFlags; char FSysName[NM]; if (GetVolumeInformation(Root,NULL,0,NULL,NULL, &FileSystemFlags,FSysName,sizeof(FSysName))) { if (FileSystemFlags & FS_FILE_COMPRESSION) { // file system supports file compression } if (FileSystemFlags & FS_FILE_ENCRYPTION) { // file system supports file encryption } }
A typical function to check the ability of hard link creation looks like that:BOOL CanCreateHardLinks(char *TargetFile,char *HardLinkName) { char RootTarget[NM],RootHardLink[NM],FSysName[NM]; GetPathRoot(TargetFile,RootTarget); GetPathRoot(HardLinkName,RootHardLink); if(!strcmp(RootTarget,RootHardLink)) // the same root (the same volume)? { // NTFS drive? DWORD FileSystemFlags; if(GetVolumeInformation(RootTarget,NULL,0,NULL,NULL,&FileSystemFlags, FSysName,sizeof(FSysName))) { if(!strcmp(FSysName,"NTFS")) return TRUE; } } return FALSE; }
- Q: Can I get the changed/unchanged flags for the file being edited? I didn't find that, but FAR knows about that and displays an asterisk in the first line.
A: See the EditorInfo structure description, specifically the EditorInfo.CurState field values.
- Q: How can I get the name of the file loaded in viewer?
A: This code gets the current file name in the viewer:WindowInfo wi; wi.Pos=-1; Info.AdvControl(Info.ModuleNumber,ACTL_GETWINDOWINFO,&wi);
That's all. File name is in wi.Name. - Q: Is it possible in FSF.ProcessName to get TRUE, when comparing "OUTBOUND\\????????.MO?"
mask and "C:\\FILES\\OUTBOUND\\0000ee2c.mod" file, but to get FALSE with "C:\\MUSIC\\assol_1.mod"?
PN_SKIPPATH is a wrong approach. When "\\" is in the mask it won't ever return TRUE.
A: Compare with the "*\\OUTBOUND\\????????.MO?" mask without using the PN_SKIPPATH. - Q: How does Windows dump the file name from the Explorer to the console window?
A: Vasily Titsky: "...Briefly, when inserting text into the console application (through the system menu or through the link drag-and-drop) the kind OS does the following: if the next symbol code is not within the current application Keyboard Layout (current language is English, but we need to insert a Russian symbol; or vice versa), system "emulates" the input of this symbol through the Alt+digits. For example, when inserting Russian 'A' , the following will be generated: press Alt, press '1', release '1', press '2', release '2', press '8', release '8', release Alt. When inserting symbols with codes below 99 (? - I didn't check this) the pressing of two digits is generated. We only have to detect it correctly and then handle it..." - Q: ProcessKey doesn't work for some reason...
I write in Delphi:
function ProcessKey(hPlugin: THandle; Key: Integer; ControlState: Word): integer; stdcall; begin windows.Beep(300,200); //return False in order to be processed by FAR itself result:=0; end;
Any key pressing should be followed by a beep - but there are no beeps. The same is for any particular key.
A: FAR calls the ProcessKey function for the active plugin panel only. - Q: How can a plugin position the cursor on a specific file?
A:{ struct PanelInfo PInfo; Info.Control(INVALID_HANDLE_VALUE,FCTL_GETPANELINFO,&PInfo); // set cursor position on the selectItem panel item struct PanelRedrawInfo PRI; char Name[NM], Dir[NM*5]; int pathlen; strcpy(Name,Info.FSF->PointToName(selectItem)); pathlen=Info.FSF->PointToName(selectItem)-selectItem; if(pathlen) memcpy(Dir,selectItem,pathlen); Dir[pathlen]=0; Info.FSF->Trim(Name); Info.FSF->Trim(Dir); Info.FSF->Unquote(Name); Info.FSF->Unquote(Dir); if(*Dir) Info.Control(INVALID_HANDLE_VALUE,FCTL_SETPANELDIR,&Dir); Info.Control(INVALID_HANDLE_VALUE,FCTL_GETPANELINFO,&PInfo); PRI.CurrentItem=PInfo.CurrentItem; PRI.TopPanelItem=PInfo.TopPanelItem; for(int J=0; J < PInfo.ItemsNumber; J++) { if(!Info.FSF->LStricmp(Name,Info.FSF->PointToName(PInfo.PanelItems[J].FindData.cFileName))) { PRI.CurrentItem=J; PRI.TopPanelItem=J; break; } } Info.Control(INVALID_HANDLE_VALUE,FCTL_REDRAWPANEL,&PRI); }
- Q: How can a plugin run a program? And show its output under the panels?
A:Info.Control(INVALID_HANDLE_VALUE,FCTL_GETUSERSCREEN,NULL); if (CreateProcess(NULL,"ls.exe",NULL,NULL,TRUE,0,NULL,NULL,&si,&pi)) { WaitForSingleObject( pi.hProcess, INFINITE ); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } Info.Control(INVALID_HANDLE_VALUE,FCTL_SETUSERSCREEN,NULL);
Dialogs
- Q: Can I somehow overcome the edit window limitation, where the macro sequence is limited to 512 characters?
A: It's the FAR dialog property. In the FarDialogItem structure the Data field size is 512 characters. (the answer is relevant for FAR Manager 1.70 beta 2 and earlier; see the DIF_VAREDIT flag description)
- Q: If I don't use the Dialog function to work with dialog, how can I handle the data input? Should I write that myself?
A: You can write that yourself :-) But you can also use the DialogAPI...
- Q: If I use the Dialog function and an input line within it, will the ProcessEditorInput and ProcessEditorEvent functions work for this control element?
A: No, they won't. Use the DialogEx function instead.
- Q: Can I change elements like Static (their captions) dynamically in a dialog?
A: It depends on the dialog type used. After the dialog creation and Dialog function call, you can't. But you can close the dialog, change its caption and recreate the dialog. If you do all that in a sequence it will be rather fast.
If you use the DialogEx function, you can send the DM_SETTEXT message to the DialogAPI from the function that handles the dialog.
- Q: OK, I use the DialogAPI, but the set of control elements handled by FAR isn't sufficient for me.
A: Use the DI_USERCONTROL element. It handles the element drawing and controls it - the plugin can do all the stuff!
- Q: Why the ListBox and ComboBox are so crude? I can't deal with them in a usual way - I have to extricate from this problem in order to add or delete them.
A: What do you want from the very first version of the DialogAPI?
- Q: Why the buttons for closing the window don't work in the "new-style" dialog?
A: "Old-style" ones don't have a handler. It's no wonder that their behavior should be the same as in FAR 1.65 and earlier.
"New-style" ones use a handler. You should handle the dialog closing yourself, except for: Ctrl-Break - always closes, Ctrl-Enter - closes if there exists at least one button with field DefaultButton=1, then a Close request with Param1 = current element number, Esc and F10 can be handled from the handler - should the dialog close or not.
- Q: Should I close the dialog myself from now on?
A: If you use a dialog handler - YES, you should: catch the DN_BTNCLICK event, check Param1 for match with required number and send the DM_CLOSE message to the dialog core.
- Q: If I use the mouse, should I catch the DN_MOUSECLICK?
A: It's to your discretion :-) First, a mouse message comes (ignore it), then the DN_BTNCLICK comes right after it...
- Q: Should I handle the DefaultButton myself as well?
A: No, you don't have to. For DefaultButton, the sequence is like that: [DN_MOUSECLICK -> ] DN_BTNCLICK -> DM_CLOSE.
- Q: Somehow it turned out that in no way the SEPARATOR could reach the frame right edge, but it got recovered when I rewrote everything from scratch.
A: See the comments for the DIF_SEPARATOR flag.
- Q: Can I somehow disable the automatic selection of elements using mouse in lists (when mouse hovering over the list selects the element, particularly if this list is not active)?
A: Partially, you can. See the DM_LISTSETMOUSEREACTION