Catch RTF from editor gadget

Just starting out? Need help? Post your questions and find answers here.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Catch RTF from editor gadget

Post by Joakim Christiansen »

I need to be able to catch the RTF from my editor gadget and put it inside another editor gadget.
I like logic, hence I dislike humans but love computers.
User avatar
Thorsten1867
Addict
Addict
Posts: 1372
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Post by Thorsten1867 »

Hilft dir speichern und laden weiter?

Code: Select all

Procedure StreamFileIn_Callback(hFile, pbBuff, cb, pcb) 
  ProcedureReturn ReadFile_(hFile, pbBuff, cb, pcb, 0)!1 
EndProcedure

Procedure StreamFileOut_Callback(hFile, pbBuff, cb, pcb)
  ProcedureReturn WriteFile_(hFile, pbBuff, cb, pcb, 0)!1
EndProcedure

Procedure Editor_Load(EGid.l, File.s) 
  Protected StreamData.EDITSTREAM 
  Protected FileID.l 
  FileID = ReadFile(#PB_Any, File) 
  If FileID 
    StreamData\dwCookie = FileID(FileID) 
    StreamData\dwError = #Null 
    StreamData\pfnCallback = @StreamFileIn_Callback() 
    If UCase(GetExtensionPart(File)) = "RTF" 
      SendMessage_(GadgetID(EGid), #EM_STREAMIN, #SF_RTF, @StreamData) 
    Else 
      SendMessage_(GadgetID(EGid), #EM_STREAMIN, #SF_TEXT, @StreamData) 
    EndIf 
    CloseFile(FileID) 
  EndIf 
EndProcedure

Procedure Editor_Save(EGid.l,File.s)
  Protected StreamData.EDITSTREAM
  Protected FileID.l 
  If File <> ""
    FileID = CreateFile(#PB_Any, File)
    If FileID
      StreamData\dwCookie = FileID(FileID)
      StreamData\dwError = #Null
      StreamData\pfnCallback = @StreamFileOut_Callback()
      If UCase(GetExtensionPart(File)) = "RTF"
        SendMessage_(GadgetID(EGid), #EM_STREAMOUT, #SF_RTF, @StreamData)
      Else
        SendMessage_(GadgetID(EGid), #EM_STREAMOUT, #SF_TEXT, @StreamData)
      EndIf
      CloseFile(FileID)
    EndIf
  Else
    ProcedureReturn 0
  EndIf
EndProcedure
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
Thorsten1867
Addict
Addict
Posts: 1372
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Post by Thorsten1867 »

Or try it with the clipboard:

Code: Select all

 
Procedure EditorGadgetSelectAll(Gadget_ID) 
  ; Select the whole Text of the EditorGadget 
  RangeAll.CHARRANGE\cpMin = 0 
  RangeAll\cpMax = -1 
  ProcedureReturn SendMessage_(GadgetID(Gadget_ID),#EM_EXSETSEL,0,@RangeAll) ; Select All 
EndProcedure 

Procedure EditorGadgetCOPY(Gadget_ID) 
  ProcedureReturn SendMessage_(GadgetID(Gadget_ID), #WM_COPY, 0, 0) 
EndProcedure 

Procedure EditorGadgetPASTE(Gadget_ID) 
  ProcedureReturn SendMessage_(GadgetID(Gadget_ID), #EM_PASTESPECIAL, 0, 0) 
EndProcedure 
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Thank you for your help, but I needed something a little different.
So I just put together some shit:

Code: Select all

Procedure GetRTFCallback(dwCookie.l,pbBuff.l,cb.l,*pcb)
  CopyMemory(pbBuff,dwCookie,cb)
EndProcedure
Procedure SetRTFCallback(dwCookie.l,pbBuff.l,cb.l,*pcb)
  PokeS(pbBuff,PeekS(dwCookie))
EndProcedure
Procedure Editor_GetRTF(Gadget.l,Adress.l)
  Protected Stream.EDITSTREAM
  Stream\dwCookie = Adress
  Stream\pfnCallback = @GetRTFCallback()
  SendMessage_(GadgetID(Gadget),#EM_STREAMOUT,#SF_RTF,@Stream)
EndProcedure
Procedure Editor_SetRTF(Gadget.l,Adress.l)
  Protected Stream.EDITSTREAM
  Stream\dwCookie = Adress
  Stream\pfnCallback = @SetRTFCallback()
  SendMessage_(GadgetID(Gadget),#EM_STREAMIN,#SF_RTF,@Stream)
EndProcedure

Code: Select all

*MyString = AllocateMemory(200)

;Copy it to buffer
Editor_GetRTF(#Editor,*MyString)

ClearGadgetItemList(#Editor) ;Clear the gadget

;Write the buffer
Editor_SetRTF(#Editor,*MyString)
It also work with:

Code: Select all

SetGadgetText(#Editor,PeekS(*MyString))
So I don't need the Editor_SetRTF() actually.
I like logic, hence I dislike humans but love computers.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Joakim, it is possible that Windows will not send all the rtf content to your GetRTFCallback() procedure in one go. It is quite possible (and very probable!) that it will call the function repeatedly, each time sending just a fraction of the total content.

Each time the callback is called, the 'cb' variable holds the number of bytes which Windows sends to your procedure (if zero then the transfer is complete and you must return non-zero to complete the process). You should place the actual number of bytes transferred each time in the address pointed to by *pcb. Of course, you should also update the address of your memory buffer to write to each time.

In fact I've just tested some very similar code that I use and the corresponding callback was called twice on a particular gadget whose rtf content I saved.
I may look like a mule, but I'm not a complete ass.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

So it would have to be something like this?

Code: Select all

Procedure.l GetRTFCallback(dwCookie.l,pbBuff.l,cb.l,*pcb.LONG)
  Static Length.l
  Debug 1
  If cb = 0
    Length = 0 ;reset
  Else
    CopyMemory(pbBuff,dwCookie+Length,cb)
    Length + cb
  EndIf
  *pcb\l = cb
  ProcedureReturn 0
EndProcedure
Do you know any easy way of just getting the size of all the data that will be sendt?

Then I could just do:

Code: Select all

Define *Buffer = AllocateMemory(GetRTFSize())
GetRTF(#Editor,*Buffer)
I like logic, hence I dislike humans but love computers.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

The following ensures that windows stops calling the callback when all the data is transferred:

Code: Select all

Procedure.l GetRTFCallback(dwCookie.l,pbBuff.l,cb.l,*pcb.LONG) 
  Protected result
  Static Length.l 
  CopyMemory(pbBuff,dwCookie+Length,cb) 
  Length + cb 
  *pcb\l = cb 
  If cb = 0 
    result=1 ;All done! Returning 1 will cancel further calls to this proc.
  EndIf
  ProcedureReturn result
EndProcedure
This is more or less what I use.
Do you know any easy way of just getting the size of all the data that will be sendt?
I don't think so. Since editor gadgets can embed OLE objects (such as images, Excel sheets etc.) determining the actual size of the rtf content before streaming would be extremely difficult. Besides which, the editor gadget does not hold it's content in rtf format internally and only converts it when we stream the contents out as you are doing.
I may look like a mule, but I'm not a complete ass.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Oh, well thanks for the help! :)
I like logic, hence I dislike humans but love computers.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

You're welcome. Good luck with your project.
I may look like a mule, but I'm not a complete ass.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

srod wrote:You're welcome. Good luck with your project.
Thanks, it's actually a chat program, and I want to use the same editor gadget for each tab and blablabla... :D
I like logic, hence I dislike humans but love computers.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Well, here is the final result:

Code: Select all

Global RTFLength

Procedure.l GetRTFCallback(dwCookie.l,pbBuff.l,cb.l,*pcb.LONG)
  ;Protected Result.l
  ;If cb = 0
    ;Result = 1
  ;Else
    CopyMemory(pbBuff,dwCookie+RTFLength,cb)
    RTFLength + cb
  ;EndIf
  *pcb\l = cb
  ProcedureReturn 0;Result
EndProcedure
Procedure.l GetRTFLenCallback(dwCookie.l,pbBuff.l,cb.l,*pcb.LONG)
  RTFLength + cb
  *pcb\l = cb
  ProcedureReturn 0
EndProcedure

Procedure GetRTF(Gadget.l,Adress.l)
  Protected Stream.EDITSTREAM
  Stream\dwCookie = Adress
  Stream\pfnCallback = @GetRTFCallback()
  RTFLength = 0
  SendMessage_(GadgetID(Gadget),#EM_STREAMOUT,#SF_RTF,@Stream)
EndProcedure
Procedure.l GetRTFLen(Gadget.l)
  Protected Stream.EDITSTREAM
  Stream\pfnCallback = @GetRTFLenCallback()
  RTFLength = 0
  SendMessage_(GadgetID(Gadget),#EM_STREAMOUT,#SF_RTF,@Stream)
  ProcedureReturn RTFLength
EndProcedure

FreeMemory(*Buffer)
*Buffer = AllocateMemory(GetRTFLen(#Editor))
GetRTF(#Editor,*Buffer)

ClearGadgetItemList(#Editor)
SetGadgetText(#Editor,PeekS(*Buffer))
I did much testing, even with large files (75kb).
And here cb never returns 0, and if it does it should enough to just copy that to *pcb and it will end properly.
Maybe you need the Result = 1 stuff on other computers but I didn't need it.
But it's all there commented away if you need it. :wink:
I like logic, hence I dislike humans but love computers.
Post Reply