uses WinProcs, WinTypes, Win31, LEdit;
{$I LEDIT__S.INC}
{$R LEDIT_2.RES}
{$I LEDIT_2.INC}

NOTHING_OPEN   = '  No open files';
INSERT_MODE    = 'Insert';
OVERWRITE_MODE = 'Overwrite';
MODIFIED       = 'Modified';
UNMODIFIED     = '';
LINE_INFO      = '  Line: %ld   Position: %d';
MAGIC          = 1233218;
Header: longint = longint(PChar(
'LEdit-Ask-User-TXT/Header files/*.h/C++ source/*.cpp/Pascal source/*.pas/' +
'Text files/*.txt/All files/*.*'));

type
 TPos = record
   Line: longint;
   Pos: word;
 end;

const
  NumWin: word = 0;
  InsertMode: word = EMP_SET;

var
  Msg: TMsg;
  LGroup,           { LEditGroup window           }
  Wnd,
  WndClient,        { Client window               }
  WndModify,        { "Modify" part of status bar }
  WndInsert,        { "Insert" part of status bar }
  WndStatus: hWnd;  { The rest of status bar      }
  StatusBarHeight,
  InsertWidth: word;
  Buffer: array[0..63] of char;
  wc: TWndClass;

{ Main frame function }
function FrameProc (Wnd: hWnd;
		    Msg,
		    wParam: word;
		    lParam: longint): longint;
export;

var
  csWindow: TMDICreateStruct;
  csClient: TClientCreateStruct;
  MStatus: WordBool;
  CurPos: TPos;
  LPos: TLEditPosition;
  Child: hWnd;

