(***********************************************)
(*                                             *)
(* Simple Text Editor (Win32 GUI Demo)         *)
(* Copyright (c) 1999 by TMT Development Corp. *)
(* Author: Vadim Bodrov, TMT Development Corp. *)
(*                                             *)
(* Targets:                                    *)
(*   WIN32 GUI application                     *)
(*                                             *)
(***********************************************)

program SEdit;

{$ifndef __WIN32__}
{$define INVALID_TARGET}
{$endif}
{$ifndef __GUI__}
{$define INVALID_TARGET}
{$endif}
{$ifdef INVALID_TARGET}
  This program must be compiled as Win32 GUI application only
{$endif}

uses Windows, Strings, Messages, CommCtrl, CommDlg,  ShellAPI, AfxRes;

{$w-,r-,q-,i-,t-,x+,v-,a+,oa+,opt+}

{$r sedit.res}

type
  TFindOptions = record
    frDown, frMatchCase, frWholeWord: Boolean;
end;

const
  ID_EDIT_FIND_NEXT = 40001;
  ID_APP_HOME_PAGE  = 40002;
  ID_EDIT_WORD_WRAP = 40003;

var
  ToolBar: HWnd;        // ToolBar handle
  MainWindow: HWnd;     // Main Window handle
  Menu: HWnd;           // Menu Handle
  Editor: HWnd;         // TextEdit handle
  Accel: HWnd;          // Accelerator table handle
  Msg: TMsg;            // Window Message

  FileName: String := '';
  TextChanged: Boolean := FALSE;
  WordWrap: Boolean := FALSE;

  SrchString: String := '';
  FindOptions: TFindOptions;

{$i controls.inc}
{$i search.inc}
{$i cdlg.inc}

function AskForSave: DWORD;
var
  Txt: String;
begin
  if TextChanged then
  begin
    Txt := 'File ' + FileName + 'is not saved' + #13 + 'Save it?' + #0;
    Result := MessageBox(MainWindow, @Txt[1], 'Warning!', MB_ICONWARNING or MB_YESNOCANCEL);
  end else
    Result := IDNO;
end;

