Recent

Author Topic: [SOLVED] KMemo - Search Text with images in it  (Read 443 times)

pixelink

  • Hero Member
  • *****
  • Posts: 1028
    • Pixelink Media
[SOLVED] KMemo - Search Text with images in it
« on: July 21, 2019, 09:24:31 pm »
Hi,

I am trying to build demo of being able to search and highlight text using the KMemo control.

I have a working demo that does highlight the text, but it doesn't highlight the right text and its Pos if off as it goes through the text.

Can anyone help me figure this out?


Here is my entire code


Code: Pascal  [Select]
  1.  
  2. unit Unit1;
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, kmemo,
  10.   strutils,LazUTF8;
  11.  
  12. type
  13.  
  14.   { TForm1 }
  15.  
  16.   TForm1 = class(TForm)
  17.     Button1: TButton;
  18.     Edit1: TEdit;
  19.     KMemo1: TKMemo;
  20.     procedure Button1Click(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.   private
  23.  
  24.   public
  25.     function FindInMemo(AMemo: TKMemo; AString: String; StartPos: Integer): Integer;
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.FormCreate(Sender: TObject);
  38. begin
  39.   KMemo1.LoadFromFile('help.rtf');
  40. end;
  41.  
  42. procedure TForm1.Button1Click(Sender: TObject);
  43. const
  44.   SearchStr: String = '';                     // The string to search for
  45.   SearchStart: Integer = 0;                   // Last position of the string to search for
  46. begin
  47.   if SearchStr <> Edit1.Text then begin      
  48.     SearchStart := 0;
  49.     SearchStr := Edit1.Text;
  50.   end;
  51.   SearchStart := FindInMemo(KMemo1, SearchStr, SearchStart + 1);
  52.  
  53.   if SearchStart > 0 then
  54.     Caption := 'Found at position['+IntToStr(SearchStart)+']!'
  55.   else
  56.     Caption := 'No further finds!';
  57.  
  58. end;
  59.  
  60. // FindInMemo: Returns the position where the string to search was found
  61. function TForm1.FindInMemo(AMemo: TKMemo; AString: String; StartPos: Integer): Integer;
  62. begin
  63.   Result := PosEx(AString, AMemo.Text, StartPos);
  64.   if Result > 0 then
  65.   begin
  66.     AMemo.SelStart := UTF8Length(PChar(AMemo.Text), Result - 1);
  67.     AMemo.SelLength := Length(AString);
  68.     AMemo.SetFocus;
  69.   end;
  70. end;
  71.  
  72. end.
  73.  
  74.  
« Last Edit: July 22, 2019, 04:01:10 pm by pixelink »
Can't Type - Forgetful - Had Stroke = Forgive this old man!

Pixelink Media •  My LAZ Software
LAZ 2.02 • Win10 • 16G RAM • Nivida GForce RTX 2060

pixelink

  • Hero Member
  • *****
  • Posts: 1028
    • Pixelink Media
Re: KMemo - Search Text with images in it
« Reply #1 on: July 21, 2019, 09:28:09 pm »
NOTE:

I believe the issue may come fro having to deal with KMemos block of line and caridge returns.


Also, on KMemos wiki is some code for searching, but it is missing the Click even, so I don't know what else if needed,

https://wiki.freepascal.org/KControls/KmemoNotes

This is all he provided...

Code: Pascal  [Select]
  1.  
  2.  
  3. function TForm1.Search(Term : ANSIString; StartAt : longint = 1; MoveCursor : Boolean = False) : longint;
  4. var
  5.     Ptr, EndP : pchar;
  6.     Offset   : longint;
  7.     NumbCR : longint;
  8. begin
  9.         Result := UTF8Pos(Term, KMemo1.Blocks.text, StartAt);
  10.         {$IFDEF WINDOWS}        // Sadley we need to subtract the extra CR windows adds to a newline
  11.         if Result = 0 then exit();
  12.         NumbCR := 0;
  13.         Ptr := PChar(KMemo1.Blocks.text);
  14.         EndP := Ptr + Result-1;
  15.         while Ptr < EndP do begin
  16.           if Ptr^ = #13 then inc(NumbCR);
  17.           inc(Ptr);
  18.         end;
  19.         Result := Result - NumbCR;
  20.         {$ENDIF}                        // does no harm in Unix but adds 66mS with my test note.
  21.     if MoveCursor then begin
  22.         KMemo1.SelStart := Result;
  23.         KMemo1.SelEnd := Result;
  24.         KMemo1.SetFocus;
  25.     end;
  26. end;
  27.  
Can't Type - Forgetful - Had Stroke = Forgive this old man!

Pixelink Media •  My LAZ Software
LAZ 2.02 • Win10 • 16G RAM • Nivida GForce RTX 2060

jamie

  • Hero Member
  • *****
  • Posts: 1765
Re: KMemo - Search Text with images in it
« Reply #2 on: July 21, 2019, 10:30:04 pm »
Isn't KMemo from an old set of components? I know there is a KStringGrid that basically is the same as we
have now..

pixelink

  • Hero Member
  • *****
  • Posts: 1028
    • Pixelink Media
Re: KMemo - Search Text with images in it
« Reply #3 on: July 21, 2019, 11:05:00 pm »
Isn't KMemo from an old set of components? I know there is a KStringGrid that basically is the same as we
have now..

Yeah, but it is the only RichEditor that supports images in read only mode.

RichMemo, doesn't support images when read Only is turned on.
Can't Type - Forgetful - Had Stroke = Forgive this old man!

Pixelink Media •  My LAZ Software
LAZ 2.02 • Win10 • 16G RAM • Nivida GForce RTX 2060

wp

  • Hero Member
  • *****
  • Posts: 6003
Re: KMemo - Search Text with images in it
« Reply #4 on: July 21, 2019, 11:42:08 pm »
Yeah, but it is the only RichEditor that supports images in read only mode.

RichMemo, doesn't support images when read Only is turned on.
I tested TRichMemo in your demo in place of the KMemo, and it puts the selection at the correct place. So, this seems to be a bug of KMemo. AFAIK, however, KMemo is no longer supported by its author. On the other hand, TRichMemo *is* supported by user skalogryz, and I think there's a good chance that he can fix the issue with images and ReadOnly state. Maybe you should file a bug report for RichMemo on Bug Tracker.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

pixelink

  • Hero Member
  • *****
  • Posts: 1028
    • Pixelink Media
Re: KMemo - Search Text with images in it
« Reply #5 on: July 22, 2019, 03:00:20 am »
Yeah, but it is the only RichEditor that supports images in read only mode.

RichMemo, doesn't support images when read Only is turned on.
I tested TRichMemo in your demo in place of the KMemo, and it puts the selection at the correct place. So, this seems to be a bug of KMemo. AFAIK, however, KMemo is no longer supported by its author. On the other hand, TRichMemo *is* supported by user skalogryz, and I think there's a good chance that he can fix the issue with images and ReadOnly state. Maybe you should file a bug report for RichMemo on Bug Tracker.

Yeah.. I discussed RichMemo with him, but he just kept saying images are not supported.
So, all I have that displays images with Read only is Kmemo.

I do have a demo with Memo too that works.

So, I am thinking that the images and hidden spaces are causing my Pos issue.


Boy, I do wish that LAz had a good working RTF comportment.
 ::)
