Detect file Code Page by viewer/editor plugin.

A place where plug-in developers can share their knowledge and experience.
Post Reply
olesio
Posts: 12
Joined: Sat 18 Jun, 2011 14:02

Detect file Code Page by viewer/editor plugin.

Post by olesio »

Hello. I did not post here from long time.

I googled, but do not find any solution. So I ask here. How to check what code page is for loaded file in FAR viewer/editor? I want to make simple plugin in Delphi which simulate F8 key press or change code page like for F8 key pressed. It is useful for *.nfo files which contain ASCII logos.

Now I'm using my own loader associeted with Total Commander F3/F4, key which execute FAR in ConEmu. And when filename have .nfo extension it simulate F8 key pressing. But it do not work perfectly for all files, which sometimes load too slow. Or some non .nfo files which contain ASCII which need to press F8 key to display corectly. And CodePage as far as I know is visible only in FAR Editor by pressing Shift+F2 code.

Summary. So I want do something like that. If code page of file is not 852 (OEM) simulate press F8. Do I must do some detection of file content and if it contain some chars used in ASCII logos, then simulate press F8? But what values should it be, greater than decimal: 128? Greater than decimal: 174? Or some else value?

Please give me some hints or code examples. Thanks in advance. And sorry for my bad English.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Detect file Code Page by viewer/editor plugin.

Post by John Doe »

Using FAR Plugins API you can execute some code on load of every file, and change codepage if needed.
Here is sample code in lua:
  1. local F = far.Flags
  2.  
  3. local OEM = win.GetOEMCP()
  4.  
  5. Event{
  6.  
  7.   group="EditorEvent";
  8.  
  9.   description="Set OEM CP on open some files";
  10.  
  11.   filemask="*.nfo,*.diz";
  12.  
  13.   uid="B7A2A2B8-DEF8-490E-BCAC-DBB6F058F757";
  14.  
  15.   condition=function(id,Event) return Event==F.EE_READ end;
  16.  
  17.   action=function(id,Event)
  18.  
  19.     editor.SetParam(nil,F.ESPT_CODEPAGE,OEM)
  20.  
  21.   end;
  22.  
  23. }
  24.  
  25.  
  26.  
  27. Event{
  28.  
  29.   group="ViewerEvent";
  30.  
  31.   description="Set OEM CP on open some files";
  32.  
  33.   filemask="*.nfo,*.diz";
  34.  
  35.   uid="581E6B89-860E-44BE-A41F-39FB359B94BF";
  36.  
  37.   condition=function(id,Event) return Event==F.VE_READ and Area.Viewer end;
  38.  
  39.   action=function(id,Event)
  40.  
  41.     if viewer.GetInfo().CurMode.CodePage~=OEM then mf.postmacro(Keys,"F8") end
  42.  
  43.   end;
  44.  
  45. }
olesio
Posts: 12
Joined: Sat 18 Jun, 2011 14:02

Re: Detect file Code Page by viewer/editor plugin.

Post by olesio »

Thanks for answer. But I must use excaly my old "Far Manager, version 3.0 (build 3900) x86"., Because new, x86 stable version downloaded from official FAR site always hangs up when view files or most cases of edit files by my loader which execute ConEmu. I tested under one nfo file. My loader is executed from Total Commander under F3 and/or F4 keys. And this old FAR version do not allow use exacly code of lua file which you gave me.

My loader in WinAPI with Delphi 7 code is available at: http://olesio.eu/far/far_loader_2.rar

And my plugin which after few tests looks to work fine. Also in WinAPI with Delphi 7 source is avaiable at: http://olesio.eu/far/far_plugin_ascii_nfo.rar

But how to make SetParam(nil,F.ESPT_CODEPAGE,OEM) in Code? And how to simulate F8 key for viewer not by Keybd_Event or SendInput API functions. I want to simulate using FAR plugin SDK methods if possible. Please give me some code example. Also it possible to detect that user pressed F8 to swap codepage? Current my plugin source code below.

Sorry for long message and once again my bad English.

Code: Select all

library ascii_nfo;

uses
  Windows,
  plugin in 'plugin.pas';

const
  Plugin_Ver = '0.1';
  Begins_Ascii_Range = 174;
  Plugin_Title = 'ASCII *.nfo files Code Page';

var
  FileLoadedByEdit : boolean;
  FarApi : TPluginStartupInfo;
  PluginStrings : array[0..0] of PChar;

procedure SendF8KeyToFAR;
begin
  Keybd_Event(VK_F8, 0, 0, 0);
  Keybd_Event(VK_F8, 0, KEYEVENTF_KEYUP, 0);
