home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / kolekce / d3456 / ALEXSOFT.ZIP / RUSSIAN / MEMOEDIT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-09-04  |  22.3 KB  |  782 lines

  1. (*////////////////////////////////////////////////////////////////////////////
  2. //   Part of AlexSoft VCL/DLL Library.                                      //
  3. //   All rights reserved. (c) Copyright 1998.                               //
  4. //   Created by: Alex Rabichooc                                             //
  5. //**************************************************************************//
  6. //  Users of this unit must accept this disclaimer of warranty:             //
  7. //    "This unit is supplied as is. The author disclaims all warranties,    //
  8. //    expressed or implied, including, without limitation, the warranties   //
  9. //    of merchantability and of fitness for any purpose.                    //
  10. //    The author assumes no liability for damages, direct or                //
  11. //    consequential, which may result from the use of this unit."           //
  12. //                                                                          //
  13. //  This Unit is donated to the public as public domain.                    //
  14. //                                                                          //
  15. //  This Unit can be freely used and distributed in commercial and          //
  16. //  private environments provided this notice is not modified in any way.   //
  17. //                                                                          //
  18. //  If you do find this Unit handy and you feel guilty for using such a     //
  19. //  great product without paying someone - sorry :-)                        //
  20. //                                                                          //
  21. //  Please forward any comments or suggestions to Alex Rabichooc at:        //
  22. //                                                                          //
  23. //  a_rabichooc@yahoo.com or alex@carmez.mldnet.com                         //
  24. /////////////////////////////////////////////////////////////////////////////*)
  25.  
  26. unit MemoEdit;
  27.  
  28. interface
  29.  
  30. uses
  31.   SysUtils, Windows, Messages, Classes, Graphics, Controls,
  32.   Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, Menus, ComCtrls, ClipBrd,
  33.   ToolWin, Db, DBTables, DBCtrls, RichEdit, DBxNav{$IFNDEF VER100}, ImgList{$ENDIF};
  34.  
  35. type
  36.   TMemoEditor = class(TForm)
  37.     MainMenu: TMainMenu;
  38.     FileOpenItem: TMenuItem;
  39.     FileSaveItem: TMenuItem;
  40.     FileSaveAsItem: TMenuItem;
  41.     FilePrintItem: TMenuItem;
  42.     FileExitItem: TMenuItem;
  43.     EditUndoItem: TMenuItem;
  44.     EditCutItem: TMenuItem;
  45.     EditCopyItem: TMenuItem;
  46.     EditPasteItem: TMenuItem;
  47.     OpenDialog: TOpenDialog;
  48.     SaveDialog: TSaveDialog;
  49.     PrintDialog: TPrintDialog;
  50.     Ruler: TPanel;
  51.     FontDialog1: TFontDialog;
  52.     FirstInd: TLabel;
  53.     LeftInd: TLabel;
  54.     RulerLine: TBevel;
  55.     RightInd: TLabel;
  56.     N5: TMenuItem;
  57.     miEditFont: TMenuItem;
  58.     StatusBar: TStatusBar;
  59.     ToolBar: TToolBar;
  60.     OpenButton: TToolButton;
  61.     SaveButton: TToolButton;
  62.     PrintButton: TToolButton;
  63.     ToolButton5: TToolButton;
  64.     UndoButton: TToolButton;
  65.     CutButton: TToolButton;
  66.     CopyButton: TToolButton;
  67.     PasteButton: TToolButton;
  68.     ToolButton10: TToolButton;
  69.     FontName: TComboBox;
  70.     FontSize: TEdit;
  71.     ToolButton11: TToolButton;
  72.     UpDown1: TUpDown;
  73.     BoldButton: TToolButton;
  74.     ItalicButton: TToolButton;
  75.     UnderlineButton: TToolButton;
  76.     ToolButton16: TToolButton;
  77.     LeftAlign: TToolButton;
  78.     CenterAlign: TToolButton;
  79.     RightAlign: TToolButton;
  80.     ToolButton20: TToolButton;
  81.     BulletsButton: TToolButton;
  82.     ToolbarImages: TImageList;
  83.     Editor: TDBRichEdit;
  84.     DataSource: TDataSource;
  85.     FindDialog1: TFindDialog;
  86.     N3: TMenuItem;
  87.     EditFindText: TMenuItem;
  88.  
  89.     procedure SelectionChange(Sender: TObject);
  90.     procedure FormCreate(Sender: TObject);
  91.     procedure ShowHint(Sender: TObject);
  92.     procedure FileOpen(Sender: TObject);
  93.     procedure FileSave(Sender: TObject);
  94.     procedure FileSaveAs(Sender: TObject);
  95.     procedure FilePrint(Sender: TObject);
  96.     procedure FileExit(Sender: TObject);
  97.     procedure EditUndo(Sender: TObject);
  98.     procedure EditCut(Sender: TObject);
  99.     procedure EditCopy(Sender: TObject);
  100.     procedure EditPaste(Sender: TObject);
  101.     procedure HelpContents(Sender: TObject);
  102.     procedure HelpSearch(Sender: TObject);
  103.     procedure HelpHowToUse(Sender: TObject);
  104.     procedure SelectFont(Sender: TObject);
  105.     procedure RulerResize(Sender: TObject);
  106.     procedure FormResize(Sender: TObject);
  107.     procedure FormPaint(Sender: TObject);
  108.     procedure BoldButtonClick(Sender: TObject);
  109.     procedure ItalicButtonClick(Sender: TObject);
  110.     procedure FontSizeChange(Sender: TObject);
  111.     procedure AlignButtonClick(Sender: TObject);
  112.     procedure FontNameChange(Sender: TObject);
  113.     procedure UnderlineButtonClick(Sender: TObject);
  114.     procedure BulletsButtonClick(Sender: TObject);
  115.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  116.     procedure RulerItemMouseDown(Sender: TObject; Button: TMouseButton;
  117.       Shift: TShiftState; X, Y: Integer);
  118.     procedure RulerItemMouseMove(Sender: TObject; Shift: TShiftState; X,
  119.       Y: Integer);
  120.     procedure FirstIndMouseUp(Sender: TObject; Button: TMouseButton;
  121.       Shift: TShiftState; X, Y: Integer);
  122.     procedure LeftIndMouseUp(Sender: TObject; Button: TMouseButton;
  123.       Shift: TShiftState; X, Y: Integer);
  124.     procedure RightIndMouseUp(Sender: TObject; Button: TMouseButton;
  125.       Shift: TShiftState; X, Y: Integer);
  126.     procedure FormShow(Sender: TObject);
  127.     procedure RichEditChange(Sender: TObject);
  128.     procedure FormDestroy(Sender: TObject);
  129.     procedure EditorKeyDown(Sender: TObject; var Key: Word;
  130.       Shift: TShiftState);
  131.     procedure EditFindTextClick(Sender: TObject);
  132.     procedure FindDialog1Find(Sender: TObject);
  133.     procedure DataSourceDataChange(Sender: TObject; Field: TField);
  134.   private
  135.     FFieldName: string;
  136.     FUpdating: Boolean;
  137.     FDragOfs: Integer;
  138.     FDragging: Boolean;
  139.     FClipboardOwner: HWnd;
  140.     FOnIdle: TIdleEvent;
  141.     FOnHint: TNotifyEvent;
  142.     procedure OnIdle(Sender: TObject; var Done: Boolean);
  143.     function CurrText: TTextAttributes;
  144.     procedure GetFontNames;
  145.     procedure CheckFileSave;
  146.     procedure SetupRuler;
  147.     procedure SetEditRect;
  148.     procedure UpdateCursorPos;
  149.     procedure ClipboardChanged;
  150.     procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
  151.     procedure WMChangeCBChain(var Msg: TWMChangeCBChain); message WM_CHANGECBCHAIN;
  152.     procedure WMDrawClipboard(var Msg: TWMDrawClipboard); message WM_DRAWCLIPBOARD;
  153.     procedure PerformFileOpen(const AFileName: string);
  154.     procedure SetModified(Value: Boolean);
  155.     procedure ReadStatusKeys;
  156.   public
  157.     constructor CreateWithField(AOwner: TComponent; AField: TField); virtual;
  158.   end;
  159.  
  160. var
  161.   MemoEditor: TMemoEditor;
  162.  
  163. implementation
  164.  
  165. uses ShellAPI, DbXCnsts;
  166.  
  167. const
  168.   RulerAdj = 4/3;
  169.   GutterWid = 6;
  170.  
  171. {$R *.DFM}
  172.  
  173. constructor TMemoEditor.CreateWithField(AOwner: TComponent; AField: TField);
  174. begin
  175.    Create(AOwner);
  176.    with Editor do
  177.    if AField <> nil then
  178.    begin
  179.       DataSource.DataSet := AField.DataSet;
  180.       DataField := AField.FieldName;
  181.    end;
  182. end;
  183.  
  184. procedure TMemoEditor.OnIdle(Sender: TObject; var Done: Boolean);
  185. begin
  186.    if Assigned(FOnIdle) then
  187.       FOnIdle(Sender, Done);
  188.    ReadStatusKeys;
  189. end;
  190.  
  191. procedure TMemoEditor.ReadStatusKeys;
  192. var PanelID : Byte;
  193.     Text    : String;
  194.     Key: Word;
  195. begin
  196.   Key := 0;
  197.   for PanelID := 2 to 4 do
  198.   begin
  199.      case PanelID of
  200.        2: begin
  201.              Text := 'NUM';
  202.              Key := vk_NumLock;
  203.           end;
  204.        3: begin
  205.              Text := 'CAPS';
  206.              Key := vk_Capital;
  207.           end;
  208.        4: begin
  209.              Text := 'SCR';
  210.              Key := vk_Scroll;
  211.           end;
  212.      end;
  213.      if GetKeyState(Key) MOD 2 = 0 then
  214.             Text := '';
  215.      StatusBar.Panels.Items[PanelID].Text:=Text;
  216.   end;
  217. end;
  218.  
  219. procedure TMemoEditor.SelectionChange(Sender: TObject);
  220. begin
  221.   with Editor.Paragraph do
  222.   try
  223.     FUpdating := True;
  224.     FirstInd.Left := Trunc(FirstIndent*RulerAdj)-4+GutterWid;
  225.     LeftInd.Left := Trunc((LeftIndent+FirstIndent)*RulerAdj)-4+GutterWid;
  226.     RightInd.Left := Ruler.ClientWidth-6-Trunc((RightIndent+GutterWid)*RulerAdj);
  227.     BoldButton.Down := fsBold in Editor.SelAttributes.Style;
  228.     ItalicButton.Down := fsItalic in Editor.SelAttributes.Style;
  229.     UnderlineButton.Down := fsUnderline in Editor.SelAttributes.Style;
  230.     BulletsButton.Down := Boolean(Numbering);
  231.     FontSize.Text := IntToStr(Editor.SelAttributes.Size);
  232.     FontName.Text := Editor.SelAttributes.Name;
  233.     case Ord(Alignment) of
  234.       0: LeftAlign.Down := True;
  235.       1: RightAlign.Down := True;
  236.       2: CenterAlign.Down := True;
  237.     end;
  238.     UpdateCursorPos;
  239.   finally
  240.     FUpdating := False;
  241.   end;
  242. end;
  243.  
  244. function TMemoEditor.CurrText: TTextAttributes;
  245. begin
  246.   if Editor.SelLength > 0 then Result := Editor.SelAttributes
  247.   else Result := Editor.DefAttributes;
  248. end;
  249.  
  250. function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
  251.   FontType: Integer; Data: Pointer): Integer; stdcall;
  252. begin
  253.   TStrings(Data).Add(LogFont.lfFaceName);
  254.   Result := 1;
  255. end;
  256.  
  257. procedure TMemoEditor.GetFontNames;
  258. var
  259.   DC: HDC;
  260. begin
  261.   DC := GetDC(0);
  262.   EnumFonts(DC, nil, @EnumFontsProc, Pointer(FontName.Items));
  263.   ReleaseDC(0, DC);
  264.   FontName.Sorted := True;
  265. end;
  266.  
  267. procedure TMemoEditor.CheckFileSave;
  268. var
  269.   SaveResp: Integer;
  270. begin
  271.   if not Editor.Modified then Exit;
  272.   SaveResp := MessageDlg(SSaveConfirm,
  273.     mtConfirmation, mbYesNoCancel, 0);
  274.   case SaveResp of
  275.     idYes: FileSave(Self);
  276.     idNo: {Nothing};
  277.     idCancel: Abort;
  278.   end;
  279. end;
  280.  
  281. procedure TMemoEditor.SetupRuler;
  282. var
  283.   I: Integer;
  284.   S: String;
  285. begin
  286.   SetLength(S, 201);
  287.   I := 1;
  288.   while I < 200 do
  289.   begin
  290.     S[I] := #9;
  291.     S[I+1] := '|';
  292.     Inc(I, 2);
  293.   end;
  294.   Ruler.Caption := S;
  295. end;
  296.  
  297. procedure TMemoEditor.SetEditRect;
  298. var
  299.   R: TRect;
  300. begin
  301.   with Editor do
  302.   begin
  303.     R := Rect(GutterWid, 0, ClientWidth-GutterWid, ClientHeight);
  304.     SendMessage(Handle, EM_SETRECT, 0, Longint(@R));
  305.   end;
  306. end;
  307.  
  308. { Event Handlers }
  309.  
  310. procedure TMemoEditor.FormCreate(Sender: TObject);
  311. var ParentForm: TCustomForm;
  312. begin
  313.   if (Owner is TWinControl) then
  314.   begin
  315.      ParentForm := GetParentForm(Owner as TWinControl);
  316.      if ParentForm <> nil then
  317.        Font := ParentForm.Font;
  318.   end;
  319.   FOnHint := Application.OnHint;
  320.   FOnIdle := Application.OnIdle;
  321.   Application.OnHint := ShowHint;
  322.   Application.OnIdle := OnIdle;
  323.   OpenDialog.InitialDir := ExtractFilePath(ParamStr(0));
  324.   SaveDialog.InitialDir := OpenDialog.InitialDir;
  325.   GetFontNames;
  326.   SetupRuler;
  327.   SelectionChange(Self);
  328.   FClipboardOwner := SetClipboardViewer(Handle);
  329.   StatusBar.Panels[5].Text := SInsert;
  330. end;
  331.  
  332. procedure TMemoEditor.ShowHint(Sender: TObject);
  333. begin
  334.   if Length(Application.Hint) > 0 then
  335.   begin
  336.     StatusBar.SimplePanel := True;
  337.     StatusBar.SimpleText := Application.Hint;
  338.   end
  339.   else StatusBar.SimplePanel := False;
  340. end;
  341.  
  342. procedure TMemoEditor.PerformFileOpen(const AFileName: string);
  343. var FRichEdit: TRichEdit;
  344. begin
  345.   if (Editor.Field <> nil) then
  346.      Editor.Field.DataSet.Edit;
  347.   FRichEdit := TRichEdit.Create(Self);
  348.   try
  349.     FRichEdit.Top := Editor.Top;
  350.     FRichEdit.Width := Editor.Width;
  351.     FRichEdit.Height := Editor.Height;
  352.     FRichEdit.Visible := False;
  353.     FRichEdit.Parent := Editor.Parent;
  354.     FRichEdit.Lines.LoadFromFile(AFileName);
  355.     FRichEdit.SelectAll;
  356.     FRichEdit.CopyToClipboard;
  357.     try
  358.       FUpdating := True;
  359.       Editor.Visible := False;
  360.       Editor.SelectAll;
  361.       Editor.PasteFromClipboard;
  362.       ClipBoard.Clear;
  363.       Editor.SelStart := 0;
  364.       Editor.SelLength := 0;
  365.     finally
  366.       Editor.Visible := True;
  367.       FUpdating := False;
  368.     end;
  369.   finally
  370.     FRichEdit.Free;
  371.   end;
  372.   Editor.SetFocus;
  373. end;
  374.  
  375. procedure TMemoEditor.FileOpen(Sender: TObject);
  376. begin
  377.   CheckFileSave;
  378.   if OpenDialog.Execute then
  379.   begin
  380.     PerformFileOpen(OpenDialog.FileName);
  381.     Editor.ReadOnly := ofReadOnly in OpenDialog.Options;
  382.   end;
  383. end;
  384.  
  385. procedure TMemoEditor.FileSave(Sender: TObject);
  386. begin
  387.   if (Editor.Field <> nil) and (Editor.Modified) and
  388.                         (Editor.Field.DataSet.CanModify) then
  389.   with Editor.Field.DataSet do
  390.   begin
  391.      Post;
  392.      Edit;
  393.   end;
  394.   SetModified(False);
  395. end;
  396.  
  397. procedure TMemoEditor.FileSaveAs(Sender: TObject);
  398. var FRichEdit: TRichEdit;
  399. begin
  400.   if SaveDialog.Execute then
  401.   begin
  402.     if FileExists(SaveDialog.FileName) then
  403.       if MessageDlg(Format(SOverWriteConfirm,
  404.         [SaveDialog.FileName]), mtConfirmation, mbYesNoCancel, 0) <> idYes then
  405.        Exit;
  406.  
  407.     FRichEdit := TRichEdit.Create(Self);
  408.     try
  409.       FRichEdit.Top := Editor.Top;
  410.       FRichEdit.Width := Editor.Width;
  411.       FRichEdit.Height := Editor.Height;
  412.       FRichEdit.Visible := False;
  413.       FRichEdit.Parent := Editor.Parent;
  414.       try
  415.         FUpdating := True;
  416.         Editor.Visible := False;
  417.         Editor.SelectAll;
  418.         Editor.CopyToClipboard;
  419.         FRichEdit.PasteFromClipBoard;
  420.         ClipBoard.Clear;
  421.         FRichEdit.Lines.SaveToFile(SaveDialog.FileName);
  422.         Editor.SelStart := 0;
  423.         Editor.SelLength := 0;
  424.       finally
  425.         Editor.Visible := True;
  426.         FUpdating := False;
  427.       end;
  428.     finally
  429.       FRichEdit.Free;
  430.     end;
  431.   end;
  432.   Editor.SetFocus;
  433. end;
  434.  
  435. procedure TMemoEditor.FilePrint(Sender: TObject);
  436. begin
  437.   if PrintDialog.Execute then
  438.     Editor.Print(FFieldName);
  439. end;
  440.  
  441. procedure TMemoEditor.FileExit(Sender: TObject);
  442. begin
  443.   Close;
  444. end;
  445.  
  446. procedure TMemoEditor.EditUndo(Sender: TObject);
  447. begin
  448.   with Editor do
  449.     if HandleAllocated then SendMessage(Handle, EM_UNDO, 0, 0);
  450. end;
  451.  
  452. procedure TMemoEditor.EditCut(Sender: TObject);
  453. begin
  454.   Editor.CutToClipboard;
  455. end;
  456.  
  457. procedure TMemoEditor.EditCopy(Sender: TObject);
  458. begin
  459.   Editor.CopyToClipboard;
  460. end;
  461.  
  462. procedure TMemoEditor.EditPaste(Sender: TObject);
  463. begin
  464.   Editor.PasteFromClipboard;
  465. end;
  466.  
  467. procedure TMemoEditor.HelpContents(Sender: TObject);
  468. begin
  469.   Application.HelpCommand(HELP_CONTENTS, 0);
  470. end;
  471.  
  472. procedure TMemoEditor.HelpSearch(Sender: TObject);
  473. const
  474.   EmptyString: PChar = '';
  475. begin
  476.   Application.HelpCommand(HELP_PARTIALKEY, Longint(EmptyString));
  477. end;
  478.  
  479. procedure TMemoEditor.HelpHowToUse(Sender: TObject);
  480. begin
  481.   Application.HelpCommand(HELP_HELPONHELP, 0);
  482. end;
  483.  
  484. procedure TMemoEditor.SelectFont(Sender: TObject);
  485. begin
  486.   FontDialog1.Font.Assign(Editor.SelAttributes);
  487.   if FontDialog1.Execute then
  488.     CurrText.Assign(FontDialog1.Font);
  489.   Editor.SetFocus;
  490. end;
  491.  
  492. procedure TMemoEditor.RulerResize(Sender: TObject);
  493. begin
  494.   RulerLine.Width := Ruler.ClientWidth - (RulerLine.Left*2);
  495. end;
  496.  
  497. procedure TMemoEditor.FormResize(Sender: TObject);
  498. begin
  499.   SetEditRect;
  500.   SelectionChange(Sender);
  501. end;
  502.  
  503. procedure TMemoEditor.FormPaint(Sender: TObject);
  504. begin
  505.   SetEditRect;
  506. end;
  507.  
  508. procedure TMemoEditor.BoldButtonClick(Sender: TObject);
  509. begin
  510.   if FUpdating then Exit;
  511.   if BoldButton.Down then
  512.     CurrText.Style := CurrText.Style + [fsBold]
  513.   else
  514.     CurrText.Style := CurrText.Style - [fsBold];
  515. end;
  516.  
  517. procedure TMemoEditor.ItalicButtonClick(Sender: TObject);
  518. begin
  519.   if FUpdating then Exit;
  520.   if ItalicButton.Down then
  521.     CurrText.Style := CurrText.Style + [fsItalic]
  522.   else
  523.     CurrText.Style := CurrText.Style - [fsItalic];
  524. end;
  525.  
  526. procedure TMemoEditor.FontSizeChange(Sender: TObject);
  527. begin
  528.   if FUpdating then Exit;
  529.   CurrText.Size := StrToInt(FontSize.Text);
  530. end;
  531.  
  532. procedure TMemoEditor.AlignButtonClick(Sender: TObject);
  533. begin
  534.   if FUpdating then Exit;
  535.   Editor.Paragraph.Alignment := TAlignment(TControl(Sender).Tag);
  536. end;
  537.  
  538. procedure TMemoEditor.FontNameChange(Sender: TObject);
  539. begin
  540.   if FUpdating then Exit;
  541.   CurrText.Name := FontName.Items[FontName.ItemIndex];
  542. end;
  543.  
  544. procedure TMemoEditor.UnderlineButtonClick(Sender: TObject);
  545. begin
  546.   if FUpdating then Exit;
  547.   if UnderlineButton.Down then
  548.     CurrText.Style := CurrText.Style + [fsUnderline]
  549.   else
  550.     CurrText.Style := CurrText.Style - [fsUnderline];
  551. end;
  552.  
  553. procedure TMemoEditor.BulletsButtonClick(Sender: TObject);
  554. begin
  555.   if FUpdating then Exit;
  556.   Editor.Paragraph.Numbering := TNumberingStyle(BulletsButton.Down);
  557. end;
  558.  
  559. procedure TMemoEditor.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  560. begin
  561.   try
  562.     CheckFileSave;
  563.   except
  564.     CanClose := False;
  565.   end;
  566. end;
  567.  
  568. { Ruler Indent Dragging }
  569.  
  570. procedure TMemoEditor.RulerItemMouseDown(Sender: TObject; Button: TMouseButton;
  571.   Shift: TShiftState; X, Y: Integer);
  572. begin
  573.   FDragOfs := (TLabel(Sender).Width div 2);
  574.   TLabel(Sender).Left := TLabel(Sender).Left+X-FDragOfs;
  575.   FDragging := True;
  576. end;
  577.  
  578. procedure TMemoEditor.RulerItemMouseMove(Sender: TObject; Shift: TShiftState;
  579.   X, Y: Integer);
  580. begin
  581.   if FDragging then
  582.     TLabel(Sender).Left :=  TLabel(Sender).Left+X-FDragOfs
  583. end;
  584.  
  585. procedure TMemoEditor.FirstIndMouseUp(Sender: TObject; Button: TMouseButton;
  586.   Shift: TShiftState; X, Y: Integer);
  587. begin
  588.   FDragging := False;
  589.   Editor.Paragraph.FirstIndent := Trunc((FirstInd.Left+FDragOfs-GutterWid) / RulerAdj);
  590.   LeftIndMouseUp(Sender, Button, Shift, X, Y);
  591. end;
  592.  
  593. procedure TMemoEditor.LeftIndMouseUp(Sender: TObject; Button: TMouseButton;
  594.   Shift: TShiftState; X, Y: Integer);
  595. begin
  596.   FDragging := False;
  597.   Editor.Paragraph.LeftIndent := Trunc((LeftInd.Left+FDragOfs-GutterWid) / RulerAdj)-Editor.Paragraph.FirstIndent;
  598.   SelectionChange(Sender);
  599. end;
  600.  
  601. procedure TMemoEditor.RightIndMouseUp(Sender: TObject; Button: TMouseButton;
  602.   Shift: TShiftState; X, Y: Integer);
  603. begin
  604.   FDragging := False;
  605.   Editor.Paragraph.RightIndent := Trunc((Ruler.ClientWidth-RightInd.Left+FDragOfs-2) / RulerAdj)-2*GutterWid;
  606.   SelectionChange(Sender);
  607. end;
  608.  
  609. procedure TMemoEditor.UpdateCursorPos;
  610. var
  611.   CharPos: TPoint;
  612. begin
  613.   CharPos.Y := SendMessage(Editor.Handle, EM_EXLINEFROMCHAR, 0,
  614.     Editor.SelStart);
  615.   CharPos.X := (Editor.SelStart -
  616.     SendMessage(Editor.Handle, EM_LINEINDEX, CharPos.Y, 0));
  617.   Inc(CharPos.Y);
  618.   Inc(CharPos.X);
  619.   StatusBar.Panels[0].Text := Format('%4d:%-3d', [CharPos.Y, CharPos.X]);
  620.  
  621.   // update the status of the cut and copy command
  622.   CopyButton.Enabled := Editor.SelLength > 0;
  623.   EditCopyItem.Enabled := CopyButton.Enabled;
  624.   CutButton.Enabled := CopyButton.Enabled;
  625.   EditCutItem.Enabled := CopyButton.Enabled;
  626. end;
  627.  
  628. procedure TMemoEditor.FormShow(Sender: TObject);
  629. begin
  630.   UpdateCursorPos;
  631.   DragAcceptFiles(Handle, True);
  632.   if (Editor.Field <> nil) and (Editor.Modified) and
  633.                         (Editor.Field.DataSet.CanModify) then
  634.   with Editor.Field.DataSet do
  635.   begin
  636.      if State = dsBrowse then
  637.        if IsEmpty then
  638.         Insert
  639.          else
  640.         Edit;
  641.   end;
  642.   RichEditChange(nil);
  643.   SetModified(False);
  644.   Editor.SetFocus;
  645.   ClipboardChanged;
  646.  
  647.   // check if we should load a file from the command line
  648.   if (ParamCount > 0) and FileExists(ParamStr(1)) then
  649.     PerformFileOpen(ParamStr(1));
  650. end;
  651.  
  652. procedure TMemoEditor.WMDropFiles(var Msg: TWMDropFiles);
  653. var
  654.   CFileName: array[0..MAX_PATH] of Char;
  655. begin
  656.   try
  657.     if DragQueryFile(Msg.Drop, 0, CFileName, MAX_PATH) > 0 then
  658.     begin
  659.       CheckFileSave;
  660.       PerformFileOpen(CFileName);
  661.       Msg.Result := 0;
  662.     end;
  663.   finally
  664.     DragFinish(Msg.Drop);
  665.   end;
  666. end;
  667.  
  668. procedure TMemoEditor.RichEditChange(Sender: TObject);
  669. begin
  670.   SetModified(Editor.Modified);
  671.   UndoButton.Enabled := SendMessage(Editor.Handle, EM_CANUNDO, 0, 0) <> 0;
  672.   EditUndoItem.Enabled := UndoButton.Enabled;
  673. end;
  674.  
  675. procedure TMemoEditor.SetModified(Value: Boolean);
  676. begin
  677.   Editor.Modified := Value;
  678.   if Value then StatusBar.Panels[1].Text := SChanged
  679.   else StatusBar.Panels[1].Text := '';
  680. end;
  681.  
  682. procedure TMemoEditor.WMChangeCBChain(var Msg: TWMChangeCBChain);
  683. begin
  684.   if Msg.Remove = FClipboardOwner then FClipboardOwner := Msg.Next
  685.   else SendMessage(FClipboardOwner, WM_CHANGECBCHAIN, Msg.Remove, Msg.Next);
  686.   Msg.Result := 0;
  687. end;
  688.  
  689. procedure TMemoEditor.ClipboardChanged;
  690. var
  691.   I: Integer;
  692.   Format: Word;
  693.   E: Boolean;
  694. begin
  695.   // check to see if we can paste what's on the clipboard
  696.   E := False;
  697.   for I := 0 to Clipboard.FormatCount - 1 do
  698.   begin
  699.     Format := Clipboard.Formats[I];
  700.     if SendMessage(Editor.Handle, EM_CANPASTE, Format, 0) <> 0 then
  701.     begin
  702.       E := True;
  703.       Break;
  704.     end;
  705.   end;
  706.   PasteButton.Enabled := E;
  707.   EditPasteItem.Enabled := E;
  708. end;
  709.  
  710. procedure TMemoEditor.WMDrawClipboard(var Msg: TWMDrawClipboard);
  711. begin
  712.   SendMessage(FClipboardOwner, WM_DRAWCLIPBOARD, 0, 0);
  713.   Msg.Result := 0;
  714.   ClipboardChanged;
  715. end;
  716.  
  717. procedure TMemoEditor.FormDestroy(Sender: TObject);
  718. begin
  719.   // remove ourselves from the viewer chain
  720.   ChangeClipboardChain(Handle, FClipboardOwner);
  721.   Application.OnIdle := FOnIdle;
  722.   Application.OnHint := FOnHint;
  723.   if (Editor.Field <> nil) and (Editor.Field.DataSet.State <> dsBrowse) then
  724.      Editor.Field.DataSet.Cancel;
  725. end;
  726.  
  727. procedure TMemoEditor.EditorKeyDown(Sender: TObject; var Key: Word;
  728.   Shift: TShiftState);
  729. begin
  730.    if Key = vk_Insert then
  731.       if StatusBar.Panels[5].Text = SInsert then
  732.          StatusBar.Panels[5].Text := SOverWrite
  733.         else
  734.          StatusBar.Panels[5].Text := SInsert;
  735. end;
  736.  
  737. procedure TMemoEditor.EditFindTextClick(Sender: TObject);
  738. begin
  739.   FindDialog1.Execute;
  740. end;
  741.  
  742. procedure TMemoEditor.FindDialog1Find(Sender: TObject);
  743. var
  744.   FoundAt: LongInt;
  745.   StartPos, ToEnd: integer;
  746.   SearchType: TSearchTypes;
  747. begin
  748.   SearchType := [];
  749.   if frMatchCase in FindDialog1.Options then
  750.     Include(SearchType, stMatchCase);
  751.   if frWholeWord in FindDialog1.Options then
  752.     Include(SearchType, stWholeWord);
  753.   with Editor do
  754.   begin
  755.      if SelLength <> 0 then
  756.         StartPos := SelStart+SelLength
  757.        else
  758.         StartPos := 0;
  759.      ToEnd := Length(Text) - StartPos;
  760.      FoundAt := FindText(FindDialog1.FindText, StartPos, ToEnd, SearchType);
  761.      if FoundAt <> -1 then
  762.      begin
  763.        SetFocus;
  764.        SelStart := FoundAt;
  765.        SelLength := Length(FindDialog1.FindText);
  766.      end
  767.        else
  768.          MessageDlg(SValueNotFound, mtInformation, [mbOk], 0);
  769.   end;
  770. end;
  771.  
  772. procedure TMemoEditor.DataSourceDataChange(Sender: TObject; Field: TField);
  773. begin
  774.    FFieldName := '';
  775.    if Editor.Field <> nil then
  776.       FFieldName := Editor.Field.DisplayLabel;
  777.    if Length(FFieldName) > 0 then
  778.      Caption := Format('%s - %s', [FFieldName, Application.Title]);
  779. end;
  780.  
  781. end.
  782.