« Last Edit: July 22, 2019, 03:30:22 pm by pixelink »
Can't Type - Forgetful - Had Stroke = Forgive this old man!

Pixelink Media •  My LAZ Software
LAZ 2.02 • Win10 • 16G RAM • Nivida GForce RTX 2060

dbannon

  • Hero Member
  • *****
  • Posts: 600
    • tomboy-ng, a rewrite of the classic Tomboy
Re: KMemo - Search Text with images in it
« Reply #6 on: July 22, 2019, 08:22:40 am »
Hi Pixelink, you are right, your issue relates to 'end of line markers'.  In Unix (ie Linux, Mac) we have but one character reserved to mark the end of a line. But Windows (and DOS), for reasons only know to a certain Mr Gates, we get two characters, a Carrage Return and a Line Feed. So, if you look into the KMemo1.Text you would see -

one<CR><LF>two<CR><LF>

Thats 10 characters in total (Gets more complicated using UTF8 but consistent).

PosEx will return  6 if you search for 'two' (but only 5 on Unix).

KMemo's char count always (sensibly) counts 1 char for a ParagraphBlock so your code will work fine under Linux (it does, I tested it) but I bet you are using windows ?

The code fragment from the wiki (my code!) counts how many addition characters have been inserted at the point we are interested in, subtracts that number from what PosEx() tells us, converting it into a number suitable to use as a KMemo character index.

I am afraid you really do need to use that extra code, no getting around it.

EDIT : KMemo is a great tool actually, I use it in tomboy-ng notes. I initially tried RichMemo but it is missing a number of functions. I have logged some but reports and patches, some used. Development is slow, I suspect skalogryz has his hands full getting Cocoa up to speed, important work !

On the other hand, TK will apply patches to KControls (inc KMemo) if you send them in. He is not willing to further develop it himself. And right now, its works a treat.


Davo
« Last Edit: July 22, 2019, 08:30:36 am by dbannon »
Lazarus 1.8, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng

pixelink

  • Hero Member
  • *****
  • Posts: 1028
    • Pixelink Media
Re: KMemo - Search Text with images in it
« Reply #7 on: July 22, 2019, 03:31:54 pm »
Hi Pixelink, you are right, your issue relates to 'end of line markers'.  In Unix (ie Linux, Mac) we have but one character reserved to mark the end of a line. But Windows (and DOS), for reasons only know to a certain Mr Gates, we get two characters, a Carrage Return and a Line Feed. So, if you look into the KMemo1.Text you would see -

one<CR><LF>two<CR><LF>

Thats 10 characters in total (Gets more complicated using UTF8 but consistent).

PosEx will return  6 if you search for 'two' (but only 5 on Unix).

KMemo's char count always (sensibly) counts 1 char for a ParagraphBlock so your code will work fine under Linux (it does, I tested it) but I bet you are using windows ?

The code fragment from the wiki (my code!) counts how many addition characters have been inserted at the point we are interested in, subtracts that number from what PosEx() tells us, converting it into a number suitable to use as a KMemo character index.

I am afraid you really do need to use that extra code, no getting around it.

EDIT : KMemo is a great tool actually, I use it in tomboy-ng notes. I initially tried RichMemo but it is missing a number of functions. I have logged some but reports and patches, some used. Development is slow, I suspect skalogryz has his hands full getting Cocoa up to speed, important work !

On the other hand, TK will apply patches to KControls (inc KMemo) if you send them in. He is not willing to further develop it himself. And right now, its works a treat.


Davo

Thanks, good info
Can't Type - Forgetful - Had Stroke = Forgive this old man!

Pixelink Media •  My LAZ Software
LAZ 2.02 • Win10 • 16G RAM • Nivida GForce RTX 2060

pixelink

  • Hero Member
  • *****
  • Posts: 1028
    • Pixelink Media
Re: KMemo - Search Text with images in it
« Reply #8 on: July 22, 2019, 04:00:38 pm »
Figured out how to get around this.

Although it is not ideal, but it will work.

I swapped out the Kmemo component for the Rich Memo.

Because search does work with images in the control, I just have to work around the Readonly bug in RM.



Can't Type - Forgetful - Had Stroke = Forgive this old man!

Pixelink Media •  My LAZ Software
LAZ 2.02 • Win10 • 16G RAM • Nivida GForce RTX 2060

wp

  • Hero Member
  • *****
  • Posts: 6003
Re: KMemo - Search Text with images in it
« Reply #9 on: July 22, 2019, 04:17:18 pm »
I just have to work around the Readonly bug in RM.
That's easy. Keep the property "ReadOnly" at false, but write an event handler for the RichMemo's OnKeyDown which swallows all key codes, maybe except CTRL+C in order to copy the selected text to the clipboard:
Code: Pascal  [Select]
  1. procedure TForm1.RichMemo1KeyDown(Sender: TObject; var Key: Word;
  2.   Shift: TShiftState);
  3. begin
  4.   if not ((Key = VK_C) and (Shift = [ssCtrl])) then
  5.     Key := 0;
  6. end;
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

lucamar

  • Hero Member
  • *****
  • Posts: 1948
Re: KMemo - Search Text with images in it
« Reply #10 on: July 22, 2019, 05:13:54 pm »
I just have to work around the Readonly bug in RM.
That's easy. Keep the property "ReadOnly" at false, but write an event handler for the RichMemo's OnKeyDown which swallows all key codes, maybe except CTRL+C in order to copy the selected text to the clipboard:
[[snip code]

The bug arises only when loading the richmemo; it's easier to set ReadOnly to False before LoadFromFile() and then set it again to True.

IIRC that was the workaround suggested by skalogryz?
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

pixelink

  • Hero Member
  • *****
  • Posts: 1028
    • Pixelink Media
Re: KMemo - Search Text with images in it
« Reply #11 on: July 24, 2019, 01:28:22 am »
I just have to work around the Readonly bug in RM.
That's easy. Keep the property "ReadOnly" at false, but write an event handler for the RichMemo's OnKeyDown which swallows all key codes, maybe except CTRL+C in order to copy the selected text to the clipboard:
[[snip code]

The bug arises only when loading the richmemo; it's easier to set ReadOnly to False before LoadFromFile() and then set it again to True.

IIRC that was the workaround suggested by skalogryz?

Yeah, I knew that. I stated in my thread with him that that works.
Can't Type - Forgetful - Had Stroke = Forgive this old man!

Pixelink Media •  My LAZ Software
LAZ 2.02 • Win10 • 16G RAM • Nivida GForce RTX 2060