Opened 10 years ago
Closed 10 years ago
#3087 closed Bug (Fixed)
UTF problem with _GUICtrlRichEdit_StreamFromFile in 3.3.14.0
| Reported by: | mLipok | Owned by: | Jpm |
|---|---|---|---|
| Milestone: | 3.3.15.1 | Component: | Standard UDFs |
| Version: | 3.3.15.0 | Severity: | None |
| Keywords: | Cc: |
Description
Disscusion here:
https://www.autoitscript.com/forum/topic/173900-problem-with-_guictrlrichedit_streamfromfile-33140/
REPRO SCRIPT:
#include <GUIConstantsEx.au3>
#include <GuiRichEdit.au3>
#include <WindowsConstants.au3>
Example()
Func Example()
Local $hGui, $iMsg, $idBtnNext, $iStep = 0, $idLblMsg, $hRichEdit
$hGui = GUICreate("Example (" & StringTrimRight(@ScriptName, StringLen(".exe")) & ")", 320, 350, -1, -1)
$hRichEdit = _GUICtrlRichEdit_Create($hGui, "This is a test.", 10, 10, 300, 220, _
BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL))
$idLblMsg = GUICtrlCreateLabel("", 10, 235, 300, 60)
$idBtnNext = GUICtrlCreateButton("Next", 270, 310, 40, 30)
GUISetState(@SW_SHOW)
_GUICtrlRichEdit_StreamFromFile($hRichEdit, @ScriptDir & "\wzor.rtf")
While True
$iMsg = GUIGetMsg()
Select
Case $iMsg = $GUI_EVENT_CLOSE
_GUICtrlRichEdit_Destroy($hRichEdit) ; needed unless script crashes
; GUIDelete() ; is OK too
Exit
EndSelect
WEnd
EndFunc ;==>Example
Please make some fix.
My proposal is to add new parameters for File enconding with default $FO_UTF8_NOBOM as it is default for new files in AutoIt 3.3.14.0+
Consider to make the relevant amendments also in:
_GUICtrlRichEdit_StreamToFile
Attachments (1)
Change History (7)
Changed 10 years ago by mLipok
comment:1 Changed 10 years ago by mLipok
comment:2 Changed 10 years ago by Jpm
Hi,
adding $FO_UTF8_NOBOM to your proposed repro script and using your proposed updated function lead to display Nothing
I supposed it was intended to display TEST as it appear when opening "wzor.rtf" with Office-Word
comment:3 Changed 10 years ago by mLipok
Yes. I see.
this was because $iFileEncoding should be used in two places, but I forget about:
$hFile = FileOpen($sFileSpec, $FO_READ + $iFileEncoding) ; reopen it at the start
I also check @error returning from _GUICtrlRichEdit_StreamFromFile()
and I always get 700
so I do deeper search:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb774302(v=vs.85).aspx
On output, the dwError member can contain a nonzero error code if an error occurred.
so this mean:
If $iError <> 0 Then SetError(700, $iError, False)
instead:
If $iError <> 1 Then SetError(700, $iError, False)
FINALLY:
Func _GUICtrlRichEdit_StreamFromFile($hWnd, $sFileSpec, $iFileEncoding = Default)
If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, False)
Local $tEditStream = DllStructCreate($tagEDITSTREAM)
DllStructSetData($tEditStream, "pfnCallback", DllCallbackGetPtr($__g_pGRC_StreamFromFileCallback))
Local $hFile
If $iFileEncoding = Default Then
$hFile = FileOpen($sFileSpec, $FO_READ)
Else
$hFile = FileOpen($sFileSpec, $FO_READ + $iFileEncoding)
EndIf
If $hFile = -1 Then Return SetError(1021, 0, False)
Local $sBuf = FileRead($hFile, 5)
FileClose($hFile)
$hFile = FileOpen($sFileSpec, $FO_READ + $iFileEncoding) ; reopen it at the start
DllStructSetData($tEditStream, "dwCookie", $hFile) ; -> Send handle to CallbackFunc
Local $wParam = ($sBuf == "{\rtf" Or $sBuf == "{urtf") ? $SF_RTF : $SF_TEXT
$wParam = BitOR($wParam, $SFF_SELECTION)
If Not _GUICtrlRichEdit_IsTextSelected($hWnd) Then
_GUICtrlRichEdit_SetText($hWnd, "")
EndIf
Local $iQchs = _SendMessage($hWnd, $EM_STREAMIN, $wParam, $tEditStream, 0, "wparam", "struct*")
FileClose($hFile)
Local $iError = DllStructGetData($tEditStream, "dwError")
If $iError <> 0 Then SetError(700, $iError, False)
If $iQchs = 0 Then
If FileGetSize($sFileSpec) = 0 Then Return SetError(1022, 0, False)
Return SetError(700, $iError, False)
EndIf
Return True
EndFunc ;==>_GUICtrlRichEdit_StreamFromFile
comment:4 Changed 10 years ago by mLipok
btw.
Good in: _GUICtrlRichEdit_StreamToFile
If $iError <> 0 Then SetError(700, $iError, False)
but it should be:
If $iError <> 0 Then Return SetError(700, $iError, False)
and wrong in: _GUICtrlRichEdit_StreamFromVar
If $iError <> 1 Then Return SetError(700, $iError, False)
it als should be:
If $iError <> 0 Then Return SetError(700, $iError, False)
Finalizing:
in all this function there should be:
Local $iError = DllStructGetData($tEditStream, "dwError") If $iError <> 0 Then Return SetError(700, $iError, False)
Instead:
Local $iError = DllStructGetData($tEditStream, "dwError") If $iError <> 1 Then Return SetError(700, $iError, False)
comment:5 Changed 10 years ago by mLipok
and I think the last post:
all fixed functions:
; #FUNCTION# ====================================================================================================================
; Authors........: Chris Haslam (c.haslam)
; Modified ......: mLipok
; ===============================================================================================================================
Func _GUICtrlRichEdit_StreamFromFile($hWnd, $sFileSpec, $iFileEncoding = Default)
If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, False)
Local $tEditStream = DllStructCreate($tagEDITSTREAM)
DllStructSetData($tEditStream, "pfnCallback", DllCallbackGetPtr($__g_pGRC_StreamFromFileCallback))
Local $hFile
If $iFileEncoding = Default Then
$hFile = FileOpen($sFileSpec, $FO_READ)
Else
$hFile = FileOpen($sFileSpec, $FO_READ + $iFileEncoding)
EndIf
If $hFile = -1 Then Return SetError(1021, 0, False)
Local $sBuf = FileRead($hFile, 5)
FileClose($hFile)
$hFile = FileOpen($sFileSpec, $FO_READ + $iFileEncoding) ; reopen it at the start
DllStructSetData($tEditStream, "dwCookie", $hFile) ; -> Send handle to CallbackFunc
Local $wParam = ($sBuf == "{\rtf" Or $sBuf == "{urtf") ? $SF_RTF : $SF_TEXT
$wParam = BitOR($wParam, $SFF_SELECTION)
If Not _GUICtrlRichEdit_IsTextSelected($hWnd) Then
_GUICtrlRichEdit_SetText($hWnd, "")
EndIf
Local $iQchs = _SendMessage($hWnd, $EM_STREAMIN, $wParam, $tEditStream, 0, "wparam", "struct*")
FileClose($hFile)
Local $iError = DllStructGetData($tEditStream, "dwError")
If $iError <> 0 Then Return SetError(700, $iError, False)
If $iQchs = 0 Then
If FileGetSize($sFileSpec) = 0 Then Return SetError(1022, 0, False)
Return SetError(700, $iError, False)
EndIf
Return True
EndFunc ;==>_GUICtrlRichEdit_StreamFromFile
; #FUNCTION# ====================================================================================================================
; Authors........: Chris Haslam (c.haslam)
; Modified ......: mLipok
; ===============================================================================================================================
Func _GUICtrlRichEdit_StreamFromVar($hWnd, $sVar)
If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, False)
Local $tEditStream = DllStructCreate($tagEDITSTREAM)
DllStructSetData($tEditStream, "pfnCallback", DllCallbackGetPtr($__g_pGRC_StreamFromVarCallback))
$__g_pGRC_sStreamVar = $sVar
Local $s = StringLeft($sVar, 5)
Local $wParam = ($s == "{\rtf" Or $s == "{urtf") ? $SF_RTF : $SF_TEXT
$wParam = BitOR($wParam, $SFF_SELECTION)
If Not _GUICtrlRichEdit_IsTextSelected($hWnd) Then
_GUICtrlRichEdit_SetText($hWnd, "")
EndIf
_SendMessage($hWnd, $EM_STREAMIN, $wParam, $tEditStream, 0, "wparam", "struct*")
Local $iError = DllStructGetData($tEditStream, "dwError")
If $iError <> 0 Then Return SetError(700, $iError, False)
Return True
EndFunc ;==>_GUICtrlRichEdit_StreamFromVar
; #FUNCTION# ====================================================================================================================
; Authors........: Chris Haslam (c.haslam)
; Modified ......: mLipok
; ===============================================================================================================================
Func _GUICtrlRichEdit_StreamToFile($hWnd, $sFileSpec, $bIncludeCOM = True, $iOpts = 0, $iCodePage = 0, $iFileEncoding = Default)
If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, False)
Local $wParam
If StringRight($sFileSpec, 4) = ".rtf" Then
$wParam = ($bIncludeCOM ? $SF_RTF : $SF_RTFNOOBJS)
Else
$wParam = ($bIncludeCOM ? $SF_TEXTIZED : $SF_TEXT)
If BitAND($iOpts, $SFF_PLAINRTF) Then Return SetError(1041, 0, False)
EndIf
; only opts are $SFF_PLAINRTF and $SF_UNICODE
If BitAND($iOpts, BitNOT(BitOR($SFF_PLAINRTF, $SF_UNICODE))) Then Return SetError(1042, 0, False)
If BitAND($iOpts, $SF_UNICODE) Then
If Not BitAND($wParam, $SF_TEXT) Then Return SetError(1043, 0, False)
EndIf
If _GUICtrlRichEdit_IsTextSelected($hWnd) Then $wParam = BitOR($wParam, $SFF_SELECTION)
$wParam = BitOR($wParam, $iOpts)
If $iCodePage <> 0 Then
$wParam = BitOR($wParam, $SF_USECODEPAGE, BitShift($iCodePage, -16))
EndIf
Local $tEditStream = DllStructCreate($tagEDITSTREAM)
DllStructSetData($tEditStream, "pfnCallback", DllCallbackGetPtr($__g_pGRC_StreamToFileCallback))
Local $hFile
If $iFileEncoding = Default Then
$hFile = FileOpen($sFileSpec, $FO_OVERWRITE)
Else
$hFile = FileOpen($sFileSpec, $FO_OVERWRITE + $iFileEncoding)
EndIf
If $hFile = -1 Then Return SetError(102, 0, False)
DllStructSetData($tEditStream, "dwCookie", $hFile) ; -> Send handle to CallbackFunc
_SendMessage($hWnd, $EM_STREAMOUT, $wParam, $tEditStream, 0, "wparam", "struct*")
FileClose($hFile)
Local $iError = DllStructGetData($tEditStream, "dwError")
If $iError <> 0 Then SetError(700, $iError, False)
Return True
EndFunc ;==>_GUICtrlRichEdit_StreamToFile
; #FUNCTION# ====================================================================================================================
; Authors........: Chris Haslam (c.haslam)
; Modified ......: mLipok
; ===============================================================================================================================
Func _GUICtrlRichEdit_StreamToVar($hWnd, $bRtf = True, $bIncludeCOM = True, $iOpts = 0, $iCodePage = 0)
If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, "")
Local $wParam
If $bRtf Then
$wParam = ($bIncludeCOM ? $SF_RTF : $SF_RTFNOOBJS)
Else
$wParam = ($bIncludeCOM ? $SF_TEXTIZED : $SF_TEXT)
If BitAND($iOpts, $SFF_PLAINRTF) Then Return SetError(1041, 0, "")
EndIf
; only opts are $SFF_PLAINRTF and $SF_UNICODE
If BitAND($iOpts, BitNOT(BitOR($SFF_PLAINRTF, $SF_UNICODE))) Then Return SetError(1042, 0, "")
If BitAND($iOpts, $SF_UNICODE) Then
If Not BitAND($wParam, $SF_TEXT) Then Return SetError(1043, 0, "")
EndIf
If _GUICtrlRichEdit_IsTextSelected($hWnd) Then $wParam = BitOR($wParam, $SFF_SELECTION)
$wParam = BitOR($wParam, $iOpts)
If $iCodePage <> 0 Then
$wParam = BitOR($wParam, $SF_USECODEPAGE, BitShift($iCodePage, -16))
EndIf
Local $tEditStream = DllStructCreate($tagEDITSTREAM)
DllStructSetData($tEditStream, "pfnCallback", DllCallbackGetPtr($__g_pGRC_StreamToVarCallback))
$__g_pGRC_sStreamVar = ""
_SendMessage($hWnd, $EM_STREAMOUT, $wParam, $tEditStream, 0, "wparam", "struct*")
Local $iError = DllStructGetData($tEditStream, "dwError")
If $iError <> 0 Then Return SetError(700, $iError, "")
Return $__g_pGRC_sStreamVar
EndFunc ;==>_GUICtrlRichEdit_StreamToVar
Just for copy/paste
comment:6 Changed 10 years ago by Jpm
- Milestone set to 3.3.15.1
- Owner set to Jpm
- Resolution set to Fixed
- Status changed from new to closed
Fixed by revision [11499] in version: 3.3.15.1
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.

Here are proposals:
Func _GUICtrlRichEdit_StreamFromFile($hWnd, $sFileSpec, $iFileEncoding = Default) If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, False) Local $tEditStream = DllStructCreate($tagEDITSTREAM) DllStructSetData($tEditStream, "pfnCallback", DllCallbackGetPtr($__g_pGRC_StreamFromFileCallback)) Local $hFile If $iFileEncoding = Default Then $hFile = FileOpen($sFileSpec, $FO_READ) Else $hFile = FileOpen($sFileSpec, $FO_READ + $iFileEncoding) EndIf If $hFile = -1 Then Return SetError(1021, 0, False) Local $sBuf = FileRead($hFile, 5) FileClose($hFile) $hFile = FileOpen($sFileSpec, $FO_READ) ; reopen it at the start DllStructSetData($tEditStream, "dwCookie", $hFile) ; -> Send handle to CallbackFunc Local $wParam = ($sBuf == "{\rtf" Or $sBuf == "{urtf") ? $SF_RTF : $SF_TEXT $wParam = BitOR($wParam, $SFF_SELECTION) If Not _GUICtrlRichEdit_IsTextSelected($hWnd) Then _GUICtrlRichEdit_SetText($hWnd, "") EndIf Local $iQchs = _SendMessage($hWnd, $EM_STREAMIN, $wParam, $tEditStream, 0, "wparam", "struct*") FileClose($hFile) Local $iError = DllStructGetData($tEditStream, "dwError") If $iError <> 1 Then SetError(700, $iError, False) If $iQchs = 0 Then If FileGetSize($sFileSpec) = 0 Then Return SetError(1022, 0, False) Return SetError(700, $iError, False) EndIf Return True EndFunc ;==>_GUICtrlRichEdit_StreamFromFile