Forum > RichMemo

Installing RichMemo into Lazarus 2.0.0

<< < (2/3) > >>

wp:
This is the declaration of the EDITSTREAMCALLBACK function, taken from the FPC richedit.pp unit:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type     EDITSTREAMCALLBACK = function (dwCookie:DWORD_PTR; pbBuff:LPBYTE; cb:LONG; var pcb:LONG):DWORD;
Here you see that the RichMemo declares dwCookie as a DWORD_PTR which is the Windows type for our PUInt - the unsigned integer which has the same size as a pointer. The sizes of pointers and longints are not equal in general depending on the bitness of the application: while longint always has 32 bit, the size of a pointer corresponds to the bitness: 32 bit in 32bit applications, 64bit in 64bit applications.

The solution of this compilation issue, therefore, is to declare dwCookie in your callback function as PtrUInt rather than LongInt, and your program should work also with FPC 3.2.2.

rick2691:
WP,

Thanks for giving this some thought.

Is the DWORD_PTR in the FPC richedit.pp unit a PtrUInt?

and if so, then ...

function EditStreamOutCallback(dwCookie:Longint; pbBuff:PByte;
                               cb:Longint; var pcb:Longint):Longint; stdcall; 

needs to be ...

function EditStreamOutCallback(dwCookie:PtrUInt; pbBuff:PByte;
                               cb:Longint; var pcb:Longint):PtrUInt; stdcall; 

per the dwCookie and Result parameters. Is that what you are saying?

If that is true, then the Delphi code that I took this from is for pre-64bit applications?
Moreover, it works for me because I am doing 32bit application?
Likewise, the debugger is choking on it because it wants 64bit compatibility?

If all of that is correct, then I think the debugger needs to be a little more verbose than it is.

Rick

wp:

--- Quote from: rick2691 on March 07, 2022, 05:44:16 pm ---Is the DWORD_PTR in the FPC richedit.pp unit a PtrUInt?
--- End quote ---
Yes.


--- Quote from: rick2691 on March 07, 2022, 05:44:16 pm ---and if so, then ...

function EditStreamOutCallback(dwCookie:Longint; pbBuff:PByte;
                               cb:Longint; var pcb:Longint):Longint; stdcall; 

needs to be ...

function EditStreamOutCallback(dwCookie:PtrUInt; pbBuff:PByte;
                               cb:Longint; var pcb:Longint):PtrUInt; stdcall; 

per the dwCookie and Result parameters. Is that what you are saying?
--- End quote ---

Almost. Only for dwCookie, not for the result. Or you can stick with the original declaration with DWORD_PTR - the important thing is that dwCookie must be declared as an integer which has the same size as a pointer because you type-cast the cookie to a Memorystream which is a pointer.

Either do this

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function EditStreamOutCallback(dwCookie: DWORD_PTR; pbBuff: PByte;                               cb: Longint; var pcb: Longint): DWORD; stdcall;or this

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function EditStreamOutCallback(dwCookie: PtrUInt; pbBuff: PByte;                               cb: Longint; var pcb: Longint): DWORD; stdcall;
The declaration of the function must follow the prototype of EDITSTREAMCALLBACK defined in unit richedit.pp (which is in the fpc folder packages\winunits-base\src) (cited in my post above).


--- Quote from: rick2691 on March 07, 2022, 05:44:16 pm ---If that is true, then the Delphi code that I took this from is for pre-64bit applications?
--- End quote ---
Yes.


--- Quote from: rick2691 on March 07, 2022, 05:44:16 pm ---Moreover, it works for me because I am doing 32bit application?
Likewise, the debugger is choking on it because it wants 64bit compatibility?
--- End quote ---
I don't know what you are doing. And I cannot test anything because you don't post a small sample project. So, I am just guessing (and may be wrong), but my arguments look very conclusive (to me).


--- Quote from: rick2691 on March 07, 2022, 05:44:16 pm ---If all of that is correct, then I think the debugger needs to be a little more verbose than it is.
--- End quote ---
You probably mean "compiler" rather than "debugger". Yes, sometimes the compiler messages are hard to understand. But again I cannot comment because you did not post the error message.

rick2691:
This is the code that I am using. I have altered by your advice, and I have tested it. It works as good as what I had already been using. So I suppose that I can use it and be more modern.

