- 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: DeleteFile or 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 use FA_DIREC (or FILE_ATTRIBUTE_DIRECTORY) file attribute to do that.
Let's continue.
We know for sure that any symbolic link (or reparse point) in
Win2K has a FILE_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 the
FSF.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);