Re: RichEditBox handling of Unicode text files now fixed
Thanks Kevin.kcarmody wrote: I will put together a posting like this with my changes. There are several dozen changes, so it will be a big posting and will take a while to put together.
Exclusive forum for HMG, a Free / Open Source xBase WIN32/64 Bits / GUI Development System
http://mail.hmgforum.com/
Thanks Kevin.kcarmody wrote: I will put together a posting like this with my changes. There are several dozen changes, so it will be a big posting and will take a while to put together.
Code: Select all
// Following 5 #defines added by Kevin Carmody, November 2014
*****************
* File type *
*****************
#define RTFTXTFILE_ANSI 1 // ANSI text file
#define RTFTXTFILE_UTF8 2 // UTF-8 text file
#define RTFTXTFILE_UTF16LE 3 // UTF-16 LE (little endian) text file
#define RTFTXTFILE_RTF 4 // RTF file
#define RTFTXTFILE_UTF16BE 5 // UTF-16 BE (big endian) text file
Code: Select all
// Following function added by Kevin Carmody, November 2014
*-----------------------------------------------------------------------------*
FUNCTION GetRtfTxtFileType ( cFile, lUtf8Test )
*-----------------------------------------------------------------------------*
LOCAL hFile := FOPEN( cFile, FO_READ )
LOCAL cBuffer := SPACE( 5 )
LOCAL nBufRead := 0
LOCAL nType := 0
/*
The following code block tests for the presence of non-ASCII characters in
an unmarked text file. It assumes that such characters may be ANSI or
parts of UTF-8 sequences. In UTF-8 mode, Windows reads bytes which are not
part of a valid UTF-8 sequence as ANSI. It would be better to know if the
file contained UTF-8 sequences for non-ANSI characters, but since some ANSI
characters are not in the Latin-1 Supplement, testing for non-ANSI UTF-8
sequences is inefficient for large files.
*/
LOCAL bHasUnicodeChars := {||
LOCAL lHasUnicode := .N.
LOCAL cChar, cStr
cBuffer := SPACE( 0x400 )
nBufRead := 1
BEGIN SEQUENCE
WHILE nBufRead > 0
nBufRead := FREAD( hFile, @cBuffer, 0x400 )
IF nBufRead > 0
cStr := LEFT( cBuffer, nBufRead )
FOR EACH cChar IN cStr
IF cChar >= CHR(0x80)
lHasUnicode := .Y.
BREAK
ENDIF
NEXT
ENDIF
ENDDO
END SEQUENCE
RETURN lHasUnicode
}
BEGIN SEQUENCE
IF hFile < 0
BREAK
ENDIF
nBufRead := FREAD( hFile, @cBuffer, 5 )
DO CASE
CASE nBufRead >= 5 .AND. LEFT( cBuffer, 5 ) == "{\rtf"
nType := RTFTXTFILE_RTF
CASE nBufRead >= 3 .AND. LEFT( cBuffer, 3 ) == E"\xEF\xBB\xBF"
nType := RTFTXTFILE_UTF8
CASE nBufRead >= 2 .AND. LEFT( cBuffer, 2 ) == E"\xFF\xFE"
nType := RTFTXTFILE_UTF16LE
CASE nBufRead >= 2 .AND. LEFT( cBuffer, 2 ) == E"\xFE\xFF"
nType := RTFTXTFILE_UTF16BE
CASE ! EMPTY( lUtf8Test ) .AND. bHasUnicodeChars:EVAL( )
nType := RTFTXTFILE_UTF8
OTHERWISE
nType := RTFTXTFILE_ANSI
ENDCASE
END SEQUENCE
FCLOSE( hFile )
RETURN nType
Code: Select all
LOCAL nFormat := GETRTFTXTFILETYPE( cFileName, .Y. )
Code: Select all
// Following function added by Kevin Carmody, November 2014
*-----------------------------------------------------------------------------*
FUNCTION Utf16ByteSwap( cInFile, cOutFile )
*-----------------------------------------------------------------------------*
LOCAL hInFile := FOPEN( cInFile , FO_READ )
LOCAL hOutFile := FCREATE( cOutFile )
LOCAL cInBuffer := SPACE( 0x400 )
LOCAL nBufRead := 1
LOCAL lSuccess := .N.
LOCAL cOutBuffer, cBytePair, nBufWrite, nByte
BEGIN SEQUENCE
IF hInFile < 0
BREAK
ENDIF
IF hOutFile < 0
BREAK
ENDIF
WHILE nBufRead > 0
cOutBuffer := ""
nBufRead := FREAD( hInFile, @cInBuffer, 0x400 )
IF nBufRead > 0
FOR nByte := 1 TO nBufRead STEP 2
cBytePair := SUBSTR( cInBuffer, nByte, 2 )
cOutBuffer += RIGHT( cBytePair, 1 ) + LEFT( cBytePair, 1 )
NEXT
nBufWrite := FWRITE( hOutFile, cOutBuffer )
IF nBufWrite < nBufRead
BREAK
ENDIF
ENDIF
ENDDO
lSuccess := .Y.
END SEQUENCE
FCLOSE( hInFile )
FCLOSE( hOutFile )
RETURN lSuccess
Code: Select all
// RichEditBox_StreamIn ( hWndControl, cFileName, lSelection, nDataFormat ) --> return lSuccess
HB_FUNC ( RICHEDITBOX_STREAMIN )
{
HWND hWndControl = (HWND) HMG_parnl (1);
TCHAR *cFileName = (TCHAR*) HMG_parc (2);
BOOL lSelection = (BOOL) hb_parl (3);
LONG nDataFormat = (LONG) hb_parnl (4);
HANDLE hFile;
// Following 3 lines added by Kevin Carmody, November 2014
BYTE bUtf8Bom[3];
BYTE bUtf16Bom[2];
DWORD dwRead;
EDITSTREAM es;
LONG Format;
switch( nDataFormat )
{
// Comments in this switch block modified by Kevin Carmody, November 2014
case 1: Format = SF_TEXT; break; // ANSI or UTF-8 with BOM or mixed (UTF-8 BOM removed, overlong UTF-8 accepted, invalid UTF-8 read as ANSI)
case 2: Format = ( CP_UTF8 << 16 ) | SF_USECODEPAGE | SF_TEXT; break; // UTF-8 without BOM (BOM not removed)
case 3: Format = SF_TEXT | SF_UNICODE; break; // UTF-16 LE without BOM (BOM not removed)
case 4: Format = SF_RTF; break;
// case 5, UTF-8 RTF, removed by Kevin Carmody, November 2014, because it can never occur
default: Format = SF_RTF; break;
}
if ( lSelection )
Format = Format | SFF_SELECTION;
if( ( hFile = CreateFile (cFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL )) == INVALID_HANDLE_VALUE )
{ hb_retl (FALSE);
return;
}
// Following switch block added by Kevin Carmody, November 2014
switch( nDataFormat )
{
case 1: break;
case 2:
if ( ! ReadFile (hFile, bUtf8Bom, 3, &dwRead, NULL) ) // read past BOM if present
hb_retl (FALSE);
if ( ! ( dwRead == 3 && bUtf8Bom[0] == 0xEF && bUtf8Bom[1] == 0xBB && bUtf8Bom[2] == 0xBF ) )
SetFilePointer (hFile, 0, 0, FILE_BEGIN);
break;
case 3:
if ( ! ReadFile (hFile, bUtf16Bom, 2, &dwRead, NULL) ) // read past BOM if present
hb_retl (FALSE);
if ( ! ( dwRead == 2 && bUtf16Bom[0] == 0xFF && bUtf16Bom[1] == 0xFE ) )
SetFilePointer (hFile, 0, 0, FILE_BEGIN);
break;
case 4: break;
default: break;
}
es.pfnCallback = EditStreamCallbackRead;
es.dwCookie = (DWORD_PTR) hFile;
es.dwError = 0;
SendMessage ( hWndControl, EM_STREAMIN, (WPARAM) Format, (LPARAM) &es );
CloseHandle (hFile);
if( es.dwError )
hb_retl (FALSE);
else
hb_retl (TRUE);
}
Code: Select all
// RichEditBox_StreamOut ( hWndControl, cFileName, lSelection, nDataFormat ) --> return lSuccess
HB_FUNC ( RICHEDITBOX_STREAMOUT )
{
HWND hWndControl = (HWND) HMG_parnl (1);
TCHAR *cFileName = (TCHAR*) HMG_parc (2);
BOOL lSelection = (BOOL) hb_parl (3);
LONG nDataFormat = (LONG) hb_parnl (4);
HANDLE hFile;
// Following 3 lines added by Kevin Carmody, November 2014
BYTE bUtf8Bom[3] = {0xEF, 0xBB, 0xBF};
BYTE bUtf16Bom[2] = {0xFF, 0xFE};
DWORD dwWritten;
EDITSTREAM es;
LONG Format;
switch( nDataFormat )
{
// Comments in this switch block modified by Kevin Carmody, November 2014
case 1: Format = SF_TEXT; break; // ANSI (non-ANSI characters converted to question marks)
case 2: Format = ( CP_UTF8 << 16 ) | SF_USECODEPAGE | SF_TEXT; break; // UTF-8 without BOM
case 3: Format = SF_TEXT | SF_UNICODE; break; // UTF-16 LE without BOM
case 4: Format = SF_RTF; break;
// case 5, UTF-8 RTF, removed by Kevin Carmody, November 2014, because it can never occur
default: Format = SF_RTF; break;
}
if ( lSelection )
Format = Format | SFF_SELECTION;
if( ( hFile = CreateFile (cFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE )
{ hb_retl (FALSE);
return;
}
// Following switch block added by Kevin Carmody, November 2014
switch( nDataFormat )
{
case 1: break;
case 2: WriteFile( hFile, bUtf8Bom, 3, &dwWritten, NULL ); break; // write UTF-8 BOM at head of file
case 3: WriteFile( hFile, bUtf16Bom, 2, &dwWritten, NULL ); break; // write UTF-16 LE BOM at head of file
case 4: break;
default: break;
}
es.pfnCallback = EditStreamCallbackWrite;
es.dwCookie = (DWORD_PTR) hFile;
es.dwError = 0;
SendMessage ( hWndControl, EM_STREAMOUT, (WPARAM) Format, (LPARAM) &es );
CloseHandle (hFile);
if( es.dwError )
hb_retl (FALSE);
else
hb_retl (TRUE);
}
Code: Select all
// Following case added by Kevin Carmody, November 2014
CASE Arg3 == "HASUNICODECHARS"
xData := RichEditBox_HasUnicodeChars ( hWndControl )
RetVal := .T.
Code: Select all
;; // Following line modified by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFTextMode,AutoURLDetect,Zoom,SelectRange,CaretPos,Value,GetSelectText,GetTextLength,ViewRect,HasUnicodeChars\> => GetProperty ( <"w">, \<"c"\> , \<"p"\> ) ;;
Code: Select all
// Following function added by Kevin Carmody, November 2014
/*
The following function tests for the presence of non-ASCII characters in
a rich edit control. It would be better to know if the control contained
non-ANSI characters, but since some ANSI characters are not in the Latin-1
Supplement, testing for non-ANSI characters is inefficient for large
documents.
*/
*-----------------------------------------------------------------------------*
FUNCTION RichEditBox_HasUnicodeChars( hWndControl )
*-----------------------------------------------------------------------------*
LOCAL cBuffer := RichEditBox_GetText( hWndControl , .N. )
LOCAL lHasUnicode := .N.
LOCAL cChar
FOR EACH cChar IN cBuffer
IF cChar >= CHR(0x80)
lHasUnicode := .Y.
ENDIF
NEXT
RETURN lHasUnicode
Code: Select all
LOCAL lUnicode := wMain.ebDoc.HASUNICODECHARS
Code: Select all
// Following case modified by Kevin Carmody, November 2014
CASE Arg3 == "RTFLOADFILE" .OR. Arg3 == "RTFTXTLOADFILE"
xData := RichEditBox_RtfTxtLoadFile ( hWndControl, Arg4, Arg5, Arg6 ) // by default save in SF_RTF format
RetVal := .T.
Code: Select all
;; // Following 2 lines modified by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>,\<arg3\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\>, \<arg3\> ) ;;
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\> ) ;;
;; // Following line added by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> ) ;;
Code: Select all
// Following function added by Kevin Carmody, November 2014
*-----------------------------------------------------------------------------*
FUNCTION RichEditBox_RtfTxtLoadFile( hWndControl, cFile, lSelection, nType )
*-----------------------------------------------------------------------------*
LOCAL lSuccess := .N.
LOCAL cTempFile
IF ! HB_ISLOGICAL( lSelection )
lSelection := .N.
ENDIF
IF ! HB_ISNUMERIC( nType )
nType := RTFTXTFILE_RTF
ENDIF
IF lSelection
RichEditBox_UnSelectAll( hWndControl )
ENDIF
IF RichEditBox_RTFLoadResourceFile( hWndControl, cFile, lSelection )
lSuccess := .T.
ELSE
IF nType == RTFTXTFILE_UTF16BE
cTempFile := GETTEMPFOLDER() + "_RtfTxtLoadFile.txt"
lSuccess := Utf16ByteSwap( cFile, cTempFile )
IF lSuccess
lSuccess := RichEditBox_StreamIn( hWndControl, cTempFile, lSelection, RTFTXTFILE_UTF16LE )
ENDIF
DELETE FILE ( cTempFile )
ELSE
lSuccess := RichEditBox_StreamIn( hWndControl, cFile, lSelection, nType )
ENDIF
ENDIF
RETURN lSuccess
Code: Select all
IF ! wMain.ebDoc.RTFTXTLOADFILE( cFileName, .N., nFormat )
Code: Select all
// Following case modified by Kevin Carmody, November 2014
CASE Arg3 == "RTFSAVEFILE" .OR. Arg3 == "RTFTXTSAVEFILE"
xData := RichEditBox_RtfTxtSaveFile ( hWndControl, Arg4, Arg5, Arg6 ) // by default save in SF_RTF format
RetVal := .T.
Code: Select all
;; // Following 2 lines modified by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>,\<arg3\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\>, \<arg3\> ) ;;
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\> ) ;;
;; // Following line added by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> ) ;;
Code: Select all
// Following function added by Kevin Carmody, November 2014
*-----------------------------------------------------------------------------*
FUNCTION RichEditBox_RtfTxtSaveFile( hWndControl, cFile, lSelection, nType )
*-----------------------------------------------------------------------------*
LOCAL lSuccess := .N.
LOCAL cTempFile
IF ! HB_ISLOGICAL( lSelection )
lSelection := .N.
ENDIF
IF ! HB_ISNUMERIC( nType )
nType := RTFTXTFILE_RTF
ENDIF
IF nType == RTFTXTFILE_UTF16BE
cTempFile := GETTEMPFOLDER() + "_RtfTxtLoadFile.txt"
lSuccess := RichEditBox_StreamOut( hWndControl, cTempFile, lSelection, RTFTXTFILE_UTF16LE )
IF lSuccess
lSuccess := Utf16ByteSwap( cTempFile, cFile )
ENDIF
DELETE FILE ( cTempFile )
ELSE
lSuccess := RichEditBox_StreamOut( hWndControl, cFile, lSelection, nType )
ENDIF
RETURN lSuccess
Code: Select all
IF ! wMain.ebDoc.RTFTXTSAVEFILE( cFileName, .N., nFormat )
Code: Select all
// Following case added by Kevin Carmody, November 2014
CASE Arg3 == HMG_UPPER ("SelPasteSpecial")
RichEditBox_PasteSpecial ( hWndControl, Arg4 )
RetVal := .T.
Code: Select all
;; // Following line added by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:SelPasteSpecial\> (\<arg1\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> ) ;;
Code: Select all
// Following case modified by Kevin Carmody, November 2014
CASE Arg3 == "RTFLOADFILE" .OR. Arg3 == "RTFTXTLOADFILE"
xData := RichEditBox_RtfTxtLoadFile ( hWndControl, Arg4, Arg5, Arg6 ) // by default save in SF_RTF format
RetVal := .T.
Code: Select all
;; // Following 2 lines modified by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>,\<arg3\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\>, \<arg3\> ) ;;
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\> ) ;;
;; // Following line added by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> ) ;;
Code: Select all
// Following case modified by Kevin Carmody, November 2014
CASE Arg3 == "RTFSAVEFILE" .OR. Arg3 == "RTFTXTSAVEFILE"
xData := RichEditBox_RtfTxtSaveFile ( hWndControl, Arg4, Arg5, Arg6 ) // by default save in SF_RTF format
RetVal := .T.
Code: Select all
// Following 2 lines modified by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>,\<arg3\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\>, \<arg3\> ) ;;
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>,\<arg2\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> , \<arg2\> ) ;;
// Following line added by Kevin Carmody, November 2014
#xtranslate <w>. \<c\> . \<p:RTFLoadFile,RTFSaveFile,RtfTxtLoadFile,RtfTxtSaveFile\> (\<arg1\>) => DoMethod ( <"w">, \<"c"\> , \<"p"\> , \<arg1\> ) ;;
Code: Select all
HB_FUNC ( C_GETFILE )
{
#define _MAXMULTISELECTFILE 1024
OPENFILENAME ofn;
TCHAR buffer [ _MAXMULTISELECTFILE * MAX_PATH ];
TCHAR cFullName [ _MAXMULTISELECTFILE ] [ MAX_PATH ];
TCHAR cCurDir [ MAX_PATH ];
TCHAR cFileName [ MAX_PATH ];
// Following line added by Kevin Carmody, November 2014
int iFilterIndex = 1;
int iPosition = 0;
int iNumSelected = 0;
int flags = OFN_FILEMUSTEXIST | OFN_EXPLORER;
memset ((void*)&buffer, 0, sizeof(buffer));
if ( hb_parl(4) )
flags = flags | OFN_ALLOWMULTISELECT ;
if ( hb_parl(5) )
flags = flags | OFN_NOCHANGEDIR ;
// Following if statement added by Kevin Carmody, November 2014
if ( hb_parni(6) )
iFilterIndex = hb_parni(6) ;
//******************************************************************************************************//
// ofn.lpstrFilter = A buffer containing pairs of null-terminated filter strings.
// The last string in the buffer must be terminated by two NULL characters.
// The following code converts a ANSI (CHAR) filter string into a UNICODE (UNSIGNED INT) filter string
#define _MAX_FILTER 5*1024
INT i, j=0, cont=0;
CHAR *p = (CHAR*) hb_parc(1);
TCHAR Filter [ _MAX_FILTER ];
memset((void*) &Filter, 0, sizeof(Filter));
for (i=0; *p != '\0'; i++)
{ cont = cont + strlen (p) + 1;
if (cont < _MAX_FILTER)
{ lstrcpy ( &Filter[j], HMG_CHAR_TO_WCHAR(p) );
j = j + lstrlen ( HMG_CHAR_TO_WCHAR (p) ) + 1;
p = p + strlen (p) + 1;
}
else
break;
}
//**********************************************************************//
memset( (void*) &ofn, 0, sizeof( OPENFILENAME ) );
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetActiveWindow();
ofn.lpstrFilter = (LPCTSTR) &Filter;
// Following statement modified by Kevin Carmody, November 2014
ofn.nFilterIndex = (DWORD) iFilterIndex;
ofn.lpstrFile = (LPTSTR) &buffer;
ofn.nMaxFile = sizeof(buffer) / sizeof(TCHAR);
ofn.lpstrInitialDir = (LPCTSTR) HMG_parc(3);
ofn.lpstrTitle = (LPCTSTR) HMG_parc(2);
ofn.Flags = flags;
if( GetOpenFileName (&ofn) )
{
if ( ofn.nFileExtension !=0 )
HMG_retc (ofn.lpstrFile);
else
{
wsprintf ( cCurDir, _TEXT("%s"), &buffer [iPosition] );
iPosition = iPosition + lstrlen (cCurDir) + 1;
do
{
iNumSelected ++;
wsprintf ( cFileName, _TEXT("%s"), &buffer [iPosition] );
iPosition = iPosition + lstrlen (cFileName) + 1;
wsprintf ( cFullName [iNumSelected], _TEXT("%s\\%s"), cCurDir, cFileName);
}
while (( lstrlen(cFileName) !=0 ) && ( iNumSelected < _MAXMULTISELECTFILE ));
if (iNumSelected > 1)
{
hb_reta (iNumSelected - 1);
for (i = 1; i < iNumSelected; i++)
HMG_storvc (cFullName[i], -1, i );
}
else
HMG_retc( &buffer[0] );
}
}
else
HMG_retc( _TEXT("") );
}
Code: Select all
*-----------------------------------------------------------------------------*
// Following line modified by Kevin Carmody, November 2014
Function GetFile( aFilter, title, cIniFolder, multiselect, nochangedir, nFilterIndex )
*-----------------------------------------------------------------------------*
local c := ''
local cfiles := ''
local fileslist := {}
local n
Local i
IF aFilter == Nil
aFilter := {}
EndIf
IF title == NIL
title := ""
ENDIF
IF cIniFolder == NIL
cIniFolder := ""
ENDIF
FOR n:=1 TO HMG_LEN(aFilter)
c := c + aFilter[n][1] + CHR(0) + aFilter[n][2] + CHR(0)
NEXT
c := c + CHR(0)
if valtype(multiselect) == 'U'
multiselect := .f.
endif
// Following if block added by Kevin Carmody, November 2014
if nFilterIndex == NIL
nFilterIndex := 1
endif
if .not. multiselect
// Following line modified by Kevin Carmody, November 2014
Return ( C_GetFile ( c , title, cIniFolder, multiselect, nochangedir, nFilterIndex ) )
else
// Following line modified by Kevin Carmody, November 2014
cfiles := C_GetFile ( c , title, cIniFolder, multiselect, nochangedir, nFilterIndex )
if HMG_LEN( cfiles ) > 0
if valtype( cfiles ) == "A"
fileslist := aclone( cfiles )
else
aadd( fileslist, cfiles )
endif
endif
For i := 1 To HMG_LEN ( FilesList)
FilesList [i] := HB_UTF8STRTRAN ( FilesList [i] , "\\" , "\" )
Next i
Return ( FilesList )
endif
Return Nil
Code: Select all
cAuxFileName := GETFILE( aReadFilter, 'Open', cFileFolder, NIL, NIL, nReadFilter )
Code: Select all
HB_FUNC ( C_PUTFILE )
{
OPENFILENAME ofn;
TCHAR buffer[1024];
// Following line added by Kevin Carmody, November 2014
int iFilterIndex = 1;
int flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER ;
if ( hb_parl(4) )
{
flags = flags | OFN_NOCHANGEDIR ;
}
// Following if statement added by Kevin Carmody, November 2014
if ( hb_parni(7) )
{
iFilterIndex = hb_parni(7) ;
}
//******************************************************************************************************//
// ofn.lpstrFilter = A buffer containing pairs of null-terminated filter strings.
// The last string in the buffer must be terminated by two NULL characters.
// The following code converts a ANSI (CHAR) filter string into a UNICODE (UNSIGNED INT) filter string
#define _MAX_FILTER 5*1024
INT i, j=0, cont=0;
CHAR *p = (CHAR*) hb_parc(1);
TCHAR Filter [_MAX_FILTER];
memset((void*) &Filter, 0, sizeof(Filter));
for (i=0; *p != '\0'; i++)
{ cont = cont + strlen (p) + 1;
if (cont < _MAX_FILTER)
{ lstrcpy ( &Filter[j], HMG_CHAR_TO_WCHAR (p) );
j = j + lstrlen ( HMG_CHAR_TO_WCHAR (p) ) + 1;
p = p + strlen (p) + 1;
}
else
break;
}
//**********************************************************************//
lstrcpy (buffer, HMG_parc(5));
memset( (void*) &ofn, 0, sizeof( OPENFILENAME ) );
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetActiveWindow() ;
ofn.lpstrFilter = (LPCTSTR) &Filter;
// Following statement modified by Kevin Carmody, November 2014
ofn.nFilterIndex = (DWORD) iFilterIndex;
ofn.lpstrFile = (LPTSTR) &buffer;
ofn.nMaxFile = sizeof(buffer) / sizeof(TCHAR);
ofn.lpstrInitialDir = (LPCTSTR) HMG_parc(3);
ofn.lpstrTitle = (LPCTSTR) HMG_parc(2);
ofn.Flags = flags;
ofn.lpstrDefExt = (LPCTSTR) HMG_parc(6);
if ( GetSaveFileName (&ofn) )
{ if (HB_ISBYREF(6))
{ if (ofn.nFileExtension > ofn.nFileOffset)
HMG_storc (&ofn.lpstrFile [ofn.nFileExtension], 6);
else
HMG_storc (_TEXT(""), 6);
}
// Following if statement added by Kevin Carmody, November 2014
if (HB_ISBYREF(7))
{
hb_stornl ((LONG) ofn.nFilterIndex, 7);
}
HMG_retc(ofn.lpstrFile);
}
else
HMG_retc( _TEXT("") );
}
Code: Select all
*--------------------------------------------------------------------------------------------*
// Following line modified by Kevin Carmody, November 2014
Function Putfile ( aFilter, cTitle, cIniFolder, lNoChangeDir, cDefaultFileName, cExtFile, nFilterIndex )
*--------------------------------------------------------------------------------------------*
LOCAL cFilter:='' , n, cFileName
IF aFilter == Nil
aFilter:={}
EndIf
IF cTitle == NIL
cTitle := ""
ENDIF
IF cIniFolder == NIL
cIniFolder := ""
ENDIF
IF cDefaultFileName == NIL
cDefaultFileName := ""
ENDIF
// Following if block added by Kevin Carmody, November 2014
IF nFilterIndex == NIL
nFilterIndex := 1
ENDIF
FOR n := 1 TO HMG_LEN ( aFilter )
cFilter = cFilter + aFilter [n] [1] + CHR(0) + aFilter [n] [2] + CHR(0)
NEXT
cFilter := cFilter + CHR(0)
// Following line modified by Kevin Carmody, November 2014
cFileName := C_PutFile ( cFilter, cTitle, cIniFolder, lNoChangeDir, cDefaultFileName, @cExtFile, @nFilterIndex )
Return cFileName
Code: Select all
cAuxFileName := PUTFILE( aWriteFilter, 'Save As', cFileFolder, ;
NIL, cFileName, @cFileExt, @nWriteFilter )
Code: Select all
Function DoMethod ( Arg1 , Arg2 , Arg3 , Arg4 , Arg5 , Arg6 , Arg7 , Arg8 , Arg9 )
// Following line modified by Kevin Carmody, November 2014
Local xData, i, hWnd
Code: Select all
// Following 2 lines modified by Kevin Carmody, November 2014
IF _RichEditBox_DoMethod ( @xData, Arg1 , Arg2 , Arg3 , Arg4 , Arg5 , Arg6 , Arg7 , Arg8 , Arg9 ) == .T.
Return xData
ENDIF
Code: Select all
// Following line modified by Kevin Carmody, November 2014
Function _RichEditBox_DoMethod ( xData, Arg1 , Arg2 , Arg3 , Arg4 , Arg5 , Arg6 , Arg7 , Arg8 , Arg9 )
Code: Select all
IF ! wMain.ebDoc.RTFTXTLOADFILE( cFileName, .N., nFormat )
Code: Select all
IF ! wMain.ebDoc.RTFTXTSAVEFILE( cFileName, .N., nFormat )
Eagerly waiting for new versionsrvet_claudio wrote:Thanks Kevin.
Many of these changes will be for the next version because HMG.3.3.2 now is ready.
Some years ago I wrote a Harbour library called UnicodeLib that has functions for converting between ANSI, Unicode, RTF, and HTML. Some of these functions now have equivalents in Harbour, but I don't think the HTML conversions do. You can download UnicodeLib from http://kevincarmody.com/software/akshar ... unicodelib.serge_girard wrote:Question: any idea about a function for converting to HTML...?
That would be so great!