It is written in C, uses the RICHEDIT control and offers the minimal functionality I need. I can give you the source code if it can be useful for you.
I was interested to review how much functionality RichEdit could offer as a Windows built-in source code editor. I remembered that RichEdit coloring was very slow for large files and that was the main problem about it. So I decided to do some more research about it. First interesting info I found was this one:
http://bcbjournal.org/articles/vol3/9910/Faster_rich_edit_syntax_highlighting.htm
Its author uses C++ Builder and found some ways to speed it up. So I decided to create a plain C language self contained example to test how fast his optimizations are. You can easily build it using Borland C:
go.bat
Code: Select all | Expand
set path=c:\bcc582\bin
bcc32 -W test.c
if errorlevel 0 test
test.c // RichEdit based editor with automatic syntax highligthing
Code: Select all | Expand
#include <windows.h>
#include <richedit.h>
#include <stdio.h>
typedef struct
{
char * txt;
long len;
FILE * out;
} COOKIE;
#define CLR_YELLOW RGB( 255, 255, 0 )
#define CLR_HCYAN RGB( 0, 255, 255 )
#define CLR_HGREEN RGB( 0, 255, 0 )
#define CLR_WHITE RGB( 255, 255, 255 )
void ParseAllText( HWND hRichEdit )
{
LONG pos = 0, start = 1;
CHARFORMAT cf;
TEXTRANGE tr;
char buffer[ 256 ];
int eventMask = SendMessage( hRichEdit, EM_SETEVENTMASK, 0, 0 );
SendMessage( hRichEdit, WM_SETREDRAW, FALSE, 0 );
memset( &cf, 0, sizeof( cf ) );
cf.cbSize = sizeof( cf );
cf.dwMask = CFM_COLOR;
while( pos != start )
{
start = pos;
pos = SendMessage( hRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, pos );
SendMessage( hRichEdit, EM_SETSEL, start, pos );
tr.chrg.cpMin = start;
tr.chrg.cpMax = pos;
tr.lpstrText = buffer; // malloc( pos - start + 1 + 1 );
SendMessage( hRichEdit, EM_GETTEXTRANGE, 0, ( LPARAM ) &tr );
if( strstr( "# define ifdef ifndef endif pragma include ", tr.lpstrText ) )
{
cf.crTextColor = CLR_YELLOW;
SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
}
else if( strstr( "local static extern public private nil for next if else endif do case endcase ", tr.lpstrText ) )
{
cf.crTextColor = CLR_HCYAN;
SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
}
else if( strstr( "function CLASS DATA INIT METHOD INLINE VIRTUAL SETGET ENDCLASS procedure return ", tr.lpstrText ) )
{
cf.crTextColor = CLR_HGREEN;
SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
}
else if( strstr( "= + - ++ -- += -= *= /= / * < > <= >= % $ | ! ^ @ {} {}, { } {| [ ] ]: ( ) (- ), ): ); ),; () (): :: := != == += -= . , ; ,; .,; ", tr.lpstrText ) )
{
cf.crTextColor = CLR_WHITE;
SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
}
// free( tr.lpstrText );
}
SendMessage( hRichEdit, WM_SETREDRAW, TRUE, 0 );
SendMessage( hRichEdit, EM_SETEVENTMASK, 0, eventMask );
InvalidateRect( hRichEdit, 0, TRUE );
}
#pragma argsused
DWORD CALLBACK StreamIn( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb )
{
COOKIE * Cookie = ( COOKIE * ) dwCookie;
if( cb > Cookie->len )
cb = Cookie->len;
if( cb > 0 )
{
memcpy( ( char * ) pbBuff, Cookie -> txt, cb );
Cookie->txt += cb;
Cookie->len -= cb;
}
* pcb = cb;
return 0;
}
BOOL LoadText( HWND hRichEdit, const char * FileName )
{
FILE * in = fopen( FileName, "rb" );
int len;
if( ! in )
return FALSE;
fseek( in, 0, SEEK_END );
len = ftell( in );
fseek( in, 0, SEEK_SET );
if( len > 0 )
{
COOKIE Cookie;
EDITSTREAM es;
char * txt = malloc( len + 1 );
fread( txt, 1, len, in );
Cookie.txt = txt;
Cookie.len = len;
es.dwCookie = ( DWORD ) &Cookie;
es.pfnCallback = StreamIn;
SendMessage( hRichEdit, EM_STREAMIN, SF_TEXT, ( LPARAM ) &es );
free( txt );
}
fclose( in );
return TRUE;
}
LRESULT WINAPI ParentWindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
static HWND hRichEdit;
static HFONT hFont;
switch( msg )
{
case WM_CREATE:
{
RECT r;
GetClientRect( hWnd, &r );
hRichEdit = CreateWindow( "RICHEDIT", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_SUNKEN,
0, 30, r.right - r.left, r.bottom - r.top - 50,
hWnd, NULL, NULL, NULL );
hFont = CreateFont( 18, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Courier New" );
SendMessage( hRichEdit, WM_SETFONT, ( WPARAM ) hFont, 0 );
LoadText( hRichEdit, "window.prg" );
SendMessage( hRichEdit, EM_EXLIMITTEXT, 0, 0xFFFFFFF );
ParseAllText( hRichEdit );
SetFocus( hRichEdit );
}
break;
case WM_CLOSE:
DeleteObject( hFont );
DestroyWindow( hWnd );
break;
case WM_LBUTTONDOWN:
break;
case WM_SIZE:
MoveWindow( hRichEdit, 0, 30, LOWORD( lParam ), HIWORD( lParam ) - 50, FALSE );
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show )
{
WNDCLASS cls;
HWND hWnd;
MSG msg;
HINSTANCE hDll = LoadLibrary( "riched32" );
cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
cls.lpfnWndProc = ParentWindowProc;
cls.cbClsExtra = 0;
cls.cbWndExtra = 0;
cls.hInstance = hInstance;
cls.hIcon = LoadIcon( 0, IDI_APPLICATION );
cls.hCursor = LoadCursor( 0, IDC_ARROW );
cls.hbrBackground = GetStockObject( WHITE_BRUSH );
cls.lpszMenuName = 0;
cls.lpszClassName = "parentclass";
if( ! RegisterClass( &cls ) )
return FALSE;
hWnd = CreateWindow( "parentClass", "RichEdit syntax highlight", WS_OVERLAPPEDWINDOW ,
100, 100, 1100, 600, 0, NULL, hInstance, 0 );
ShowWindow( hWnd, SW_MAXIMIZE );
UpdateWindow( hWnd );
while( GetMessage( &msg, 0, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
FreeLibrary( hDll );
return 0;
}
No Harbour, no FWH, just pure C language speed to test it, but unfortunately still slow for large PRG files. So I decided to keep googling and then found this:
http://win32assembly.online.fr/tut35.html
It may result scaring at a first review as it is developed using assembler (ouch!)
![Smile :-)](./images/smilies/icon_smile.gif)
fresh.c // I thought about this name for a "Free RichEdit Editor Syntax Highlighted" acronym
![Smile :-)](./images/smilies/icon_smile.gif)
Code: Select all | Expand
#pragma resource "fresh.res"
#include <windows.h>
#include <richedit.h>
#include <stdio.h>
typedef struct
{
DWORD WordLen; // the length of the word: used as a quick comparison
char * pszWord; // pointer to the word
COLORREF * pColor; // point to the dword that contains the color used to hilite the word
void * NextLink; // point to the next WORDINFO structure
} WORDINFO;
#define IDR_MAINMENU 101
#define IDM_OPEN 40001
#define IDM_SAVE 40002
#define IDM_CLOSE 40003
#define IDM_SAVEAS 40004
#define IDM_EXIT 40005
#define IDM_COPY 40006
#define IDM_CUT 40007
#define IDM_PASTE 40008
#define IDM_DELETE 40009
#define IDM_SELECTALL 40010
#define IDM_OPTION 40011
#define IDM_UNDO 40012
#define IDM_REDO 40013
#define IDD_OPTIONDLG 101
#define IDC_BACKCOLORBOX 1000
#define IDC_TEXTCOLORBOX 1001
#define IDR_MAINACCEL 105
#define IDD_FINDDLG 102
#define IDD_GOTODLG 103
#define IDD_REPLACEDLG 104
#define IDC_FINDEDIT 1000
#define IDC_MATCHCASE 1001
#define IDC_REPLACEEDIT 1001
#define IDC_WHOLEWORD 1002
#define IDC_DOWN 1003
#define IDC_UP 1004
#define IDC_LINENO 1005
#define IDM_FIND 40014
#define IDM_FINDNEXT 40015
#define IDM_REPLACE 40016
#define IDM_GOTOLINE 40017
#define IDM_FINDPREV 40018
#define RichEditID 300
#define CLR_HRED RGB( 255, 0, 0 )
#define CLR_HGREEN RGB( 0, 255, 0 )
#define CLR_HBLUE RGB( 0, 0, 255 )
#define CLR_BLACK RGB( 0, 0, 0 )
#define CLR_WHITE RGB( 255, 255, 255 )
char FindBuffer[ 256 ];
char ReplaceBuffer[ 256 ];
HWND hWndRichEdit;
WNDPROC OldWndProc;
int RichEditVersion;
COLORREF BackGroundColor = CLR_WHITE;
COLORREF TextColor = CLR_BLACK;
COLORREF CommentColor = CLR_HBLUE;
COLORREF ColorArray[ 10 ] = { CLR_HRED, CLR_HGREEN, CLR_HBLUE, CLR_WHITE, CLR_BLACK,
CLR_BLACK, CLR_BLACK, CLR_BLACK, CLR_BLACK, CLR_BLACK };
BOOL FileOpened = FALSE;
char * szFileFilter = "PRG source code (*.prg)\0*.prg\0All Files (*.*)\0*.*\0";
char FileName[ 256 ];
char AlternateFileName[ 256 ];
HANDLE hSearch = NULL;
char * OpenFileFail = "Cannot open the file";
char * AppName = "Fresh 1.0";
char * WordFileName = "wordfile.txt";
FINDTEXTEX findtext;
char * WannaSave = "The data in the control is modified. Want to save it ?";
HFONT hFont;
WORDINFO SyntaxArray[ 256 ];
void SetColor( void )
{
CHARFORMAT cfm;
SendMessage( hWndRichEdit, EM_SETBKGNDCOLOR, 0, BackGroundColor );
memset( &cfm, 0, sizeof( cfm ) );
cfm.cbSize = sizeof( cfm );
cfm.dwMask = CFM_COLOR;
cfm.crTextColor = TextColor;
SendMessage( hWndRichEdit, EM_SETCHARFORMAT, SCF_ALL, ( LPARAM ) &cfm );
}
void CenterWindow( HWND hWnd )
{
RECT rWnd, rDsk;
LONG Left, Top, Width, Height;
GetWindowRect( hWnd, &rWnd );
GetWindowRect( GetDesktopWindow(), &rDsk );
Width = rWnd.right - rWnd.left;
Height = rWnd.bottom - rWnd.top;
Left = ( rDsk.right / 2 ) - ( Width / 2 );
Top = ( rDsk.bottom / 2 ) - ( Height / 2 );
MoveWindow( hWnd, Left, Top, Width, Height, FALSE );
}
void ParseBuffer( char * pszTokens, DWORD dwGroup )
{
char buffer[ 128 ];
char * pStart = pszTokens;
// BOOL InProgress = FALSE;
BOOL bFound = FALSE;
WORDINFO * pWordInfo;
if( ! strlen( pszTokens ) )
return;
CharLower( pszTokens );
while( * pszTokens )
{
if( ( ( * pszTokens ) == ' ' ) || ( ( * pszTokens ) == 9 ) ) // tab
bFound = TRUE;
if( * pszTokens && bFound )
{
pWordInfo = SyntaxArray + pStart[ 0 ];
if( SyntaxArray[ pStart[ 0 ] ].WordLen )
{
while( pWordInfo->NextLink )
pWordInfo = pWordInfo->NextLink;
pWordInfo->NextLink = ( WORDINFO * ) malloc( sizeof( WORDINFO ) );
memset( ( void * ) pWordInfo->NextLink, 0, sizeof( WORDINFO ) );
}
pWordInfo->WordLen = pszTokens - pStart;
pWordInfo->pszWord = ( char * ) malloc( pWordInfo->WordLen + 1 );
strncpy( pWordInfo->pszWord, pStart, pWordInfo->WordLen );
pWordInfo->pszWord[ pWordInfo->WordLen ] = 0;
pWordInfo->pColor = ColorArray + dwGroup - 1;
pWordInfo->NextLink = NULL;
bFound = FALSE;
// MessageBox( 0, pWordInfo->pszWord, "token", 0 );
while( ( ( ( * pszTokens ) == ' ' ) || ( ( * pszTokens ) == 9 ) ) && ( * pszTokens ) )
pszTokens++;
pStart = pszTokens;
}
if( * pszTokens )
pszTokens++;
}
}
void FillHiliteInfo( void )
{
char filename[ 1024 ];
char buffer[ 1024 ];
char * pTemp;
RtlZeroMemory( SyntaxArray, sizeof( SyntaxArray ) );
GetModuleFileName( GetModuleHandle( NULL ), filename, sizeof( filename ) );
pTemp = filename + lstrlen( filename );
while( ( pTemp > filename ) && ( ( * pTemp ) != '\\' ) )
pTemp--;
* ++pTemp = 0;
lstrcat( pTemp, WordFileName );
if( GetFileAttributes( filename ) != INVALID_FILE_ATTRIBUTES )
{
if( GetPrivateProfileString( "ASSEMBLY", "C1", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 1 );
if( GetPrivateProfileString( "ASSEMBLY", "C2", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 2 );
if( GetPrivateProfileString( "ASSEMBLY", "C3", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 3 );
if( GetPrivateProfileString( "ASSEMBLY", "C4", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 4 );
if( GetPrivateProfileString( "ASSEMBLY", "C5", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 5 );
if( GetPrivateProfileString( "ASSEMBLY", "C6", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 6 );
if( GetPrivateProfileString( "ASSEMBLY", "C7", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 7 );
if( GetPrivateProfileString( "ASSEMBLY", "C8", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 8 );
if( GetPrivateProfileString( "ASSEMBLY", "C9", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 9 );
if( GetPrivateProfileString( "ASSEMBLY", "C10", NULL, buffer, sizeof( buffer ), filename ) )
ParseBuffer( buffer, 10 );
}
else
MessageBox( 0, "wordfile.txt does not exist", "Attention", MB_ICONINFORMATION );
}
BOOL CheckModifyState( HWND hWnd )
{
int nResult;
if( SendMessage( hWndRichEdit, EM_GETMODIFY, 0, 0 ) )
if( ( nResult = MessageBox( hWnd, WannaSave, AppName, MB_YESNOCANCEL ) ) == IDYES )
SendMessage( hWnd, WM_COMMAND, IDM_SAVE, 0 );
else if( nResult == IDCANCEL )
return FALSE;
return TRUE;
}
void PrepareEditMenu( HMENU hSubMenu )
{
CHARRANGE chrg;
if( ! SendMessage( hWndRichEdit, EM_CANPASTE, CF_TEXT, 0 ) )
EnableMenuItem( hSubMenu, IDM_PASTE, MF_GRAYED );
else
EnableMenuItem( hSubMenu, IDM_PASTE, MF_ENABLED );
if( ! SendMessage( hWndRichEdit, EM_CANUNDO, 0, 0 ) )
EnableMenuItem( hSubMenu, IDM_UNDO, MF_GRAYED );
else
EnableMenuItem( hSubMenu, IDM_UNDO, MF_ENABLED );
if( ! SendMessage( hWndRichEdit, EM_CANREDO, 0, 0 ) )
EnableMenuItem( hSubMenu, IDM_REDO, MF_GRAYED );
else
EnableMenuItem( hSubMenu, IDM_REDO, MF_ENABLED );
chrg.cpMin = SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &chrg );
if( chrg.cpMin == chrg.cpMax )
{
EnableMenuItem( hSubMenu, IDM_COPY, MF_GRAYED );
EnableMenuItem( hSubMenu, IDM_CUT, MF_GRAYED );
EnableMenuItem( hSubMenu, IDM_DELETE, MF_GRAYED );
}
else
{
EnableMenuItem( hSubMenu, IDM_COPY, MF_ENABLED );
EnableMenuItem( hSubMenu, IDM_CUT, MF_ENABLED );
EnableMenuItem( hSubMenu, IDM_DELETE, MF_ENABLED );
}
}
#pragma argsused
static INT_PTR CALLBACK OptionProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
switch( wMsg )
{
case WM_INITDIALOG:
CenterWindow( hDlg );
return TRUE;
case WM_COMMAND:
switch( wParam )
{
case IDOK:
EndDialog( hDlg, IDOK );
break;
case IDCANCEL:
EndDialog( hDlg, IDCANCEL );
break;
}
break;
}
return FALSE;
}
#pragma argsused
static INT_PTR CALLBACK SearchProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
switch( wMsg )
{
case WM_INITDIALOG:
CenterWindow( hDlg );
return TRUE;
case WM_COMMAND:
switch( wParam )
{
case IDOK:
EndDialog( hDlg, IDOK );
break;
case IDCANCEL:
EndDialog( hDlg, IDCANCEL );
break;
}
break;
}
return FALSE;
}
#pragma argsused
static INT_PTR CALLBACK ReplaceProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
switch( wMsg )
{
case WM_INITDIALOG:
CenterWindow( hDlg );
return TRUE;
case WM_COMMAND:
switch( wParam )
{
case IDOK:
EndDialog( hDlg, IDOK );
break;
case IDCANCEL:
EndDialog( hDlg, IDCANCEL );
break;
}
break;
}
return FALSE;
}
#pragma argsused
static INT_PTR CALLBACK GoToProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
switch( wMsg )
{
case WM_INITDIALOG:
CenterWindow( hDlg );
return TRUE;
case WM_COMMAND:
switch( wParam )
{
case IDOK:
EndDialog( hDlg, IDOK );
break;
case IDCANCEL:
EndDialog( hDlg, IDCANCEL );
break;
}
break;
}
return FALSE;
}
LRESULT WINAPI NewRichEditProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
HDC hDC;
HFONT hOldFont;
RECT rect;
TEXTRANGE txtrange;
char buffer[ 1024 * 10 ];
HRGN hRgn, hOldRgn;
POINT pt;
DWORD nChar, nLine, dwPos;
WORDINFO * pWordInfo;
BOOL bExit;
switch( msg )
{
case WM_PAINT:
HideCaret( hWnd );
CallWindowProc( OldWndProc, hWnd, msg, wParam, lParam );
hDC = GetDC( hWnd );
SetBkMode( hDC, TRANSPARENT );
hOldFont = SelectObject( hDC, hFont );
SendMessage( hWnd, EM_GETRECT, 0, ( LPARAM ) &rect );
nChar = SendMessage( hWnd, EM_CHARFROMPOS, 0, ( LPARAM ) &rect );
nLine = SendMessage( hWnd, EM_LINEFROMCHAR, nChar, 0 );
txtrange.chrg.cpMin = SendMessage( hWnd, EM_LINEINDEX, nLine, 0 );
txtrange.chrg.cpMax = SendMessage( hWnd, EM_CHARFROMPOS, 0, ( LPARAM ) &rect.right );
hRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom );
hOldRgn = SelectObject( hDC, hRgn );
txtrange.lpstrText = buffer;
if( SendMessage( hWnd, EM_GETTEXTRANGE, 0, ( LPARAM ) &txtrange ) )
{
char * pPos = buffer;
char * pStart = buffer;
char * pToken;
while( * pPos )
{
if( * pPos == ' ' || * pPos == 9 || * pPos == 0xD || * pPos == 0xA )
{
pToken = ( char * ) malloc( pPos - pStart + 1 );
strncpy( pToken, pStart, pPos - pStart );
pToken[ pPos - pStart ] = 0;
MessageBox( 0, pToken, "token", 0 );
if( RichEditVersion == 3 )
SendMessage( hWnd, EM_POSFROMCHAR, ( WPARAM ) &rect, ( LPARAM ) ( pStart - buffer ) + nChar );
else
{
dwPos = SendMessage( hWnd, EM_POSFROMCHAR, ( WPARAM ) pStart, 0 );
rect.left = LOWORD( dwPos );
rect.top = HIWORD( dwPos );
}
if( pToken[ 0 ] >= 'A' && pToken[ 0 ] <= 'Z' )
pWordInfo = SyntaxArray + pToken[ 0 ] - 'A' + 'a';
else
pWordInfo = SyntaxArray + pToken[ 0 ];
bExit = FALSE;
while( pWordInfo->WordLen && ! bExit )
{
if( strlen( pToken ) == pWordInfo->WordLen &&
lstrcmpi( pWordInfo->pszWord, pToken ) == 0 )
{
bExit = TRUE;
SetTextColor( hDC, * pWordInfo->pColor );
DrawText( hDC, pToken, -1, &rect, 0 );
}
else
{
if( pWordInfo->NextLink )
pWordInfo= pWordInfo->NextLink;
else
bExit = TRUE;
}
}
free( pToken );
while( * pPos == ' ' || * pPos == 9 || * pPos == 0xD || * pPos == 0xA && * pPos )
pPos++;
if( ! * pPos )
pPos++;
pStart = pPos;
}
pPos++;
}
}
SelectObject( hDC, hOldRgn );
DeleteObject( hRgn );
SelectObject( hDC, hOldFont );
ReleaseDC( hWnd, hDC );
ShowCaret( hWnd );
return 0;
case WM_CLOSE:
SetWindowLong( hWnd, GWL_WNDPROC, ( LONG ) OldWndProc );
break;
}
return CallWindowProc( OldWndProc, hWnd, msg, wParam, lParam );
}
DWORD CALLBACK StreamInProc( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR * pcb )
{
ReadFile( ( HANDLE ) dwCookie, ( LPVOID ) pbBuff, ( DWORD ) cb, ( LPDWORD ) pcb, 0 );
return 0;
}
DWORD CALLBACK StreamOutProc( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR * pcb )
{
WriteFile( ( HANDLE ) dwCookie, ( LPVOID ) pbBuff, ( DWORD ) cb, ( LPDWORD ) pcb, 0 );
return 0;
}
LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
RECT rect;
OPENFILENAME ofn;
char buffer[ 256 ];
EDITSTREAM editstream;
FILE * hFile;
HMENU hPopup;
POINT pt;
CHARRANGE chrg;
switch( msg )
{
case WM_CREATE:
GetClientRect( hWnd, &rect );
hWndRichEdit = CreateWindowEx( WS_EX_CLIENTEDGE, "RichEdit20A", 0,
WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL |
WS_HSCROLL | ES_NOHIDESEL, 0, 0,
rect.right - rect.left, rect.bottom - rect.top,
hWnd, ( HMENU ) RichEditID, GetModuleHandle( NULL ), 0 );
SendMessage( hWndRichEdit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLELINEBREAK, TO_SIMPLELINEBREAK );
if( ! SendMessage( hWndRichEdit, EM_GETTYPOGRAPHYOPTIONS, 1, 1 ) )
RichEditVersion = 2;
else
RichEditVersion = 3;
SendMessage( hWndRichEdit, EM_SETEDITSTYLE, SES_EMULATESYSEDIT, SES_EMULATESYSEDIT );
OldWndProc = ( WNDPROC ) SetWindowLong( hWndRichEdit, GWL_WNDPROC, ( LONG ) NewRichEditProc );
SendMessage( hWndRichEdit, EM_LIMITTEXT, -1, 0 );
// SetColor();
SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
SendMessage( hWndRichEdit, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS );
SendMessage( hWndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0 );
hFont = CreateFont( 18, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Courier New" );
SendMessage( hWndRichEdit, WM_SETFONT, ( WPARAM ) hFont, 0 );
FillHiliteInfo();
SetFocus( hWndRichEdit );
break;
case WM_NOTIFY:
if( ( ( NMHDR * ) lParam )->code == EN_MSGFILTER )
{
if( ( ( MSGFILTER * ) lParam )->msg == WM_RBUTTONDOWN )
{
hPopup = GetSubMenu( GetMenu( hWnd ), 1 );
PrepareEditMenu( hPopup );
pt.x = LOWORD( lParam );
pt.y = HIWORD( lParam );
ClientToScreen( hWnd, &pt );
TrackPopupMenu( hPopup, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pt.x, pt.y,
NULL, hWnd, NULL );
}
}
break;
case WM_INITMENUPOPUP:
if( lParam == 0 )
{
if( FileOpened )
{
EnableMenuItem( ( HMENU ) wParam, IDM_OPEN, MF_GRAYED );
EnableMenuItem( ( HMENU ) wParam, IDM_CLOSE, MF_ENABLED );
EnableMenuItem( ( HMENU ) wParam, IDM_SAVE, MF_ENABLED );
EnableMenuItem( ( HMENU ) wParam, IDM_SAVEAS, MF_ENABLED );
}
else
{
EnableMenuItem( ( HMENU ) wParam, IDM_OPEN, MF_ENABLED );
EnableMenuItem( ( HMENU ) wParam, IDM_CLOSE, MF_GRAYED );
EnableMenuItem( ( HMENU ) wParam, IDM_SAVE, MF_GRAYED );
EnableMenuItem( ( HMENU ) wParam, IDM_SAVEAS, MF_GRAYED );
}
}
else if( lParam == 1 )
PrepareEditMenu( ( HMENU ) wParam );
else if( lParam == 2 )
{
if( FileOpened )
{
EnableMenuItem( ( HMENU ) wParam, IDM_FIND, MF_ENABLED );
EnableMenuItem( ( HMENU ) wParam, IDM_FINDNEXT, MF_ENABLED );
EnableMenuItem( ( HMENU ) wParam, IDM_FINDPREV, MF_ENABLED );
EnableMenuItem( ( HMENU ) wParam, IDM_REPLACE, MF_ENABLED );
EnableMenuItem( ( HMENU ) wParam, IDM_GOTOLINE, MF_ENABLED );
}
else
{
EnableMenuItem( ( HMENU ) wParam, IDM_FIND, MF_GRAYED );
EnableMenuItem( ( HMENU ) wParam, IDM_FINDNEXT, MF_GRAYED );
EnableMenuItem( ( HMENU ) wParam, IDM_FINDPREV, MF_GRAYED );
EnableMenuItem( ( HMENU ) wParam, IDM_REPLACE, MF_GRAYED );
EnableMenuItem( ( HMENU ) wParam, IDM_GOTOLINE, MF_GRAYED );
}
}
break;
case WM_COMMAND:
if( ! lParam ) // menu commands
{
switch( LOWORD( wParam ) )
{
case IDM_OPEN:
{
memset( &ofn, 0, sizeof( ofn ) );
ofn.lStructSize = sizeof( ofn );
ofn.hwndOwner = hWnd;
ofn.hInstance = GetModuleHandle( NULL );
ofn.lpstrFilter = szFileFilter;
FileName[ 0 ] = 0;
ofn.lpstrFile = FileName;
ofn.nMaxFile = sizeof( FileName );
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
if( GetOpenFileName( &ofn ) )
{
if( ( hFile = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ) !=
INVALID_HANDLE_VALUE )
{
editstream.dwCookie = ( DWORD_PTR ) hFile;
editstream.pfnCallback = StreamInProc;
SendMessage( hWndRichEdit, EM_STREAMIN, SF_TEXT, ( LPARAM ) &editstream );
SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
CloseHandle( hFile );
FileOpened = TRUE;
}
else
MessageBox( hWnd, OpenFileFail, AppName, MB_OK | MB_ICONERROR );
}
}
break;
case IDM_CLOSE:
{
if( CheckModifyState( hWnd ) )
SetWindowText( hWndRichEdit, NULL );
FileOpened = FALSE;
}
break;
case IDM_SAVE:
{
if( ( hFile = CreateFile( FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ) ) !=
INVALID_HANDLE_VALUE )
{
editstream.dwCookie = ( DWORD_PTR ) hFile;
editstream.pfnCallback = StreamOutProc;
SendMessage( hWndRichEdit, EM_STREAMOUT, SF_TEXT, ( LPARAM ) &editstream );
SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
CloseHandle( hFile );
}
else
MessageBox( hWnd, OpenFileFail, AppName, MB_OK | MB_ICONERROR );
}
break;
case IDM_COPY:
SendMessage( hWndRichEdit, WM_COPY, 0, 0 );
break;
case IDM_CUT:
SendMessage( hWndRichEdit, WM_CUT, 0, 0 );
break;
case IDM_PASTE:
SendMessage( hWndRichEdit, WM_PASTE, 0, 0 );
break;
case IDM_DELETE:
SendMessage( hWndRichEdit, EM_REPLACESEL, TRUE, 0 );
break;
case IDM_SELECTALL:
{
chrg.cpMin = 0;
chrg.cpMax = -1;
SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &chrg );
}
break;
case IDM_UNDO:
SendMessage( hWndRichEdit, EM_UNDO, 0, 0 );
break;
case IDM_REDO:
SendMessage( hWndRichEdit, EM_REDO, 0, 0 );
break;
case IDM_OPTION:
DialogBoxParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_OPTIONDLG, hWnd, OptionProc, 0 );
break;
case IDM_SAVEAS:
{
RtlZeroMemory( &ofn, sizeof( ofn ) );
ofn.lStructSize = sizeof( ofn );
ofn.hwndOwner = hWnd;
ofn.hInstance = GetModuleHandle( NULL );
ofn.lpstrFilter = szFileFilter;
AlternateFileName[ 0 ] = 0;
ofn.lpstrFile = AlternateFileName;
ofn.nMaxFile = sizeof( AlternateFileName );
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
if( GetSaveFileName( &ofn ) )
{
if( CreateFile( AlternateFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ) !=
INVALID_HANDLE_VALUE )
{
}
}
}
break;
case IDM_FIND:
if( ! hSearch )
CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_FINDDLG, hWnd, SearchProc, 0 );
break;
case IDM_REPLACE:
if( ! hSearch )
CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_REPLACEDLG, hWnd, ReplaceProc, 0 );
break;
case IDM_GOTOLINE:
if( ! hSearch )
CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_GOTODLG, hWnd, GoToProc, 0 );
break;
case IDM_FINDNEXT:
if( lstrlen( FindBuffer ) )
{
SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &findtext.chrg );
if( findtext.chrg.cpMin != findtext.chrg.cpMax )
findtext.chrg.cpMin = findtext.chrg.cpMax;
findtext.chrg.cpMax = -1;
findtext.lpstrText = FindBuffer;
if( SendMessage( hWndRichEdit, EM_FINDTEXTEX, FR_DOWN, ( LPARAM ) &findtext ) != -1 )
SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &findtext.chrgText );
}
break;
case IDM_FINDPREV:
if( lstrlen( FindBuffer ) )
{
SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &findtext.chrg );
findtext.chrg.cpMax = 0;
findtext.lpstrText = FindBuffer;
if( SendMessage( hWndRichEdit, EM_FINDTEXTEX, 0, ( LPARAM ) &findtext ) != -1 )
SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &findtext.chrgText );
}
break;
case IDM_EXIT:
SendMessage( hWnd, WM_CLOSE, 0, 0 );
break;
}
}
break;
case WM_CLOSE:
if( CheckModifyState( hWnd ) )
{
DeleteObject( hFont );
DestroyWindow( hWnd );
}
break;
case WM_SIZE:
MoveWindow( hWndRichEdit, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
#pragma argsused
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show )
{
WNDCLASSEX wc;
MSG msg;
HWND hWnd;
char * szClassName = "FreshClass";
HACCEL hAccel;
HINSTANCE hDll = LoadLibrary( "riched32" );
wc.cbSize = sizeof( WNDCLASSEX );
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hbrBackground = GetStockObject( WHITE_BRUSH );
wc.lpszMenuName = ( LPCTSTR ) IDR_MAINMENU;
wc.lpszClassName = szClassName;
wc.hIcon = wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
RegisterClassEx( &wc );
hWnd = CreateWindowEx( NULL, szClassName, "Fresh 1.0",
WS_OVERLAPPEDWINDOW, 70, 70,
1130, 630, 0, NULL, hInstance, NULL );
ShowWindow( hWnd, SW_SHOWNORMAL );
UpdateWindow( hWnd );
hAccel = LoadAccelerators( hInstance, ( LPCTSTR ) IDR_MAINACCEL );
while( GetMessage( &msg, 0, 0, 0 ) )
{
if( IsDialogMessage( hSearch, &msg ) )
TranslateAccelerator( hWnd, hAccel, &msg );
else
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
FreeLibrary( hDll );
return 0;
}
fresh.rc
Code: Select all | Expand
// #include "resource.h"
#define IDC_NEXT 1003
#define IDR_MAINMENU 101
#define IDD_OPTIONDLG 101
#define IDD_FINDDLG 102
#define IDD_GOTODLG 103
#define IDD_REPLACEDLG 104
#define IDR_MAINACCEL 105
#define IDC_BACKCOLORBOX 1000
#define IDC_FINDEDIT 1000
#define IDC_TEXTCOLORBOX 1001
#define IDC_MATCHCASE 1001
#define IDC_REPLACEEDIT 1001
#define IDC_WHOLEWORD 1002
#define IDC_DOWN 1003
#define IDC_UP 1004
#define IDC_LINENO 1005
#define IDM_OPEN 40001
#define IDM_SAVE 40002
#define IDM_CLOSE 40003
#define IDM_SAVEAS 40004
#define IDM_EXIT 40005
#define IDM_COPY 40006
#define IDM_CUT 40007
#define IDM_PASTE 40008
#define IDM_DELETE 40009
#define IDM_SELECTALL 40010
#define IDM_OPTION 40011
#define IDM_UNDO 40012
#define IDM_REDO 40013
#define IDM_FIND 40014
#define IDM_FINDNEXT 40015
#define IDM_REPLACE 40016
#define IDM_GOTOLINE 40017
#define IDM_FINDPREV 40018
IDR_MAINMENU MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open", IDM_OPEN
MENUITEM "&Close", IDM_CLOSE
MENUITEM "&Save", IDM_SAVE
MENUITEM "Save &As", IDM_SAVEAS
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "&Undo", IDM_UNDO
MENUITEM "&Redo", IDM_REDO
MENUITEM "&Copy", IDM_COPY
MENUITEM "C&ut", IDM_CUT
MENUITEM "&Paste", IDM_PASTE
MENUITEM SEPARATOR
MENUITEM "&Delete", IDM_DELETE
MENUITEM SEPARATOR
MENUITEM "Select &All", IDM_SELECTALL
END
POPUP "&Search"
BEGIN
MENUITEM "&Find...\tCtrl+F", IDM_FIND
MENUITEM "Find &Next\tF3", IDM_FINDNEXT
MENUITEM "Find &Prev.\tCtrl+F3", IDM_FINDPREV
MENUITEM "&Replace..\tCtrl+R", IDM_REPLACE
MENUITEM SEPARATOR
MENUITEM "&Go To Line\tCtrl+G", IDM_GOTOLINE
END
MENUITEM "Options", IDM_OPTION
END
IDD_OPTIONDLG DIALOG DISCARDABLE 0, 0, 183, 54
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU
CAPTION "Options"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,137,7,39,14
PUSHBUTTON "Cancel",IDCANCEL,137,25,39,14
GROUPBOX "",IDC_STATIC,5,0,124,49
LTEXT "Background Color:",IDC_STATIC,20,14,60,8
LTEXT "",IDC_BACKCOLORBOX,85,11,28,14,SS_NOTIFY | WS_BORDER
LTEXT "Text Color:",IDC_STATIC,20,33,35,8
LTEXT "",IDC_TEXTCOLORBOX,85,29,28,14,SS_NOTIFY | WS_BORDER
END
IDD_FINDDLG DIALOG DISCARDABLE 0, 0, 186, 54
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Find.."
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_FINDEDIT,42,3,94,12,ES_AUTOHSCROLL
CONTROL "Match Case",IDC_MATCHCASE,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,6,24,54,10
CONTROL "Whole Word",IDC_WHOLEWORD,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,6,37,56,10
CONTROL "Down",IDC_DOWN,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
83,27,35,10
CONTROL "Up",IDC_UP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,83,
38,25,10
DEFPUSHBUTTON "OK",IDOK,141,3,39,12
PUSHBUTTON "Cancel",IDCANCEL,141,18,39,12
LTEXT "Find what:",IDC_STATIC,5,4,34,8
GROUPBOX "Direction",IDC_STATIC,70,18,64,32
END
IDD_GOTODLG DIALOGEX 0, 0, 106, 30
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Go To Line"
FONT 8, "MS Sans Serif", 0, 0
BEGIN
EDITTEXT IDC_LINENO,29,4,35,11,ES_AUTOHSCROLL | ES_NUMBER,
WS_EX_CLIENTEDGE
DEFPUSHBUTTON "OK",IDOK,70,4,31,11
PUSHBUTTON "Cancel",IDCANCEL,70,17,31,11
LTEXT "Line :",IDC_STATIC,8,5,18,8
END
IDD_REPLACEDLG DIALOG DISCARDABLE 0, 0, 186, 33
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Replace"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_FINDEDIT,51,3,84,12,ES_AUTOHSCROLL
EDITTEXT IDC_REPLACEEDIT,51,17,84,11,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,142,3,39,11
PUSHBUTTON "Cancel",IDCANCEL,142,17,39,11
LTEXT "Find what:",IDC_STATIC,3,4,34,8
LTEXT "Replace with",IDC_STATIC,3,18,42,8
END
IDR_MAINACCEL ACCELERATORS DISCARDABLE
BEGIN
"F", IDM_FIND, VIRTKEY, CONTROL, NOINVERT
"G", IDM_GOTOLINE, VIRTKEY, CONTROL, NOINVERT
"R", IDM_REPLACE, VIRTKEY, CONTROL, NOINVERT
VK_F3, IDM_FINDNEXT, VIRTKEY, NOINVERT
VK_F3, IDM_FINDPREV, VIRTKEY, CONTROL, NOINVERT
END
go.bat:
Code: Select all | Expand
set path=c:\bcc582\bin
brc32 -r fresh.rc
bcc32 -W fresh.c
if errorlevel 0 fresh
It uses a wordfile.txt to specify the tokens to highlight:
Code: Select all | Expand
[ASSEMBLY]
C1=CLASS ENDCLASS DATA METHOD INLINE
C2=#include #pragma #ifdef #endif #define another
C3=local static public private
C4=if else endif return do case end endcase
C5=
C6=
C7=
C8=
C9=
C10=
It already works though it is not complete and still has some bugs while parsing. But the concept is there and it is quite interesting
![Smile :-)](./images/smilies/icon_smile.gif)
Original source code and idea belongs to Iczelion@win32asm.cjb.net.