begin
  case (Msg) of
    WM_CREATE:
      begin
        { Create LEdit group }
        LGroup := CreateWindow('LEditGroup',
                               nil,
                               WS_CHILD,
                               0,0,0,0,
                               Wnd, 0, hInstance, nil);

        { Create MDI Client }
        csClient.hWindowMenu  := GetSubMenu(GetMenu(Wnd),4);
        csClient.idFirstChild := START_WIN + 1;
        WndClient := CreateWindow('MDICLIENT',
	 	                  nil,
			          WS_CHILD OR WS_CLIPCHILDREN OR WS_VISIBLE
                                  OR WS_HSCROLL OR WS_VSCROLL,
			          0,0,0,0,
			          Wnd, 4, hInstance, @csClient);

        { Create status bar windows }
        WndModify := CreateWindow('STATIC',
				  nil,
				  WS_CHILD OR WS_VISIBLE OR WS_BORDER
                                  OR SS_CENTER,
				  0,0,0,0,
				  Wnd, $FFFF, hInstance, nil);
        WndInsert := CreateWindow('STATIC',
				  INSERT_MODE,
				  WS_CHILD OR WS_VISIBLE OR WS_BORDER
                                  OR SS_CENTER,
				  0,0,0,0,
				  Wnd, $FFFF, hInstance, nil);
        WndStatus := CreateWindow('STATIC',
			          NOTHING_OPEN,
				  WS_CHILD OR WS_VISIBLE OR WS_BORDER,
				  0,0,0,0,
				  Wnd, $FFFF, hInstance, nil);
      end;
    WM_SIZE:
      begin
        { Move MDI client }
        MoveWindow(WndClient,0,0,
		   LOWORD(lParam),HIWORD(lParam)-StatusBarHeight,TRUE);

        { Move status bar windows }
        MoveWindow(WndModify,0,HIWORD(lParam)-StatusBarHeight,
		   InsertWidth,StatusBarHeight,TRUE);
        MoveWindow(WndInsert,InsertWidth,HIWORD(lParam)-StatusBarHeight,
		   InsertWidth,StatusBarHeight,TRUE);
        MoveWindow(WndStatus,InsertWidth*2,HIWORD(lParam)-StatusBarHeight,
       		   LOWORD(lParam)-2*InsertWidth,StatusBarHeight,TRUE);

        { Don't call DefFrameProc() }
        FrameProc := 0;
        exit;
      end;
    WM_COMMAND:
      case (wParam) of
	EC_FILENEW,
	EC_FILEOPEN:
	  begin
            { Create LEdit child }
            csWindow.szClass   := 'LEdit';
            if wParam = EC_FILEOPEN then
              csWindow.szTitle := PChar(Header)
            else
              csWindow.szTitle := nil;
            csWindow.hOwner    := hInstance;
	    csWindow.x         := CW_USEDEFAULT;
	    csWindow.y         := CW_USEDEFAULT;
	    csWindow.cx        := CW_USEDEFAULT;
	    csWindow.cy        := CW_USEDEFAULT;
	    csWindow.style     := WS_HSCROLL OR WS_VSCROLL OR
		                  ES_MDICHILD OR ES_CANCHANGEFONT OR
				  ES_USESHORTNAME OR ES_FILELOWER;
	    csWindow.lParam    := 0;

            Child := SendMessage(WndClient,WM_MDICREATE,0,longint(@csWindow));

	    if (Child <> 0) then
	      begin
                { Change a little LEdit behaviour }
		SendMessage(Child,EM_SETFILEFILTER,0,Header+15);
		SendMessage(Child,EM_SETFONT,
                  GetStockObject(DEVICE_DEFAULT_FONT),0);
                SendMessage(Child,EM_SETSYNTAX,0,1);
                Behaviour(Child);

                SendMessage(Child,EM_SETRUNTIMEFLAGS,16384,0);

                { Attach LEdit to the group }
                SendMessage(Child,EM_ATTACH,LGroup,0);
                { Or SendMessage(LGroup,EM_ATTACH,Child,0);}

		SetFocus(Child);
	      end;
            exit;
	  end;
	EC_WINDOWTILE:
          { Tile children }
          SendMessage(WndClient,WM_MDITILE,0,0);
	EC_WINDOWCASCADE:
          { Cascade children }
          SendMessage(WndClient,WM_MDICASCADE,0,0);
	EC_WINDOWICONS:
          { Arrange icons }
          SendMessage(WndClient,WM_MDIICONARRANGE,0,0);
	EC_WINDOWCLOSEALL:
	  begin
            { If it's impossible to close then do nothing }
	    if SendMessage(LGroup,EM_CLOSE,0,0) = 0 then
	      exit;

            { Take first child }
	    Child := SendMessage(WndClient,WM_MDIGETACTIVE,0,0);
	    while ( Child <> 0) do
	      begin
                { Destroy the child }
	        SendMessage(WndClient,WM_MDIDESTROY,Child,0);

                { Take next child }
	        Child := SendMessage(WndClient,WM_MDIGETACTIVE,0,0);
	      end;
          end;
	EC_HELPABOUT:
          { Show copyright message }
	  MessageBox(Wnd,
            'LEdit MDI demonstration'#13#10'(c) 1995 Andrey B. Yastrebov',
            'About LEDIT_E2',MB_OK OR MB_ICONINFORMATION);
	EC_FILEEXIT:
          { Close the window if it's possible }
          SendMessage(Wnd,WM_CLOSE,0,0);
        START_WIN..END_WIN:
	  begin
            { Handles LEdit notifications }
	    case ( HIWORD(lParam) ) of
	      EN_SETFOCUS,
              EN_CHANGE:
                begin
                  { Show modify status }
		  MStatus := LongBool(
                    SendMessage(LOWORD(lParam),EM_GETMODIFY,0,0));
                  if MStatus then
		    SetWindowText(WndModify, MODIFIED)
                  else
                    SetWindowText(WndModify, UNMODIFIED);

                  { Show current position }
		  SendMessage(LOWORD(lParam),EM_GETSEL,0,longint(@LPos));
		  CurPos.Line := LPos.EndLine;
		  CurPos.Pos  := LPos.EndPosition;
		  wvsprintf(@Buffer,LINE_INFO,CurPos);
		  SetWindowText(WndStatus, @Buffer);
                end;
	      EN_INSERTMODE:
	        begin
                  { Change insertion mode and show it }
                  InsertMode := EMP_SET;
		  SetWindowText(WndInsert,INSERT_MODE);
                end;
	      EN_OVERWRITEMODE:
		begin
                  { Change insertion mode and show it }
		  InsertMode := EMP_CLEAR;
		  SetWindowText(WndInsert,OVERWRITE_MODE);
		end;
	      EN_CREATED:
                { Increase number of LEdit windows }
	        inc(NumWin);
	      EN_DESTROY:
	        begin
                  { Decrease number of LEdit windows }
		  dec(NumWin);

                  { Correct status bar view if there are no windows }
		  if ( NumWin = 0) then
                    begin
		      SetWindowText(WndModify,nil);
		      SetWindowText(WndStatus,NOTHING_OPEN);
                    end;
	        end;
            end;
            { Return zero for all unhanled LEdit notifications }
            { because DefFrameProc () does it wrong            }
	    FrameProc := 0;
            if ( HIWORD(lParam) <> 0 ) then
              exit;
          end;
	else
          { pass the Comand to the active LEdit }
	  SendMessage(LGroup,WM_COMMAND,wParam,lParam);
      end;
    WM_INITMENU:
      begin
        { DisableMenu will be called automatically }
	SendMessage(LGroup,EM_ENABLEMENU,wParam,0);
      end;
    WM_CLOSE,
    WM_QUERYENDSESSION:
      { If LEdit windows report that they can be closed }
      { then let DefFrameProc() decides                 }
      { Otherwise don't allow to close                  }
      if SendMessage(LGroup,EM_CLOSE,0,0) = 0 then begin
        FrameProc := 0;
        exit;
      end;
    WM_DESTROY:
      { Stop the application }
      PostQuitMessage(0);
  end;
  { Call DefFrameProc() for the rest of messages }
  FrameProc := DefFrameProc(Wnd,WndClient,Msg,wParam,lParam);
end;

{ Main block }
begin
  { Don't allow multiple instances }
  if ( hPrevInst <> 0 ) then
    Halt(0);

  { Determine constants }
  StatusBarHeight := GetSystemMetrics(SM_CYMENU);
  InsertWidth := GetSystemMetrics(SM_CXVSCROLL)*8;

  { Register frame window class }
  wc.style         := CS_HREDRAW OR CS_VREDRAW;
  wc.lpfnWndProc   := @FrameProc;
  wc.cbClsExtra    := 0;
  wc.cbWndExtra    := 0;
  wc.hInstance     := hInstance;
  wc.hIcon         := LoadIcon(0,IDI_APPLICATION);
  wc.hCursor       := LoadCursor(0,IDC_ARROW);
  wc.hbrBackground := (COLOR_APPWORKSPACE + 1);
  wc.lpszMenuName  := 'STD_MDI_MENU';
  wc.lpszClassName := 'LEditFrame';
  RegisterClass(wc);

  { Create main window }
  Wnd := CreateWindow('LEditFrame',
		      'MDI Editor',
		      WS_OVERLAPPEDWINDOW,
		      CW_USEDEFAULT, CW_USEDEFAULT,
		      CW_USEDEFAULT, CW_USEDEFAULT,
		      0, 0, hInstance, nil);
  if ( Wnd <> 0 ) then
    begin
      { Show window }
      ShowWindow(Wnd,SW_SHOW);

      { Run message loop }
      while GetMessage(Msg,0,0,0) do
        if ( NOT TranslateMDISysAccel(WndClient,Msg) ) then
          begin
            TranslateMessage(Msg);
	    DispatchMessage(Msg);
          end
    end;
end.
