Autor Téma: Podivné chování LoadFromStream  (Přečteno 959 krát)

Offline rmaster

  • Nováček
  • *
  • Příspěvků: 9
  • Karma: 0
    • Verze Delphi: XE3
Podivné chování LoadFromStream
« kdy: 29-03-2024, 07:56:42 »
Zdravím,
používám RxRichEdit z RxLib a mám podivný problém, se kterým si nevím rady.
1) Mám jeden RxRichEdit a v něm si naformátuji text, jak potřebuji - to funguje bez problémů
2) Pak programově vytvořím jiný RX třeba RxRichEdit2 a do něho celý obsah přenesu pomocí SaveToStream / LoadFromStream

Kód: Delphi [Vybrat]
  1. try
  2.         T_Strm.Clear;
  3.         RxRichEdit.Lines.SaveToStream(T_Strm);
  4.         T_Strm.Seek(0, soFromBeginning) ;
  5.         RxRichEdit2.Lines.LoadFromStream(T_Strm);
  6.       finally
  7.       end;

A v tomto bodě nastane problém, že ve výsledném RxRichEdit2 je někde uprostřed textu vložená jedna mezera navíc. Někdy je to až ke konci textu, většinou ten RTF má tak 50 řádků.
Děje se to jen třeba u jednoho z 50ti přesunů a nějak to asi souvisí s počtem znaků v tom RTF, protože když u problémového přesunu textu vymažu někde uprostřed třeba znak nebo mezeru ručně, tak ten problém nenastane. Počítal jsem, že SaveToStream / LoadFromStream vždy přesune data přesně 1:1.
Ještě doplním, že když uložím ten stream (T_Strm) do souboru, tak tam je to OK, takže to udělá až ten LoadFromStream.
Nemáte někdo nápad jak najít chybu?

Zde ještě vložím tu definici LoadFromStream:

Kód: Delphi [Vybrat]
  1. procedure TRichEditStrings.LoadFromStream(Stream: TStream{$IFDEF RX_D12}; Encoding: TEncoding{$ENDIF});
  2. var
  3.   EditStream: TEditStream;
  4.   Position: Longint;
  5.   TextType: Longint;
  6.   StreamInfo: TRichEditStreamInfo;
  7.   Converter: TConversion;
  8. {$IFDEF RX_D12}
  9.   PlainText: Boolean;
  10. {$ENDIF}
  11. begin
  12. {$IFDEF RX_D12}
  13.   if Encoding = nil then
  14.   begin
  15.     // Find the appropraite encoding
  16.     if ContainsPreamble(Stream, TEncoding.Unicode.GetPreamble) then
  17.       Encoding := TEncoding.Unicode
  18.     else
  19.       if ContainsPreamble(Stream, TEncoding.BigEndianUnicode.GetPreamble) then
  20.         Encoding := TEncoding.BigEndianUnicode
  21.       else
  22.         if ContainsPreamble(Stream, TEncoding.UTF8.GetPreamble) then
  23.           Encoding := TEncoding.UTF8
  24.         else
  25.           Encoding := TEncoding.Default;
  26.   end;
  27. {$ENDIF}
  28.   StreamInfo.Stream := Stream;
  29.   if FConverter <> nil then
  30.     Converter := FConverter
  31.   else
  32.     Converter := RichEdit.DefaultConverter.Create;
  33.   StreamInfo.Converter := Converter;
  34. {$IFDEF RX_D12}
  35.   PlainText:= (FFormat = sfPlainText) or
  36.                         ((FFormat = sfDefault) and (RichEdit.PlainText = True));
  37.   StreamInfo.PlainText:= PlainText;
  38.   StreamInfo.Encoding := Encoding;
  39. {$ENDIF}
  40.   try
  41.     with EditStream do
  42.     begin
  43. {$IFDEF RX_D12}
  44.       dwCookie := DWORD_PTR(@StreamInfo);
  45.       pfnCallBack := StreamLoad;
  46. {$ELSE}
  47.       dwCookie := Longint(Pointer(@StreamInfo));
  48.       pfnCallBack := @StreamLoad;
  49. {$ENDIF}
  50.       dwError := 0;
  51.     end;
  52.     Position := Stream.Position;
  53.     case FFormat of
  54.       sfDefault:
  55.         if RichEdit.PlainText then
  56.           TextType := SF_TEXT
  57.         else
  58.           TextType := SF_RTF;
  59.       sfRichText: TextType := SF_RTF;
  60.       else {sfPlainText}
  61.         TextType := SF_TEXT;
  62.     end;
  63.     if TextType = SF_RTF then
  64.     begin
  65.       if smPlainRtf in Mode then
  66.         TextType := TextType or SFF_PLAINRTF;
  67.     end
  68.     else
  69.     if TextType = SF_TEXT then
  70.     begin
  71. {$IFNDEF RX_D12}
  72.       if (smUnicode in Mode) and (RichEditVersion > 1) then
  73. {$ENDIF}
  74.         TextType := TextType or SF_UNICODE;
  75.     end;
  76.     if smSelection in Mode then
  77.       TextType := TextType or SFF_SELECTION;
  78.     SendMessage(RichEdit.Handle, EM_STREAMIN, TextType, Longint(@EditStream));
  79.  
  80.     if (EditStream.dwError <> 0) then
  81.     begin
  82.       Stream.Position := Position;
  83.       if (TextType and SF_RTF = SF_RTF) then
  84.         TextType := SF_TEXT{$IFNDEF RX_D12} or SF_UNICODE{$ENDIF}
  85.       else
  86.         TextType := SF_RTF;
  87. {$IFDEF RX_D12}
  88.       StreamInfo.PlainText := not PlainText;
  89. {$ENDIF}
  90.       SendMessage(RichEdit.Handle, EM_STREAMIN, TextType, Longint(@EditStream));
  91.       if EditStream.dwError <> 0 then
  92.         raise EOutOfResources.Create(ResStr(sRichEditLoadFail));
  93.     end;
  94.     RichEdit.SetSelection(0, 0, True);
  95.   finally
  96.     if FConverter = nil then Converter.Free;
  97.   end;
  98. end;
  99.  
  100.  

