Modify

Opened 4 years ago

Closed 4 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)

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

Download all attachments as: .zip

Change History (7)

Changed 4 years ago by mLipok

comment:1 Changed 4 years ago by mLipok

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 Changed 4 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 4 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 4 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 4 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 4 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.

Add Comment

Modify Ticket

Action
as closed The owner will remain Jpm.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.