end;

function ReadTextFromFile(AFileName : string; var OutStr : string) : boolean;
var
  BytesRead : DWORD;
  SrcFile : THandle;
  SrcFileSize : Int64;
begin
  OutStr := '';
  SrcFile := CreateFile(PChar(AFileName), GENERIC_READ, FILE_SHARE_READ or
    FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  Result := SrcFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    SrcFileSize := GetFileSize(SrcFile, nil);
    SetLength(OutStr, SrcFileSize);
    ReadFile(SrcFile, OutStr[1], SrcFileSize, BytesRead, nil);
    CloseHandle(SrcFile);
  end;
end;

function TextHaveInfoFileChar(AText : string) : boolean;
var
  I : Byte;
begin
  for I := Begins_Ascii_Range to High(Byte) do
  begin
    Result := Pos(Char(I), AText) > 0;
    if Result then
    begin
      Break;
    end;
  end;
end;

procedure SetOEMCodePage(AFileName : string);
var
  Str : string;
begin
  if ReadTextFromFile(AFileName, Str) then
  begin
    if TextHaveInfoFileChar(Str) then
    begin
      SendF8KeyToFAR;
    end;
    Str := '';
  end;
end;

procedure GetPluginInfo(var Info : TPluginInfo); stdcall;
begin
  with Info do
  begin
    StructSize := SizeOf(Info);
    Flags := PF_VIEWER or PF_EDITOR;
    DiskMenuStringsNumber := 0;
    PluginStrings[0] := Plugin_Title;
    PluginMenuStrings := @PluginStrings;
    PluginMenuStringsNumber := 1;
    PluginConfigStringsNumber := 0;
    CommandPrefix := nil;
  end;
end;

procedure SetStartupInfo(var PSI : TPluginStartupInfo); stdcall;
begin
  Move(PSI, FarApi, SizeOf(FarApi));
end;

function OpenPlugin(OpenFrom : integer; Item : Integer) : THandle stdcall;
var
  Msg : array[0..4] of PChar;
begin
  Msg[0] := Plugin_Title + ' v' + Plugin_Ver;
  Msg[1] := 'Plugin made by olesio (E-Mail: oles[at]o2.pl)';
  Msg[2] := 'Plugin allow you to open most of files with a';
  Msg[3] := 'properly CP Code Page to display *.nfo files.';
  Msg[4] := #01#00;
  MSg[4] := 'OK';
  FARAPI.Message(FARAPI.ModuleNumber, FMSG_NORMAL, '', @Msg, Length(Msg), 1);
  Result := 0;
end;

function ProcessViewerEvent(Event : integer; Param : Pointer) : integer; stdcall export;
var
  VI : TViewerInfo;
  FullFileName : string;
begin
  if Event = VE_GOTFOCUS then
  begin
    FarApi.ViewerControl(VCTL_GETINFO, @VI);
    FullFileName := VI.FileName;
    if not FileLoadedByEdit then
    begin
      SetOEMCodePage(FullFileName);
    end;
    FileLoadedByEdit := True;
  end;
  Result := 0;
end;

function ProcessEditorEvent(Event : integer; Param : Pointer) : integer; stdcall export;
var
  EI : TEditorInfo;
  FullFileName : string;
begin
  if Event = EE_REDRAW then
  begin
    FarApi.EditorControl(ECTL_GETINFO, @EI);
    FullFileName := EI.FileName;
    if not FileLoadedByEdit then
    begin
      SetOEMCodePage(FullFileName);
    end;
    FileLoadedByEdit := True;
  end;
  Result := 0;
end;

exports
  OpenPlugin,
  GetPluginInfo,
  SetStartupInfo,
  ProcessViewerEvent,
  ProcessEditorEvent;

begin
  FileLoadedByEdit := False;
end.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Detect file Code Page by viewer/editor plugin.

Post by John Doe »

olesio wrote:And this old FAR version do not allow use exacly code of lua file which you gave me.
Really? Is there any error message?
olesio wrote:But how to make SetParam(nil,F.ESPT_CODEPAGE,OEM) in Code?
Search in api by ESPT_CODEPAGE keyword.
It is for editor only.
olesio wrote:And how to simulate F8 key for viewer not by Keybd_Event or SendInput API functions.
Use MCTL_SENDSTRING with SequenceText Keys"F8".
olesio wrote:Also it possible to detect that user pressed F8 to swap codepage?
Search ProcessEditorInputW (editor only).
But why do you want to detect it?
olesio wrote:Sorry for long message and once again my bad English.
Don't worry, English is not native for most of us.

As for you code.

VE_GOTFOCUS and EE_REDRAW are not appropriate events.
Use VE_READ and EE_READ instead: they come only once.
pepak
Posts: 604
Joined: Sun 13 Jul, 2008 11:18
Has thanked: 17 times
Been thanked: 54 times

Re: Detect file Code Page by viewer/editor plugin.

Post by pepak »

Wouldn't using the Shift+F8 menu solve your problem? Regardless of which codepage is selected, you can press Shift+F8, HOME, DOWN, ENTER to select the OEM codepage...
olesio
Posts: 12
Joined: Sat 18 Jun, 2011 14:02

Re: Detect file Code Page by viewer/editor plugin.

Post by olesio »

Quotes of @John Doe answers below.
Really? Is there any error message?
As far as I remember something wrong with 18 line. Some missing "action" feature. Ofcourse new version of FAR and LUA plugin works fine. But when I tried update LUA Plugin without updating FAR, I had another errors. Probable newer plugin have some new features in code which are not accepted by old FAR. And like I wrote I do not want to update FAR becasue I have too much problems with ConEmu, which in most cases hangs up when viewing/editing files by F3/F4 key from Total Commander. I prefer Total Commander, but for viewing and fast edit files I'm using in most cases FAR. Because I like full screen console view and font. Also I use ExtCom plugin for syntax highlighting and compile *.dpr and *.pp files.
Search in api by ESPT_CODEPAGE keyword.
It is for editor only.
Thanks I try to use it some how. I seen it in API Pascal Header file, but did not realize how to use it correctly.
Use MCTL_SENDSTRING with SequenceText Keys"F8".
What method allow me to send it? I cannot find some example Googling fot "far plugin MCTL_SENDSTRING".
Search ProcessEditorInputW (editor only).
But why do you want to detect it?
Uh, only editor - too bad. And I want to detecting in following case. User view nfo file with F3, F8 is simulated, but he press F8 button by himself, Now he/she press F6 and nfo is not displayed ok. I thought it is good idead to set again prefered code page by F8 key. But ok, maybe you have right. If user swap code page that means he want to display it like he/she see text now. Ofcourse plugin is for my easy FAR editor usage only. But maybe in future I public it and someone other may use it in that way like I think.
VE_GOTFOCUS and EE_REDRAW are not appropriate events.
Use VE_READ and EE_READ instead: they come only once.
I used GOTFOCUS event, because from my tests (maybe it is caused by old FAR build) when I view or edit file included in packed archive under Total Commander and it is copied to %TEMP%, FAR have empty file name. And when I use FOCUS event all is ok. And way which I coded event detection and global boolean variable was think by me when test it plugin and do many combinations, like first view/edit later press F6, and F6 again etc. And way like plugin works now it is satisfactory for me.

@pepak: if I understand Shift+F8 GUI and help informations good, it does not work like I want. Because I must select code page manually. And autodetect do not work. And I want to do this full automatic super hiper simple ;) And my plugin at this moment works like I want it to work.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Detect file Code Page by viewer/editor plugin.

