Recent

Author Topic: Automatic font change  (Read 40538 times)

rick2691

  • Sr. Member
  • ****
  • Posts: 444
Automatic font change
« on: October 19, 2016, 08:45:14 pm »
My effort to match font metrics by choosing compatible fonts failed. With one line it worked, but after doing several it failed.

Researching I found there is a function to turn off font swapping. Unfortunately RichMemo doesn't appear to have full functionality with the process.

It involves EM_GETLANGOPTIONS and EM_SETLANGOPTIONS, which also requires the parameter of IMF_AUTOFONT. The IMF_AUTOFONT parameter is what seems to be missing.

With that parameter... PageMemo.Perform(EM_SETLANGOPTIONS, 0,
                       LPARAM(PageMemo.Perform(EM_GETLANGOPTIONS, 0, 0)
                       and (not IMF_AUTOFONT))); 
...is supposed to work.

Alternately... //turn off richedit's auto font switching...
      i := SendMessage(PageMemo.Handle, EM_GETLANGOPTIONS, 0, 0);
      i := i and not IMF_AUTOFONT;
      SendMessage(PageMemo.Handle, EM_SETLANGOPTIONS, 0, i); 
...is also supposed to work.

But RichMemo does not have IMF_AUTOFONT registered.

A link to show how the parameter is managed is in... http://www.diicode.com/code/esijxny9-1257602

Can you look into it for me?

Rick
« Last Edit: October 19, 2016, 09:07:51 pm by rick2691 »
Windows 11, LAZ 2.0.10, FPC 3.2.0, SVN 63526, i386-win32-win32/win64, using windows unit

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Automatic font change
« Reply #1 on: October 19, 2016, 09:20:26 pm »
sure. tonight EST.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Automatic font change
« Reply #2 on: October 20, 2016, 06:17:55 am »
Here's a sample.

Code: Pascal  [Select][+][-]
  1. const
  2.   IMF_AUTOKEYBOARD                  = $0001;
  3.   IMF_AUTOFONT                        = $0002;
  4.   IMF_IMECANCELCOMPLETE   = $0004;      // high completes the comp string when aborting, low cancels.
  5.   IMF_IMEALWAYSSENDNOTIFY = $0008;
  6.  
  7. procedure TForm1.Button1Click(Sender: TObject);
  8. var
  9.   opt : LResult;
  10. begin
  11.   opt:=SendMessage(RichMemo1.Handle, EM_GETLANGOPTIONS, 0, 0);
  12.   opt:=opt and not IMF_AUTOFONT; // disable autofont
  13.   SendMessage(RichMemo1.Handle, EM_SETLANGOPTIONS, 0, LParam(opt));
  14. end;  
  15.  

rick2691

  • Sr. Member
  • ****
  • Posts: 444
Re: Automatic font change
« Reply #3 on: October 20, 2016, 02:59:57 pm »
I am posting an entire code section, in case there is a problem with where I am executing the code.

There is an odd behavior... when doing English in a mixed language line, any punctuations are stepping backwards as if it thinks that I am attempting to resume Hebrew. If I hit an English key it repositions to the proper English placement. This is the same behavior that Hebrew writing was doing with punctuations.

I assume that the constants may have some wrong values.

Besides this problem, the first objective has failed, it is not turning font swapping off.

Isn't EM_GETLANGOPTIONS returning a Byte value that represents a Set of operators?

I have wondered all along as to how...

opt:=opt and not IMF_AUTOFONT;

... could work. It may be a Delphi method. Likewise, isn't it testing for a true/false condition instead of a value?

One programmer I found had commented... "And for Lister's TRichEdit this flag is set by default (flags=0x83), but when I've removed it (set flags to 0x82), layout didn't switch anymore!"