Děkuji moc.

Offline Jan Fiala

  • Hrdina
  • ****
  • Příspěvků: 439
  • Karma: 6
    • Verze Delphi: 10.4.1
    • PSPad editor
Re:Podivné chování LoadFromStream
« Odpověď #1 kdy: 29-03-2024, 17:57:59 »
Nepomuze prenos bez streamu? Neco jako:
RichEdit2.Lines.Assign(RichEdit1.Lines);

Offline rmaster

  • Nováček
  • *
  • Příspěvků: 9
  • Karma: 0
    • Verze Delphi: XE3
Re:Podivné chování LoadFromStream
« Odpověď #2 kdy: 29-03-2024, 19:38:15 »
Díky, ale to to bohužel nefunguje.
Takto se přenese jen text, ale já potřebuji, aby se přenesl včetně formátování a barev.
Ještě doplním, že pokud bych použil SaveToFile a LoadFromFile, tak to také blbne.

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 1142
  • Karma: 29
    • Verze Delphi: XE8, Sydney
Re:Podivné chování LoadFromStream
« Odpověď #3 kdy: 30-03-2024, 08:31:36 »
A jak se chová v novější verzi RxLib? Odkaz, viz http://www.micrel.cz/RxLib/files/unrxlib_275_u_1_0_22.rar

Offline rmaster

  • Nováček
  • *
  • Příspěvků: 9
  • Karma: 0
    • Verze Delphi: XE3
Re:Podivné chování LoadFromStream
« Odpověď #4 kdy: 30-03-2024, 09:09:50 »
Poslední verzi jsem také zkoušel a chová se to stejně.
Přišel jsem na to, že to dělá i jen obyčejný LoadFromFile a většinou pro soubor, který má 1024 znaků - což dle čísla vypadá, že by to nemusela být náhoda. Zkusil jsem v té jejich proceduře LoadFromFile vše odstranit a nechat tam jen toto:
Kód: Delphi [Vybrat]
  1. inherited LoadFromFile(FileName{$IFDEF RX_D12}, Encoding{$ENDIF});
a chová se to stejně, takže asi přímo v té proceduře chyba nebude.

Ještě doplním, že když kouknu přímo na ten RTF v TXT editoru, tak to dává tu mezeru vždy na začátek řádku (druhý řádek před \cf1 - nahradil jsem to červeným písmenem X):