However, I have gone back to compiler 2.0.10, and operating in 32 bit format, which does not choke on my older code nor your changes to it. Curiously, even compiler 2.0.12 chokes on my older code, so it might date when things have become so complicated.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---//========================= begin: stream callback for Get/PutRTFselection // by Peter Below (TeamB)  < 100113.1...@compuserve.com > // Stream Callback function//type  TEditStreamCallBack = function(dwCookie:PtrUInt; pbBuff:PByte;   //  PtrUInt = DWord = LongWord                                 cb:Longint; var pcb:Longint                                 ):DWORD; stdcall;                                 //  ):DWORD_Ptr or PtrUInt for ansistring *was*  ):Longint for widestring  TEditStream = record                dwCookie:LongInt; // PtrUInt;                dwError:Longint;                pfnCallback:TEditStreamCallBack;                end; // Callback function for EM_STREAMOUT ... by the TEAM//function EditStreamOutCallback(dwCookie:PtrUInt; pbBuff:PByte;                               cb:Longint; var pcb:Longint):DWORD; stdcall;                               //  ):DWORD for ansistring *was*  ):Longint for widestring  // TMemoryStream;  // TStream;begin  // This will write the contents of the Richmemo OUT to a TMemoryStream field.  //  // dwCookie is Application-defined, so we're passing the blob stream.  //  pcb:= TMemoryStream(dwCookie).Write(pbBuff^, cb);  // TMemoryStream  // TStream  Result:= 0;end; // Callback function for EM_STREAMIN//function EditStreamInCallback(dwCookie:PtrUInt; pbBuff:PByte;                              cb:Longint; var pcb:Longint):DWORD; stdcall;var                           //  ):DWORD for ansistring *was*  ):Longint for widestring  theStream: TMemoryStream;  // try TMemoryStream instead of TStream.begin  // This will write the contents of a TStream field IN to a Richmemo.  //  // dwCookie is Application-defined, so we're passing the stream containing  // the formatted text to be added.  //  theStream:= TMemoryStream(dwCookie);  Result:= 0;   with theStream do       begin       if (Size - Position) <= cb then           begin           pcb:= Size;           Read(pbBuff^, Size);           end           else begin                pcb:= cb;                Read(pbBuff^, cb);                end;       end;end; // copyout Stream from RichEdit: uses stream callback above//Procedure GetRTFSelection(Amemo:TRichMemo; IntoStream:TMemoryStream);  // TStream);Var EditStream: TEditStream;Begin  with EditStream do       Begin       dwCookie:= Longint(IntoStream);       dwError:= 0;       pfnCallback:= @EditStreamOutCallBack;  // get OUT FROM stream       end;  Amemo.Perform(EM_STREAMOUT, SF_RTF or SFF_SELECTION, longint(@EditStream));End; // Insert Stream into RichEdit: uses stream callback above//procedure PutRTFSelection(Amemo:TRichMemo; SourceStream:TMemoryStream);  // TStream);var EditStream: TEditStream;begin  with EditStream do       begin       dwCookie:= Longint(SourceStream);       dwError:= 0;       pfnCallback:= @EditStreamInCallBack;  // put IN to stream       end;  Amemo.Perform(EM_STREAMIN, SF_RTF or SFF_SELECTION, Longint(@EditStream));end; //=================================== end: stream callback for Get/PutRTFselection  
How the code works is that I select anything or everything that is in an RTF document, and then call to MnuSaveSelectionClick(Sender: TObject).


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TCmdForm.SaveSelection;  // PageMemo to New TabPagevar MS: TMemoryStream;  // TMemoryStream;// TMemoryStream is a TStream descendant that stores its data in memory.// TMemoryStream self-handles all allocation and destroying of memory.// When the stream is freed, all allocated memory will also be freed.begin  // PageMemo range must already be selected  MS:= TMemoryStream.create;  // TMemoryStream.Create;  //MS:= TStringStream.create;  try    GetRTFSelection(PageMemo,MS); // stores selection as MS    PageMemo.SelLength:= 0;    MS.Position:= 0;    btnNewClick(Self);    PageMemo.SetFocus;    PutRTFSelection(PageMemo,MS); // copy/paste MS to Untitled    PageMemo.SelLength:= 0;    //PageMemo.SetFocus;  finally    MS.Free;  end;end; procedure TCmdForm.MnuSaveSelectionClick(Sender: TObject);begin  if PageTabControl.PageCount>0 then     begin     if PageMemo.SelLength>0        then SaveSelection   // ReportPageTab;        else showmessage('Nothing selected.');     end else showmessage('No active document.');end;  
This opens a new TabSheet and copies the selected to it. It is just a convenience for saving (on the fly) the content in a document that I have decided to edit. ie. rewrite. So that I can restore the section if my editing doesn't get me anywhere. It's a book.

Given all the trouble that I have encountered by upgrading to the latest compiler version, I may not reinstall it. There could be other 64bit problems that I don't know about yet. Meanwhile, I only want to get my work finished.

Unfortunately, even with version 2.0.10 I now have a problem importing images into the document ... because I am forced to use Online Package Manager to install RichMemo, instead of just installing from a disk package. It seems that graphic functions have been modified, and images are currently imported at too large of a scale (about double size).

Do you know anything about that? I would really like to get that fixed.

Rick

wp:
Quickling scanning through this code I see three more issues with Pointer-to-Integer conversion. I marked the lines by a yellow background: Use a PtrUint rather than a LongInt here in order to be compatibile with 64-bit.

--- Quote from: rick2691 on March 09, 2022, 03:54:07 pm ---
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---//========================= begin: stream callback for Get/PutRTFselection // by Peter Below (TeamB)  < 100113.1...@compuserve.com > // Stream Callback function//type  TEditStreamCallBack = function(dwCookie:PtrUInt; pbBuff:PByte;   //  PtrUInt = DWord = LongWord                                 cb:Longint; var pcb:Longint                                 ):DWORD; stdcall;                                 //  ):DWORD_Ptr or PtrUInt for ansistring *was*  ):Longint for widestring  TEditStream = record                dwCookie:LongInt; // PtrUInt;                dwError:Longint;                pfnCallback:TEditStreamCallBack;                end; // Callback function for EM_STREAMOUT ... by the TEAM//function EditStreamOutCallback(dwCookie:PtrUInt; pbBuff:PByte;                               cb:Longint; var pcb:Longint):DWORD; stdcall;                               //  ):DWORD for ansistring *was*  ):Longint for widestring  // TMemoryStream;  // TStream;begin  // This will write the contents of the Richmemo OUT to a TMemoryStream field.  //  // dwCookie is Application-defined, so we're passing the blob stream.  //  pcb:= TMemoryStream(dwCookie).Write(pbBuff^, cb);  // TMemoryStream  // TStream  Result:= 0;end; // Callback function for EM_STREAMIN//function EditStreamInCallback(dwCookie:PtrUInt; pbBuff:PByte;                              cb:Longint; var pcb:Longint):DWORD; stdcall;var                           //  ):DWORD for ansistring *was*  ):Longint for widestring  theStream: TMemoryStream;  // try TMemoryStream instead of TStream.begin  // This will write the contents of a TStream field IN to a Richmemo.  //  // dwCookie is Application-defined, so we're passing the stream containing  // the formatted text to be added.  //  theStream:= TMemoryStream(dwCookie);  Result:= 0;   with theStream do       begin       if (Size - Position) <= cb then           begin           pcb:= Size;           Read(pbBuff^, Size);           end           else begin                pcb:= cb;                Read(pbBuff^, cb);                end;       end;end; // copyout Stream from RichEdit: uses stream callback above//Procedure GetRTFSelection(Amemo:TRichMemo; IntoStream:TMemoryStream);  // TStream);Var EditStream: TEditStream;Begin  with EditStream do       Begin       dwCookie:= Longint(IntoStream);       dwError:= 0;       pfnCallback:= @EditStreamOutCallBack;  // get OUT FROM stream       end;  Amemo.Perform(EM_STREAMOUT, SF_RTF or SFF_SELECTION, longint(@EditStream));End; // Insert Stream into RichEdit: uses stream callback above//procedure PutRTFSelection(Amemo:TRichMemo; SourceStream:TMemoryStream);  // TStream);var EditStream: TEditStream;begin  with EditStream do       begin       dwCookie:= Longint(SourceStream);       dwError:= 0;       pfnCallback:= @EditStreamInCallBack;  // put IN to stream       end;  Amemo.Perform(EM_STREAMIN, SF_RTF or SFF_SELECTION, Longint(@EditStream));end; //=================================== end: stream callback for Get/PutRTFselection  
--- End quote ---


--- Quote from: rick2691 on March 09, 2022, 03:54:07 pm ---because I am forced to use Online Package Manager to install RichMemo, instead of just installing from a disk package.
--- End quote ---
Nobody forces you to use Online Package Manager. It is just a convenient - a VERY convenient - tool to distribute packages. But you still can load the .lpk file of any package from any source into Lazarus and install it manually. I do this all the time.


--- Quote from: rick2691 on March 09, 2022, 03:54:07 pm ---It seems that graphic functions have been modified, and images are currently imported at too large of a scale (about double size).

Do you know anything about that? I would really like to get that fixed.
--- End quote ---
I am not a specialist with RichEdit/RichMemo. But you should search the forum for it. I remember there was a discussion about images in RichMemo not too long ago.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version