Code: Pascal  [Select][+][-]
  1. procedure TCmdForm.btnOpenClick(Sender: TObject);
  2. var
  3.   fs: TFileStream;
  4.   opt : LResult;
  5. const
  6.   IMF_AUTOKEYBOARD  = $0001;
  7.   IMF_AUTOFONT = $0002;
  8.   IMF_IMECANCELCOMPLETE = $0004;     // high completes the comp string when aborting, low cancels.
  9.   IMF_IMEALWAYSSENDNOTIFY = $0008;
  10. begin
  11.   OpenDialog1.Title:= 'Select File';
  12.   OpenDialog1.Filter:= 'Rich Files (*.rtf)|*.rtf|Text Files (*.txt)|*.txt';
  13.   OpenDialog1.FileName:= '';
  14.   if OpenDialog1.Execute then
  15.   begin
  16.     fs := nil;
  17.     try
  18.       BuildPageMemo; // starts new tab and adds untitled PageMemo
  19.       DiskName:= OpenDialog1.Filename;
  20.       FileLabel:= ExtractFileName(Diskname);
  21.       FilePath:= ExtractFilePath(Diskname);
  22.       FileType:= lowercase(ExtractFileExt(Diskname));
  23.  
  24.       // turn font substitution off...
  25.       opt:=SendMessage(PageMemo.Handle, EM_GETLANGOPTIONS, 0, 0);
  26.       opt:=opt and not IMF_AUTOFONT; // disable autofont
  27.       SendMessage(PageMemo.Handle, EM_SETLANGOPTIONS, 0, LParam(opt));
  28.  
  29.       if FileType='.rtf' then
  30.          begin
  31.          // Utf8ToAnsi is required for windows stream
  32.          try fs:= TFileStream.Create(Utf8ToAnsi(DiskName), fmOpenRead or fmShareDenyNone);
  33.              PageMemo.LoadRichText(fs);
  34.              PageMemo.Hint:= DiskName; //OpenDialog1.Filename;
  35.              finally
  36.              fs.Free;
  37.              end;
  38.          end;
  39.  
  40.       if FileType='.txt' then
  41.          begin
  42.          PageMemo.Lines.LoadFromFile(DiskName);
  43.          x:= pos('.',FileLabel);
  44.          if x>0 then TabLabel:=Copy(FileLabel,1,x-1);
  45.          FileType:= '.rtf';
  46.          PageMemo.hint:= FilePath+TabLabel+'.rtf';
  47.          showmessage('Text-File will save as a Rich-File');
  48.          SavePageTab;
  49.          end;
  50.  
  51.       x:= pos('.',FileLabel);
  52.       if x>0 then TabLabel:=Copy(FileLabel,1,x-1);
  53.       PageControl1.ActivePage.Caption:= TabLabel; //FileLabel;
  54.  
  55.       BackupPageTab(Self);
  56.       StatusBar1.SimpleText:= ' '+ExtractFilePath(PageMemo.Hint);  //PageMemo.Hint;
  57.     finally
  58.     end;
  59.   end;
  60. end;  
  61.  

Rick
Windows 11, LAZ 2.0.10, FPC 3.2.0, SVN 63526, i386-win32-win32/win64, using windows unit

rick2691

  • Sr. Member
  • ****
  • Posts: 444
Re: Automatic font change
« Reply #4 on: October 20, 2016, 03:17:00 pm »
Here is the first introduction to turning off font swapping...

http://archives.miloush.net/michkap/archive/2006/02/13/531110.html

It's first form was in C++ (or another C thing)

Rick
Windows 11, LAZ 2.0.10, FPC 3.2.0, SVN 63526, i386-win32-win32/win64, using windows unit

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Automatic font change
« Reply #5 on: October 20, 2016, 03:39:03 pm »

Isn't EM_GETLANGOPTIONS returning a Byte value that represents a Set of operators?

I have wondered all along as to how...

opt:=opt and not IMF_AUTOFONT;

... could work. It may be a Delphi method. Likewise, isn't it testing for a true/false condition instead of a value?
Yes, it is. But using bitwise operators is more straight forward way.
Besides, EM_GETLANGOPTIONS doesn't return byte, it returns LRESULT (which is 32-bit on 32-bit machines, and 64-bit on 64-bit machines).
Thus assuming it's byte, there's a potential risk of loosing data.

That's why I prefer to do low-level interaction via bitwise operations, rather than building "set of" type on top of it. (using "set of" with a high-level interface is 100% fine)

rick2691

  • Sr. Member
  • ****
  • Posts: 444
Re: Automatic font change
« Reply #6 on: October 20, 2016, 05:14:06 pm »
What about the "odd behavior" that I cited on Reply #3, and that it had not turned off the font switching?

Rick
Windows 11, LAZ 2.0.10, FPC 3.2.0, SVN 63526, i386-win32-win32/win64, using windows unit

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Automatic font change
« Reply #7 on: October 20, 2016, 06:01:39 pm »
What about the "odd behavior" that I cited on Reply #3, and that it had not turned off the font switching?
Remember, you've had a similar problem with spaces and commas.
When you wanted them to be Hebrew, RichMemo (richedit) put them as English.
Thus you added a special RTF insert, to force the language.

Is it possible that this code actually takes effect?

rick2691

  • Sr. Member
  • ****
  • Posts: 444
Re: Automatic font change
« Reply #8 on: October 20, 2016, 07:15:52 pm »
I will check. But I just found that my English portion that I had cited was operating with a swapped font. That was why it was acting like that.

I checked the opt computation. It is EM_SETLANGOPTIONS sets it to 130. Your "and not IMF_AUTOFONT" code sets it to 128 ...so it is correct.

It must be that I am activating the "no switch" code at the wrong time, because it doesn't do anything.

But one programmer commented that RichEdit 3 had altered the EM_GETLANGOPTIONS method. He said he had to go back to version 2. When he did it operated fine. He did not specify what was changed. Do you think that our current version has assigned a different value to IMF_AUTOFONT.

