//***************************************************// // RichEd in HLA // // Programmed by Sevag Krikorian (Kain) // // Adapted from various codes available in MASM // // In particular, RichEd template included with // // RADasm. Thanks Keitl for making that available // // // // Note: This program uses the shlwapi.lib and // // shell32.lib and advapi32.lib from masm32 // // // // The headers and imports from masm32 libs were // // created by Odyssey's utility: msm2hla // // // // Program released as open-source freeware // // // //***************************************************// program RichEd; #include( "RichEd.hhf" ) const version :text := """Version: 0.2.6"" #$d #$a"; procedure QuitApplication( hwnd:dword; wParam:dword; lParam:dword ); @nostackalign; begin QuitApplication; w.PostQuitMessage( 0 ); end QuitApplication; procedure SetFormat; static chr :w.CHARRANGE; chr2 :w.CHARRANGE; cf :w.CHARFORMAT; begin SetFormat; w.SendMessage(hwnd, w.EM_GETMODIFY,0,0); push (eax); w.SendMessage(hwnd, w.EM_EXGETSEL,0, &chr); w.SendMessage(hwnd, w.EM_HIDESELECTION, true,0); mov (0, chr2.cpMin); mov (-1,chr2.cpMax); w.SendMessage(hwnd, w.EM_EXSETSEL,0,&chr2); mov (@size(cf), cf.cbSize); mov (w.CFM_CHARSET | w.CFM_FACE | w.CFM_SIZE | w.CFM_COLOR, cf.dwMask); mov (logfont.lfCharSet, al); mov (al,cf.bCharSet); mov (logfont.lfPitchAndFamily, al); mov (al, cf.bPitchAndFamily); w.lstrcpyn(cf.szFaceName,&logfont.lfFaceName,w.LF_FACESIZE); mov (logfont.lfHeight, eax); neg (eax); mov (15,ecx); mul (ecx); mov (eax, cf.yHeight); mov (rgb, cf.crTextColor); w.SendMessage(hwnd, w.EM_SETCHARFORMAT, w.SCF_SELECTION,&cf); w.SendMessage(hREd, w.WM_SETFONT, hFont, true); w.SendMessage(hREd, w.EM_SETMARGINS, w.EC_LEFTMARGIN,5); pop (eax); w.SendMessage(hwnd, w.EM_SETMODIFY, eax,0); w.SendMessage(hwnd, w.EM_EXSETSEL,0,&chr); w.SendMessage(hwnd,w.EM_HIDESELECTION, false, 0); end SetFormat; procedure SetupWindowTitle; @nostackalign; begin SetupWindowTitle; // reset the title string str.delete(windowtitle, 0, w.MAX_PATH); // write the appname and filename to the string str.catz(&AppName,windowtitle); str.cat(" - [",windowtitle); str.catz(&FileName,windowtitle); str.cat("]",windowtitle); w.SetWindowText(hwnd,windowtitle); end SetupWindowTitle; // streams data into richedit control procedure StreamInProc (var pBytesRead:dword ; NumBytes:dword ; var pBuffer:dword ; hFile:dword); @nostackalign; begin StreamInProc; w.ReadFile(hFile,pBuffer,NumBytes,pBytesRead,NULL); xor (1, eax); end StreamInProc; // streams data out of richedit control procedure StreamOutProc (var pBytesRead:dword ; NumBytes:dword ; var pBuffer:dword ; hFile:dword); @nostackalign; begin StreamOutProc; w.WriteFile(hFile,pBuffer,NumBytes,pBytesRead,NULL); xor (1, eax); end StreamOutProc; procedure SaveFile; static hFile :dword; // file handle editstream :w.EDITSTREAM; begin SaveFile; w.CreateFile(&FileName,w.GENERIC_WRITE, w.FILE_SHARE_READ,NULL,w.CREATE_ALWAYS,w.FILE_ATTRIBUTE_NORMAL,0); if (eax <> w.INVALID_HANDLE_VALUE) then mov (eax,hFile); mov (eax,editstream.dwCookie); mov (&StreamOutProc, editstream.pfnCallback); w.SendMessage(hREd, w.EM_STREAMOUT, w.SF_TEXT, &editstream); w.CloseHandle(hFile); w.SendMessage(hREd, w.EM_SETMODIFY, false, 0); mov (false, eax); else w.MessageBox(hwnd, "File Save failed", "Save Error",w.MB_OK); mov (true, eax); endif; end SaveFile; procedure SaveAs; static ofn :w.OPENFILENAME; begin SaveAs; w.RtlZeroMemory(&ofn, @size(ofn)); mov (@size(ofn),ofn.lStructSize); mov (hwnd,ofn.hWndOwner); mov (hInstance,ofn.hInstance); mov (0,ofn.lpstrFilter); mov (&FileName,ofn.lpstrFile); fileio.gwd(CurrentDir); mov (CurrentDir,ofn.lpstrInitialDir); mov (@elements(FileName),ofn.nMaxFile); mov (w.OFN_EXPLORER | w.OFN_FILEMUSTEXIST | w.OFN_LONGNAMES | w.OFN_OVERWRITEPROMPT,ofn.Flags); mov (NULL, ofn.lpstrDefExt); w.GetSaveFileName(ofn); if(eax) then SaveFile(); if(eax) then // reset FileName to untitled str.zcpy(&NewFile,&FileName); endif; SetupWindowTitle(); endif; end SaveAs; procedure CheckSave; @nostackalign; begin CheckSave; str.zcmp(&FileName,&NewFile); if (eax=0) then // zstrings equal SaveAs(); else SaveFile(); endif; end CheckSave; // checks for modified file, gets confirmation from user procedure getConfirm; @nostackalign; begin getConfirm; w.SendMessage(hREd, w.EM_GETMODIFY,0,0); if (eax) then w.MessageBox(hwnd, &FileName,"Save Changes to", w.MB_YESNOCANCEL | w.MB_ICONQUESTION); if (eax=w.IDYES) then SaveFile(); elseif (eax=w.IDNO) then mov (false,eax); else mov (true,eax); endif; endif; end getConfirm; procedure CloseApplication ( hwnd:dword; wParam:dword; lParam:dword ); static rect :w.RECT; begin CloseApplication; getConfirm(); if (!eax) then w.GetWindowLong(hwnd, w.GWL_STYLE); test (w.WS_MAXIMIZE, eax); if (@z) then test (w.WS_MINIMIZE, eax); if(@z) then mov (false, wpos.fMax); w.GetWindowRect(hwnd, &rect); mov (rect.left, eax); mov (eax, wpos.x); mov (rect.top, eax); mov (eax, wpos.y); mov (rect.right, eax); sub (rect.left, eax); mov (eax, wpos.wt); mov (rect.bottom, eax); sub (rect.top, eax); mov (eax, wpos.ht); endif; else mov (true, wpos.fMax); endif; w.DestroyWindow(hwnd); endif; end CloseApplication; procedure LoadFile; static hFile :dword; editstream :w.EDITSTREAM; begin LoadFile; fileio.open(&FileName,fileio.r); if (eax <> 0) then // no error mov (eax, hFile); fileio.size(hFile); if (eax >0) then mov (hFile, editstream.dwCookie); mov (&StreamInProc, editstream.pfnCallback); w.SendMessage(hREd, w.EM_STREAMIN, w.SF_TEXT, &editstream); fileio.close(hFile); w.SendMessage(hREd, w.EM_SETMODIFY, false,0); endif; endif; end LoadFile; procedure FileOpen; static ofn :w.OPENFILENAME; // file structure begin FileOpen; w.RtlZeroMemory(&ofn, @size(ofn)); mov (0,FileName); mov (@size(ofn),ofn.lStructSize); mov (hwnd,ofn.hWndOwner); mov (hInstance,ofn.hInstance); mov (0,ofn.lpstrFilter); mov (@size(FileName), ofn.nMaxFile); mov (&FileName,ofn.lpstrFile); fileio.gwd(CurrentDir); mov (CurrentDir,ofn.lpstrInitialDir); mov (NULL, ofn.lpstrDefExt); mov (w.OFN_PATHMUSTEXIST | w.OFN_FILEMUSTEXIST | w.OFN_HIDEREADONLY | w.OFN_LONGNAMES,ofn.Flags); w.GetOpenFileName(ofn); if (eax) then LoadFile(); SetupWindowTitle(); endif; w.SetFocus(hREd); end FileOpen; // find text procedure Find; @nostackalign; begin Find; search: w.SendMessage(hREd, w.EM_FINDTEXTEX, frflags, &findtxt); if (eax <> -1) then jmp found; endif; w.MessageBox(hwnd, "Continue searching from top?", "Find/Replace", w.MB_YESNO | w.MB_ICONQUESTION | w.MB_TASKMODAL); if (eax = w.IDNO) then w.SetFocus(hFind); jmp endfind; endif; if (fres = 0) then w.SendMessage(hREd, w.EM_SETSEL, 0,0); mov (0, findtxt.chrg.cpMin); mov (-1, findtxt.chrg.cpMax); else w.SendMessage(hREd, w.WM_GETTEXTLENGTH,0,0); mov (eax, findtxt.chrg.cpMin); mov (0, findtxt.chrg.cpMax); endif; jmp search; found: if (eax = findtxt.chrg.cpMin && eax <> findtxt.chrg.cpMax && fres=0) then inc (findtxt.chrg.cpMin); jmp search; endif; w.SendMessage(hREd, w.EM_EXSETSEL,0, &findtxt.chrgText); w.SendMessage(hREd, w.EM_SCROLLCARET,0,0); w.SetFocus(hFind); mov (true, eax); exit Find; endfind: mov (false, eax); end Find; // procdeure to handle find dialog procedure FindDlgProc ( lParam:dword; wParam:dword; uMsg:uns32; hDlg:dword); static chrg :w.CHARRANGE; var hCtl :dword; begin FindDlgProc; if (uMsg = w.WM_INITDIALOG) then if (lParam) then // enable replace w.GetDlgItem(hDlg, IDC_BTN_REPLACEALL); w.EnableWindow(eax,true); w.GetDlgItem(hDlg, IDC_BTN_REPLACE); w.EnableWindow(eax,true); w.GetDlgItem(hDlg, IDC_REPLACETEXT); mov (eax,hCtl); w.GetWindowLong(hCtl,w.GWL_STYLE); xor (w.WS_VISIBLE, eax); w.SetWindowLong(hCtl,w.GWL_STYLE,eax); w.GetDlgItem(hDlg,IDC_REPLACESTATIC); mov (eax,hCtl); w.GetWindowLong(hCtl,w.GWL_STYLE); xor (w.WS_VISIBLE, eax); w.SetWindowLong(hCtl,w.GWL_STYLE, eax); w.SetWindowText(hDlg, "Replace"); w.GetDlgItem(hDlg, IDC_REPLACETEXT); w.SendMessage(eax, w.EM_LIMITTEXT, w.MAX_PATH,0); w.SetDlgItemText(hDlg, IDC_REPLACETEXT, &replacebuf); endif; mov (hDlg, eax); mov (eax, hFind); w.GetDlgItem(hDlg, IDC_FINDTEXT); mov (eax, hFindEdt); // get selected text w.SendMessage(hREd, w.EM_EXGETSEL, 0, &chrg); mov (chrg.cpMax, eax); sub (chrg.cpMin, eax); if (eax && eax <256) then w.SendMessage(hREd, w.EM_GETSELTEXT,0,&findbuf); endif; // w.SendMessage(hREd, w.EM_GETSELTEXT,0,&findbuf); w.SendMessage( hFindEdt, w.WM_SETTEXT, 0, &findbuf); w.SetFocus(hFindEdt); w.SendMessage(hFindEdt, w.EM_LIMITTEXT, w.MAX_PATH,0); if (findbuf = ' ') then mov (0, findbuf); endif; w.GetDlgItem(hDlg, IDC_RBN_DOWN); w.SendMessage(eax,w.BM_SETCHECK, w.BST_CHECKED,0); w.SendMessage(hREd, w.EM_EXGETSEL,0, &findtxt.chrgText); mov (false, eax); elseif (uMsg = w.WM_COMMAND) then if (wParam <> w.IDCANCEL) then and (0, frflags); w.SendMessage(hREd, w.EM_EXGETSEL,0,&findtxt.chrgText); w.GetDlgItemText(hDlg, IDC_FINDTEXT,&findbuf, w.MAX_PATH); push (findtxt.chrgText.cpMin); pop (findtxt.chrg.cpMin); mov (-1, findtxt.chrg.cpMax); lea (eax, findbuf); mov (eax, findtxt.lpstrText); if (wParam <> w.IDOK) then w.GetDlgItemText(hDlg, IDC_REPLACETEXT, &replacebuf, w.MAX_PATH); endif; w.IsDlgButtonChecked(hDlg, IDC_CHK_WHOLEWORD); if (eax) then or (w.FR_WHOLEWORD, frflags); endif; w.IsDlgButtonChecked(hDlg, IDC_CHK_MATCHCASE); if (eax) then or (w.FR_MATCHCASE, frflags); endif; w.IsDlgButtonChecked(hDlg, IDC_RBN_UP); if (eax) then mov (1, fres); mov (0, findtxt.chrg.cpMax); endif; w.IsDlgButtonChecked(hDlg, IDC_RBN_DOWN); if (eax) then mov (0, fres); or (w.FR_DOWN, frflags); endif; if (wParam = w.IDOK) then Find(); endif; replace: if (wParam = IDC_BTN_REPLACE || wParam = IDC_BTN_REPLACEALL) then if (replacebuf = ' ') then w.GetDlgItem(hDlg, IDC_REPLACETEXT); w.SendMessage(eax, w.EM_GETSELTEXT,0,&replacebuf); endif; w.SendMessage(hREd, w.EM_REPLACESEL, true,&replacebuf); mov (findtxt.chrgText.cpMin, eax); mov (eax, findtxt.chrgText.cpMax); str.zlen(&replacebuf); add (eax, findtxt.chrgText.cpMax); w.SendMessage(hREd, w.EM_EXSETSEL, 0, &findtxt.chrgText); if (fres) then sub (1, findtxt.chrg.cpMin); else add (1, findtxt.chrg.cpMin); endif; Find(); if (eax <> 1) then jmp exitfind; endif; if (wParam = IDC_BTN_REPLACEALL) then jmp replace; endif; endif; jmp exitfind; else w.EndDialog(hDlg, wParam); mov (true, eax); and (0, hFind); w.SetFocus(hREd); endif; endif; exitfind: mov (false, eax); end FindDlgProc; // handles opening dropped files procedure OpenDroppedFile ( hwnd:dword; wParam:dword; lParam:dword ); @nostackalign; begin OpenDroppedFile; getConfirm(); if (!eax) then w.SetWindowText(hREd,0); // clear edit window DragQueryFile(wParam,0,&FileName,@size(FileName)); LoadFile(); SetupWindowTitle(); endif; w.SetFocus(hREd); end OpenDroppedFile; // handles Font selection procedure SelectFont; static cf :w.CHOOSEFONT; begin SelectFont; w.RtlZeroMemory (&cf, @size(cf)); mov (@size(cf), cf.lStructSize); mov (hwnd, cf.hWndOwner); mov (&logfont, cf.lpLogFont); mov (w.CF_SCREENFONTS | w.CF_EFFECTS | w.CF_INITTOLOGFONTSTRUCT, cf.Flags); mov (rgb, cf.rgbColors); w._ChooseFont(cf); if (eax) then w.DeleteObject(hFont); w.CreateFontIndirect(logfont); mov (eax,hFont); mov (cf.rgbColors, rgb); SetFormat(); endif; end SelectFont; // handles Select All command procedure SelectAll; static chr :w.CHARRANGE; begin SelectAll; mov (0, chr.cpMin); mov (-1,chr.cpMax); w.SendMessage(hREd,w.EM_EXSETSEL,0,&chr); end SelectAll; // handles w.WM_COMMAND message procedure ProcessCommand ( hwnd:dword; wParam:dword; lParam:dword ); @nostackalign; begin ProcessCommand; mov (wParam,eax); and ($0ffff,eax); if (eax=IDM_NEW) then getConfirm(); if (!eax) then w.SetWindowText(hREd,0); // clear edit window str.zcpy(&NewFile,&FileName); SetupWindowTitle(); w.SetFocus(hREd); endif; w.SetFocus(hREd); elseif (eax = IDM_OPEN) then getConfirm(); if (!eax) then FileOpen(); endif; w.SetFocus(hREd); elseif (eax = IDM_SAVE) then CheckSave(); w.SetFocus(hREd); elseif (eax = IDM_SAVEAS) then SaveAs(); w.SetFocus(hREd); elseif (eax = IDM_SAVEQUIT) then CheckSave(); w.SendMessage(hwnd, w.WM_CLOSE,0,0); elseif (eax = IDM_CUT) then w.SendMessage(hREd, w.WM_CUT,0,0); elseif (eax = IDM_COPY) then w.SendMessage(hREd, w.WM_COPY,0,0); elseif (eax = IDM_PASTE) then w.SendMessage(hREd, w.WM_PASTE,0,0); elseif (eax = IDM_SELECTALL) then SelectAll(); elseif (eax = IDM_UNDO) then w.SendMessage(hREd, w.EM_UNDO,0,0); elseif (eax = IDM_REDO) then w.SendMessage(hREd, w.EM_REDO,0,0); elseif (eax = IDM_FIND) then if (!hFind) then w.CreateDialogParam(hInstance,val ID_FINDDLG,hwnd, &FindDlgProc,false); else w.SetFocus(hFind); endif; elseif (eax = IDM_FINDNEXT) then and (0, fres); mov (1, frflags); mov (-1, findtxt.chrg.cpMax); if (findbuf = ' ') then w.SendMessage(hREd, w.EM_GETSELTEXT,0,&findbuf); test (eax, eax); jz exitproc; endif; w.SendMessage(hREd, w.EM_EXGETSEL,0, &findtxt.chrgText); push (findtxt.chrgText.cpMin); pop (findtxt.chrg.cpMin); lea (eax, findbuf); mov (eax, findtxt.lpstrText); Find(); w.SetFocus(hREd); elseif (eax = IDM_REPLACE) then if (!hFind) then w.CreateDialogParam(hInstance,val ID_FINDDLG, hwnd, &FindDlgProc, true); else w.SetFocus(hFind); endif; elseif (eax = IDM_FONT) then SelectFont(); w.SetFocus(hREd); elseif (eax = IDM_ABOUT) then w.MessageBox(hwnd, version #$D#$A "By Sevag Krikorian" #$D#$A "Kahlinor@yahoo.com", "RichEdit HLA", w.MB_OK); elseif (eax=IDM_QUIT) then w.SendMessage(hwnd,w.WM_CLOSE,0,0); endif; exitproc: end ProcessCommand; // size window procedure SizeApplication ( hwnd:dword; wParam:dword; lParam:dword); var rect :w.RECT; height :dword; begin SizeApplication; w.GetClientRect(hwnd, rect); mov (rect.bottom,eax); sub (rect.top,eax); mov (eax, height); w.MoveWindow(hREd,0,rect.top,rect.right,height,true); end SizeApplication; // handles w.INITDIALOG message procedure SetupRichEdit ( hwnd:dword; wParam:dword; lParam:dword ); @nostackalign; begin SetupRichEdit; // set window position w.MoveWindow(hwnd, wpos.x,wpos.y,wpos.wt,wpos.ht,true); // setup Richedit control w.GetDlgItem(hwnd,IDC_RED); mov (eax,hREd); w.SendMessage(hREd, w.EM_SETTEXTMODE, 0, w.TM_PLAINTEXT); w.SendMessage(hREd, w.EM_SETEVENTMASK, 0, w.ENM_SELCHANGE); w.SendMessage(hREd, w.EM_LIMITTEXT,-1,0); w.SendMessage(hREd, w.EM_SETMODIFY, false,0); w.SendMessage(hREd, w.EM_EMPTYUNDOBUFFER,0,0); DragAcceptFiles(hwnd, true); str.zcpy(&szfont,logfont.lfFaceName); mov (-12,logfont.lfHeight); mov (400,logfont.lfWeight); w.CreateFontIndirect(&logfont); mov (eax,hFont); // w.SendMessage(hREd, w.WM_SETFONT, hFont, true); SetFormat(); // set up default window title w.SetWindowText(hREd,0); w.SetFocus(hREd); end SetupRichEdit; procedure WndProc( lParam:dword; wParam:dword; uMsg:uns32; hwnd:dword ); @nostackalign; begin WndProc; mov( uMsg, eax ); mov( &Dispatch, edx ); forever mov( (type MsgProcPtr_t [edx]).MessageHndlr, ecx ); if( ecx = 0 ) then w.DefWindowProc( hwnd, uMsg, wParam, lParam ); exit WndProc; elseif( eax = (type MsgProcPtr_t [edx]).MessageValue ) then push( hwnd ); // (type tMsgProc ecx)(hwnd, wParam, lParam) push( wParam ); // This calls the associated routine after push( lParam ); // pushing the necessary parameters. call( ecx ); sub( eax, eax ); // Return value for function is zero. break; endif; add( @size( MsgProcPtr_t ), edx ); endfor; end WndProc; begin RichEd; w.GetModuleHandle( NULL ); mov ( eax, hInstance ); w.InitCommonControls(); w.GetCommandLine(); mov ( eax, CmdLine); PathGetArgs(CmdLine); mov (eax, CmdLine); mov ([eax], dl); if (dl <> 0) then if (dl = '"') then PathUnquoteSpaces(eax); endif; mov (eax, CmdLine); endif; w.LoadLibrary(&RichEditDLL); mov (eax,hREDDLL); // get registry information RegCreateKeyEx(w.HKEY_CURRENT_USER, &szAppPath,0, &szREG_SZ,0,w.KEY_WRITE | w.KEY_READ,0, &hReg, &lpdwDisp); if (lpdwDisp = w.REG_OPENED_EXISTING_KEY) then mov (@size(wpos), lpcbData); RegQueryValueEx(hReg,&szWinPos,0,&lpType,&wpos,&lpcbData); endif; // create the window mov( @size( w.WNDCLASSEX ), wc.cbSize ); mov( w.CS_HREDRAW | w.CS_VREDRAW, wc.style ); mov( &WndProc, wc.lpfnWndProc ); mov( NULL, wc.cbClsExtra ); mov( w.DLGWINDOWEXTRA, wc.cbWndExtra ); mov( NULL, wc.hbrBackground ); mov( IDM_MENU, wc.lpszMenuName ); mov( &ClassName, wc.lpszClassName ); mov( hInstance, wc.hInstance ); // Get the icons and cursor for this application: w.LoadIcon( NULL, val w.IDI_APPLICATION ); mov( eax, wc.hIcon ); mov( eax, wc.hIconSm ); w.LoadCursor( NULL, val w.IDC_ARROW ); mov( eax, wc.hCursor ); w.RegisterClassEx( wc ); w.CreateDialogParam ( hInstance, val ID_DLG, NULL, &WndProc, NULL ); mov( eax, hwnd ); if (wpos.fMax) then mov (w.SW_MAXIMIZE, eax); else mov (w.SW_SHOWNORMAL, eax); endif; w.ShowWindow( hwnd, eax ); w.UpdateWindow(hwnd); mov (CmdLine, edx); mov ([edx], al); if (al) then str.zcpy ([edx], &FileName); LoadFile(); else str.zcpy(&NewFile, &FileName); endif; SetupWindowTitle(); w.LoadAccelerators(hInstance,val ID_ACCEL); mov (eax, hAccel); w.GetMenu(hwnd); mov (eax, hMnu); forever w.GetMessage( msg, NULL, 0, 0 ); breakif( !eax ); w.IsDialogMessage(hFind, msg); if (!eax) then if (!w.TranslateAccelerator(hwnd,hAccel,msg)) then w.TranslateMessage( msg ); w.DispatchMessage( msg ); endif; endif; endfor; w.FreeLibrary(hREDDLL); RegSetValueEx(hReg,&szWinPos,0,w.REG_BINARY,&wpos, @size(wpos)); RegCloseKey(hReg); mov( msg.wParam, eax ); w.ExitProcess( eax ); end RichEd;