\par
X\cf1 <Label:5.>\cf0 Te\'ef m\'e1m jen jedno \cf2 [F]\cf0 p\'f8\'e1n\'ed,\cf2 [G]\cf0  u\'9e \cf2 [C]\cf0 nechat vandro\cf2 [F]\cf0 v\'e1n\'ed,\par
\cf2 [G]\cf0 m\'edt \cf2 [C]\cf0 hospo\cf2 [Emi]\cf0 du a \cf2 [F]\cf0 pro vo\cf2 [C]\cf0 du u\'9e \cf2 [G]\cf0 nikdy nebejt \cf2 [C]\cf0 k m\'e1n\'ed.\par
\par

Offline gerger

  • Nováček
  • *
  • Příspěvků: 1
  • Karma: 0
    • Verze Delphi: 11.3
Re:Podivné chování LoadFromStream
« Odpověď #5 kdy: 02-04-2024, 09:34:19 »
Ahoj, Rx neznám, ale pokud dědí z klasického RichEdit, můžes zkusit zkus toto:

Kód: Delphi [Vybrat]
  1. RichInsertTextFormatted(TargetRich, RichGetTextFormatted(SourceRich));

Kód: Delphi [Vybrat]
  1. function EditStreamReader(dwCookie: DWORD; pBuff: Pointer; cb: LongInt; pcb: PLongInt): DWORD; stdcall;
  2. begin
  3.   Result := 0;
  4.  
  5.   try
  6.     pcb^ := TStream(dwCookie).Read(pBuff^, cb);
  7.   except
  8.     Result := $FFFF;
  9.   end;
  10. end;
  11.  
  12. function EditStreamWriter(dwCookie: DWORD; pBuff: Pointer; cb: LongInt; pcb: PLongInt): DWORD; stdcall;
  13. begin
  14.   Result := 0;
  15.  
  16.   try
  17.     pcb^ := TStream(dwCookie).Write(pBuff^, cb);
  18.   except
  19.     Result := $FFFF;
  20.   end;
  21. end;
  22.  
  23. function RichGetTextFormatted(RichEdit: TRichEdit): string;
  24. var
  25.   SStream: TStringStream;
  26.   EditStream: TEditStream;
  27. begin
  28.   SStream := TStringStream.Create;
  29.   try
  30.     EditStream.dwCookie := DWORD(SStream);
  31.     EditStream.dwError := 0;
  32.     EditStream.pfnCallback := @EditStreamWriter;
  33.  
  34.     RichEdit.Perform(EM_STREAMOUT, SF_RTF or SFF_PLAINRTF, LPARAM(@EditStream));
  35.  
  36.     if EditStream.dwError = 0 then
  37.     begin
  38.       Result := SStream.DataString;
  39.     end else begin
  40.       Result := '';
  41.     end;
  42.   finally
  43.     SStream.Free;
  44.   end;
  45. end;
  46.  
  47. procedure RichInsertTextFormatted(RichEdit: TRichEdit; Text: string);
  48. var
  49.   SStream: TStringStream;
  50.   EditStream: TEditStream;
  51. begin
  52.   SStream := TStringStream.Create(Text);
  53.   RichEdit.Lines.BeginUpdate;
  54.   try
  55.     SStream.Position := 0;
  56.     RichEdit.MaxLength := 0;
  57.  
  58.     EditStream.dwCookie := DWORD(SStream);
  59.     EditStream.dwError := 0;
  60.     EditStream.pfnCallback := @EditStreamReader;
  61.  
  62.     RichEdit.Perform(EM_STREAMIN, SF_RTF or SFF_PLAINRTF or SFF_SELECTION, LPARAM(@EditStream));
  63.   finally
  64.     RichEdit.Lines.EndUpdate;
  65.     SStream.Free;
  66.   end;
  67. end;

Offline rmaster

  • Nováček
  • *
  • Příspěvků: 9
  • Karma: 0
    • Verze Delphi: XE3
Re:Podivné chování LoadFromStream
« Odpověď #6 kdy: 10-04-2024, 20:41:04 »
Tak toto mi padá na nějakou systémovou chybu.
Nakonec jsem oslovil přímo vývojáře z RxLib http://www.micrel.cz/ a oni poslali opravenou komponentu a vše funguje.
Každopádně díky všem.