Rick
Windows 11, LAZ 2.0.10, FPC 3.2.0, SVN 63526, i386-win32-win32/win64, using windows unit

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Automatic font change
« Reply #9 on: October 20, 2016, 07:23:40 pm »
But one programmer commented that RichEdit 3 had altered the EM_GETLANGOPTIONS method. He said he had to go back to version 2. When he did it operated fine. He did not specify what was changed. Do you think that our current version has assigned a different value to IMF_AUTOFONT.
I'm thinking that the solution is very fragile.
It's not just going back to some version, it also depends on how this old-version is implemented for a certain system. That's quite a blackbox, and it's up to MS how things will work.

rick2691

  • Sr. Member
  • ****
  • Posts: 444
Re: Automatic font change
« Reply #10 on: October 20, 2016, 09:38:11 pm »
The specifications, posted as follows, indicate that the options have values of 1 or 0 for being on or off respectively. Does that indicate that it is a string values for a set? But EM_GETLANGOPTIONS returns a single value, and it is 130... very large.

https://msdn.microsoft.com/en-us/library/windows/desktop/bb788040(v=vs.85).aspx
Windows 11, LAZ 2.0.10, FPC 3.2.0, SVN 63526, i386-win32-win32/win64, using windows unit

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Automatic font change
« Reply #11 on: October 20, 2016, 09:46:30 pm »
But EM_GETLANGOPTIONS returns a single value, and it is 130... very large.
That is because the value returned is value that can consist of multiple flags. Those names listed all represent a bit (or bit combination) and as such are flags. Figure out which bit it is that you need and filter it from that return value.

e.g.
IMF_AUTOFONT = $2;

If returnvalue and IMF_AUTOFONT <> 0 then BitIsOn else BitIsOff

Or did i misunderstood what you did not understood ?  :)
« Last Edit: October 20, 2016, 09:53:03 pm by molly »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Automatic font change
« Reply #12 on: October 20, 2016, 09:52:33 pm »
It's a bit mask. You can read about that in description of EM_SETLANGOPTIONS
"This message sets the values of all language option flags" (where a flag is a bit)

Values for each of the option (or a flag) comes in Richedit.h which is part of MSDN.
Pascal (obviously) is lagging behind and some constants might not be present in richedit.pas.

However, finding actual values is easy. you can simply google for "define IMF_DUALFONT" and it should bring you quickly to the latest RichEdit.h (i.e. here)

The value 130 means corresponds to hexidemical value $82. (I'm using dollar sign, since it's pascal convention)
And that corresponds to two flags:
IMF_AUTOFONT = $0002
IMF_DUALFONT = $0080
IMF_AUTOFONT or IMF_DUALFONT= $82=130
Bitwise operations.

Now, whenever you write an expression like this:
Code: [Select]
  opt:=opt and not IMF_AUTOFONT;
where opt originally is 130, what you get is the following:

not IMF_AUTOFONT is $FFFFFFFD (it's missing bit $2 )

$82 and $FFFFFFFD = $80  ($8 - matched, $2 didn't match)
That's how you end up with 128 (=$80).
Even though 128 might look a very high value... it's actually only 1 flag!
In the same way 130 is actually 2 flags... and so on.

"set ofs" are operating in the similar manner (as long as set is declared as a bitwise set)
« Last Edit: October 20, 2016, 09:54:26 pm by skalogryz »

rick2691

  • Sr. Member
  • ****
  • Posts: 444
Re: Automatic font change
« Reply #13 on: October 20, 2016, 10:31:22 pm »
It looks like this is another dead horse. It is the stupidest thing that I have seen Microsoft do. Their own fonts don't look good, or they don't do 0 based vowels, or they don't do every language, or they don't handle diacritics properly... and they force us to use one font in an entire paragraph. If we try to use another, they switch it to one of their own wimpy fonts. They even swapped out a Greek font for an Arabic font.

My definition of a "control freak" is a person who insists on managing things, and has no clue as to how to do it.

Rick
Windows 11, LAZ 2.0.10, FPC 3.2.0, SVN 63526, i386-win32-win32/win64, using windows unit

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Automatic font change
« Reply #14 on: October 20, 2016, 10:35:48 pm »
Try to take multilingual text to Wordpad. See how it behaves.

Purpose of such test:
Wordpad is pretty much how RichEdit behaves by default. It doesn't have richmemo on top as well as any of your code. It would also behave its best.

If it doesn't act the way you like, there's a slight chance, that you won't be able to make Richmemo to work.

Also. RichEdit might behave much better, if you install corresponding language layouts to your system, and would use them to type the text in.

This has been Microsoft policy for years - make it nice and easy for an end user. Not a developer :) (What makes sense to some extent)

 

TinyPortal © 2005-2018