Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OSXSetRTFValue() and OSXGetRTFValue() functions to wxTextCtrl #24621

Closed
wants to merge 5 commits into from

Conversation

Blake-Madden
Copy link
Contributor

@Blake-Madden Blake-Madden commented Jun 18, 2024

This adds new methods to write and read direct RTF data to a wxTextCtrl under macOS. The benefit of this is performance and being able to read and write RTF files easily.

[ ] Compile with iPhone
[ ] Add support to Load and Save file methods in wxTextCtrl
[ ] Show loading and saving RTF file in sample

@Blake-Madden
Copy link
Contributor Author

I'm not sure what to do about unit testing. With the RTF control under macOS and MSW, when you feed RTF into it, the control optimizes it in unpredictable ways. So, reading the RTF back from the control will almost always be slightly different from what you passed into it. Point is, I don't see a way to call set and then verify that the get function returns the same value. I could just see if the return value is some sort of RTF at least. Thoughts?

@Blake-Madden
Copy link
Contributor Author

Also, for the simple I just have a simple menu option that sets one of the controls to RTF content. Should I add more, like be able to load/save an RTF file?

@vadz
Copy link
Contributor

vadz commented Jun 18, 2024

Thanks, but can we implement this for MSW too (for rich edit controls)? It seems a bit strange to add support for Microsoft format only to wxOSX...

Re testing: maybe we could at least check that the contents retrieved back contains some unique substring of the provided text or something like this?

Re sample: I think allowing to enter the RTF and/or loading it from file would be useful for testing, so it would be nice to add it.

Thanks!

@Blake-Madden
Copy link
Contributor Author

Thanks, but can we implement this for MSW too (for rich edit controls)? It seems a bit strange to add support for Microsoft format only to wxOSX...

I was going to do that in a future PR :) I'll remove the "OSX" prefix in anticipation of that and just document that this is currently for macOS only (at the moment).

@PBfordev
Copy link
Contributor

PBfordev commented Jun 19, 2024

Getting RTF into/out from richedit seems easy (no error checking):

#include <windows.h>
#include <richedit.h>

DWORD CALLBACK EditStreamCallbackOut(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
    wxString* rtf = reinterpret_cast<wxString*>(dwCookie);

    rtf->append(reinterpret_cast<char*>(pbBuff), cb);
    *pcb = cb;
    return 0;
}

DWORD CALLBACK EditStreamCallbackIn(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
    wxStringInputStream* rtfStream = reinterpret_cast<wxStringInputStream*>(dwCookie);

    rtfStream->Read(pbBuff, cb);
    *pcb = cb;
    return 0;
}

wxString GetRTFFromTextCtrl(wxTextCtrl& textCtrl)
{
    wxCHECK_MSG(textCtrl.GetWindowStyle() & wxTE_RICH2, "", "textCtrl must have wxTE_RICH2 flag");

    wxString rtf;
    EDITSTREAM es{(DWORD_PTR)&rtf, 0, &EditStreamCallbackOut};

    SendMessage(textCtrl.GetHWND(), EM_STREAMOUT, SF_RTF | SF_TEXTIZED | SF_UNICODE, (LPARAM)&es);
    return rtf;
}

void SetRTFToTextCtrl(wxTextCtrl& textCtrl, const wxString& rtf)
{
    wxCHECK_RET(textCtrl.GetWindowStyle() & wxTE_RICH2, "textCtrl must have wxTE_RICH2 flag");

    wxStringInputStream rtfStream(rtf);
    EDITSTREAM es{(DWORD_PTR)&rtfStream, 0, &EditStreamCallbackIn};

    SendMessage(textCtrl.GetHWND(), EM_STREAMIN, SF_RTF | SF_TEXTIZED | SF_UNICODE, (LPARAM)&es);
}

Requires richedit 2.0, perhaps it's time to retire wxTE_RICH (autotranslate it to wxTE_RICH2).

@Blake-Madden
Copy link
Contributor Author

OK, I'm going to pull this for now and rework so that I can reorg the change sets better.

@Blake-Madden
Copy link
Contributor Author

Thanks, PB.

The MSW implementation I've been using appends to a std::string in the callback, and when it's done I would pass that to the destination wxString. I seem to recall the callback sending char chunks in arbitrary sizes, and sometimes that char stream could only contain part of a multi-byte sequence. So if I wrote appended that to a wxString that would then convert to double byte, then the multi-byte sequence would be corrupted. So the solution was to append to a std::string (where no conversion would take place) and then send it to a wxString once everything was ready and then that would do the double-byte conversion.

@PBfordev
Copy link
Contributor

PBfordev commented Jul 1, 2024

I see, I only did cursory testing, did not realize that chunks may not respect code points boundaries even when SF_UNICODE is used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants