Modify

Opened 11 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: J-Paul Mesnage
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)

wzor.rtf (182 bytes ) - added by mLipok 11 years ago.

Download all attachments as: .zip

Change History (7)

by mLipok, 11 years ago

Attachment: wzor.rtf added

comment:1 by mLipok, 11 years ago

Here are proposals:

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
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

comment:2 by J-Paul Mesnage, 11 years ago

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 by mLipok, 11 years ago

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 by mLipok, 11 years ago

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 by mLipok, 11 years ago

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 by J-Paul Mesnage, 10 years ago

Milestone: 3.3.15.1
Owner: set to J-Paul Mesnage
Resolution: Fixed
Status: newclosed

Fixed by revision [11499] in version: 3.3.15.1

Modify Ticket

Action
as closed The owner will remain J-Paul Mesnage.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.