Post by John Doe »

olesio wrote: I have too much problems with ConEmu, which in most cases hangs up when viewing/editing files by F3/F4 key from Total Commander
Are you able to reproduce hangup without Conemu? Or without Total Commander?
olesio wrote:
Use MCTL_SENDSTRING with SequenceText Keys"F8".
What method allow me to send it? I cannot find some example Googling fot "far plugin MCTL_SENDSTRING".
Perhaps your google is broken.
See http://far-plugins.googlecode.com/svn/t ... arCtrl.pas
olesio
Posts: 12
Joined: Sat 18 Jun, 2011 14:02

Re: Detect file Code Page by viewer/editor plugin.

Post by olesio »

Are you able to reproduce hangup without Conemu? Or without Total Commander?
FAR executed normally without ConEmu do not hangs up. I think Total Commander have nothing with that problem. Probable reason is in my opinion stupid feature in ConEmu, which need to show any key press prompt and error code,

if ConEmu was closed faster than 10 seconds after open it. I do not know how to switch off. So in old ConEmu dlls I just patched using IDA and HIEW and it always close without waiting. Anyway, right now I must use old ConEmu and old FAR build. Because I prefer to view FAR on full screen window without any console window title bar.

Hangs up in 99% cases are only when I view file by F3 under Total Commander. When I choose F4 to edit, file close ok without problem after exit And do not hangs up. And thanks for source code example. I try to do something later by myself with it.
Post Reply

Return to “Plug-In Developers”