function MyWndProc conv arg_stdcall (Window: HWND; Mess: DWord; WParam: DWord; LParam: LongInt): LongInt;
begin
  Result := 0;
  case Mess of
  WM_SIZE:
    begin
      MoveWindow(Editor, 0, 27, LoWord(LParam), HiWord(LParam) - 27, TRUE);
      MoveWindow(ToolBar, 0, 0, LoWord(LParam), 27, TRUE);
    end;

  WM_CLOSE:
     declare
     var SaveRes: DWORD;
     begin
       SaveRes := AskForSave;
       if Saveres = IDCANCEL then exit;
       if SaveRes = IDYES then
       begin
         if FileName <> '' then
           eSaveFile(Editor, FileName, FALSE)
         else
           eSaveFile(Editor, FileName, TRUE);
       end;
       Result := DefWindowProc(Window, Mess, WParam, LParam);
     end;

  WM_DESTROY:
    PostQuitMessage(0);

  WM_COMMAND:
     begin
       if (HiWord(WParam) = EN_CHANGE) and (LParam = Editor) then
         TextChanged := TRUE;

       case LoWord(WParam) of
       ID_FILE_NEW:
         begin
           declare
           var SaveRes: DWORD;
           begin
             SaveRes := AskForSave;
             if SaveRes = IDCANCEL then exit;
             if SaveRes = IDYES then
             begin
               if FileName <> '' then
                 eSaveFile(Editor, FileName, FALSE)
               else
                 eSaveFile(Editor, FileName, TRUE);
             end;
           end;
           SendMessage(Editor, EM_SETSEL, 0, -1);
           SendMessage(Editor, WM_CLEAR, 0, 0);
           TextChanged := FALSE;
           FileName := '';
         end;

       ID_FILE_OPEN:
         begin
           declare
           var SaveRes: DWORD;
           begin
             SaveRes := AskForSave;
             if SaveRes = IDCANCEL then exit;
             if SaveRes = IDYES then
             begin
               if FileName <> '' then
                 eSaveFile(Editor, FileName, FALSE)
               else
                 eSaveFile(Editor, FileName, TRUE);
             end;
             eOpenFile(Editor, FileName, TRUE);
           end;
         end;

       ID_FILE_SAVE:
         begin
           if FileName <> '' then
             eSaveFile(Editor, FileName, FALSE)
           else
             eSaveFile(Editor, FileName, TRUE);
         end;

       ID_FILE_SAVE_AS:
         eSaveFile(Editor, FileName, TRUE);

       ID_APP_EXIT:
         CloseWindow(Window);

       ID_EDIT_UNDO:
         SendMessage(Editor, WM_UNDO, 0, 0);

       ID_EDIT_CUT:
         SendMessage(Editor, WM_CUT, 0, 0);

       ID_EDIT_COPY:
         SendMessage(Editor, WM_COPY, 0, 0);

       ID_EDIT_PASTE:
         SendMessage(Editor, WM_PASTE, 0, 0);

       ID_EDIT_SELECT_ALL:
         SendMessage(Editor, EM_SETSEL, 0, -1);

       ID_EDIT_FIND:
         DialogBoxParam(hInstance, MAKEINTRESOURCE(102), MainWindow, @FindDlgProc, 0);

       ID_EDIT_FIND_NEXT:
         begin
           if SrchString = '' then
             DialogBoxParam(hInstance, MAKEINTRESOURCE(102), MainWindow, @FindDlgProc, 0)
           else
             SearchText(SrchString, FindOptions);
         end;

       ID_APP_HOME_PAGE:
         ShellExecute(MainWindow, 'open', 'http://www.tmt.com', nil, nil, SW_SHOWDEFAULT);

       ID_APP_ABOUT:
         DialogBoxParam(hInstance, MAKEINTRESOURCE(101), MainWindow, @AboutDlgProc, 0);

       ID_EDIT_WORD_WRAP:
         begin
           WordWrap := not WordWrap;
           CheckMenuItem(Menu, ID_EDIT_WORD_WRAP, DWORD(WordWrap) * MF_CHECKED or MF_BYCOMMAND);
           Editor := CreateEditControl(MainWindow, WordWrap);
         end;
       end;
    end;
  else
    Result := DefWindowProc(Window, Mess, WParam, LParam);
  end;
end;

begin
  InitCommonControls;
  Menu := LoadMenu(hInstance, MAKEINTRESOURCE(102));
  MainWindow := CreateMainWindow(@MyWndProc, Menu);
  ToolBar := CreateMainToolBar;
  Editor := CreateEditControl(MainWindow, FALSE);

  ShowWindow(MainWindow, SW_SHOW);
  UpdateWindow(MainWindow);

  ShowWindow(ToolBar, SW_SHOW);

  // Load an accelerator-table resource
  Accel := LoadAccelerators(hInstance, MAKEINTRESOURCE(128));

  // Initialize FindOptions structure
  with FindOptions do
  begin
    frDown      := TRUE;
    frMatchCase := FALSE;
    frWholeWord := TRUE;
  end;

  // Load file specified in ParamStr(1)
  if ParamCount >0 then
  begin
    FileName := ParamStr(1);
    eOpenFile(Editor, FileName, FALSE);
  end;

  while GetMessage(Msg, 0, 0, 0) do
  begin
    // Process accelerator keys for menu commands
    TranslateAccelerator(MainWindow, Accel, Msg);

    // Translate virtual-key messages into character messages
    TranslateMessage(Msg);

    // Dispatch a message to a window procedure (MyWndProc)
    DispatchMessage(Msg);
  end;

  // Destroy a main window
  DestroyMenu(Menu);
end.