fpc/fcl/shedit/keys.inc
peter 4ace790492 * remove $Log
git-svn-id: trunk@231 -
2005-06-07 09:47:55 +00:00

491 lines
12 KiB
PHP

{
"SHEdit" - Text editor with syntax highlighting
Copyright (C) 1999-2000 by Sebastian Guenther (sg@freepascal.org)
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
// TSHTextEdit: Implementation of keyboard handling methods
function TSHTextEdit.AddKeyboardAction(AMethod: TKeyboardActionProc;ASelectionAction:TSelectionAction;ADescr: String): TKeyboardActionDescr;
begin
Result := TKeyboardActionDescr(KeyboardActions.Add);
Result.Descr := ADescr;
Result.Method := AMethod;
Result.SelectionAction := ASelectionAction;
end;
function TSHTextEdit.AddKeyboardAssignment(AKeyCode: Integer; AShiftState: TShiftState; AAction: TKeyboardActionDescr): TShortcut;
begin
Result := TShortcut(Shortcuts.Add);
Result.KeyCode := AKeyCode;
Result.ShiftState := AShiftState;
Result.Action := AAction;
end;
procedure TSHTextEdit.AddKeyDef(AMethod: TKeyboardActionProc; ASelectionAction:TSelectionAction; ADescr: String; AKeyCode: Integer; AShiftState: TShiftState);
begin
AddKeyboardAssignment(AKeyCode, AShiftState,AddKeyboardAction(AMethod, ASelectionAction, ADescr));
end;
procedure TSHTextEdit.ToggleOverwriteMode;
begin
OverwriteMode := not OverwriteMode; // *** specify signal for change
end;
procedure TSHTextEdit.AdjustCursorToRange;
begin
if FCursorY < FWidget.VertPos then begin
HideCursor;
FCursorY := FWidget.VertPos;
ShowCursor;
end else if FCursorY > FWidget.VertPos + FWidget.PageHeight then begin
HideCursor;
FCursorY := FWidget.VertPos + FWidget.PageHeight - 1;
ShowCursor;
end;
if FCursorX < FWidget.HorzPos then begin
HideCursor;
FCursorX := FWidget.HorzPos;
ShowCursor;
end else if FCursorX > FWidget.HorzPos + FWidget.PageWidth then begin
HideCursor;
FCursorX := FWidget.HorzPos + FWidget.PageWidth - 1;
ShowCursor;
end;
end;
procedure TSHTextEdit.AdjustRangeToCursor;
var
py : integer;
begin
if FCursorY < FWidget.VertPos then
FWidget.VertPos := FCursorY
else if FCursorY >= FWidget.VertPos + FWidget.PageHeight then begin
py := FCursorY - FWidget.PageHeight + 1;
if py < 0 then
FWidget.VertPos:=0
else
FWidget.VertPos:=py;
end;
if FCursorX < FWidget.HorzPos then
FWidget.HorzPos := FCursorX
else if FCursorX >= FWidget.HorzPos + FWidget.PageWidth then begin
py := FCursorX - FWidget.PageWidth + 1;
if py < 0 then
FWidget.HorzPos := 0
else
FWidget.HorzPos := py;
end;
end;
procedure TSHTextEdit.CursorUp;
begin
if FCursorY > 0 then
Dec(FCursorY);
end;
procedure TSHTextEdit.CursorDown;
begin
if FCursorY < FDoc.LineCount - 1 then
Inc(FCursorY);
end;
procedure TSHTextEdit.CursorLeft;
begin
Dec(FCursorX);
if FCursorX < 0 then
if FCursorY>0 then begin
Dec(FCursorY);
FCursorX := FDoc.LineLen[FCursorY];
end else
FCursorX := 0;
end;
procedure TSHTextEdit.CursorRight;
begin
Inc(FCursorX);
end;
procedure TSHTextEdit.CursorDocBegin;
begin
FCursorX := 0;
FCursorY := 0;
end;
procedure TSHTextEdit.CursorDocEnd;
begin
FCursorY := FDoc.LineCount-1;
FCursorX := FDoc.LineLen[FCursorY];
end;
procedure TSHTextEdit.CursorHome;
begin
FCursorX := 0;
AdjustRangeToCursor;
end;
procedure TSHTextEdit.CursorEnd;
begin
FCursorX := FDoc.LineLen[FCursorY];
AdjustRangeToCursor;
end;
procedure TSHTextEdit.CursorPageUp;
begin
Dec(FCursorY, FWidget.PageHeight);
if FCursorY < 0 then
FCursorY := 0;
end;
procedure TSHTextEdit.CursorPageDown;
begin
Inc(FCursorY, FWidget.PageHeight);
if FCursorY > FDoc.LineCount - 1 then
FCursorY := FDoc.LineCount - 1;
end;
procedure TSHTextEdit.EditDelLeft;
var
s: String;
begin
if FCursorX > 0 then begin
s := FDoc.LineText[FCursorY];
Dec(FCursorX);
AddUndoInfo(TUndoDelLeft.Create(s[FCursorX + 1]), True);
s := Copy(s, 1, FCursorX) + Copy(s, FCursorX + 2, Length(s));
FDoc.LineText[FCursorY] := s;
ChangeInLine(FCursorY);
end else if FCursorY > 0 then begin
FCursorX := FDoc.LineLen[FCursorY - 1];
FDoc.LineText[FCursorY - 1] := FDoc.LineText[FCursorY - 1] +
FDoc.LineText[FCursorY];
Dec(FCursorY);
FDoc.RemoveLine(FCursorY + 1);
AddUndoInfo(TUndoDelLeft.Create(#13), True);
end;
end;
procedure TSHTextEdit.EditDelRight;
var
s: String;
begin
if FCursorX < FDoc.LineLen[FCursorY] then begin
s := FDoc.LineText[FCursorY];
AddUndoInfo(TUndoDelRight.Create(s[FCursorX + 1]), True);
s := Copy(s, 1, FCursorX) + Copy(s, FCursorX + 2, Length(s));
FDoc.LineText[FCursorY] := s;
ChangeInLine(FCursorY);
end else if FCursorY < FDoc.LineCount - 1 then begin
FDoc.LineText[FCursorY] := FDoc.LineText[FCursorY] +
FDoc.LineText[FCursorY + 1];
FDoc.RemoveLine(FCursorY + 1);
AddUndoInfo(TUndoDelRight.Create(#13), True);
end;
end;
procedure TSHTextEdit.EditDelLine;
var
DeletedText: String;
begin
DeletedText := FDoc.LineText[FCursorY];
if FDoc.LineCount = 1 then
FDoc.LineText[FCursorY] := ''
else
FDoc.RemoveLine(FCursorY);
if FCursorY >= FDoc.LineCount then
FCursorY := FDoc.LineCount - 1;
FCursorX := 0;
AddUndoInfo(TUndoDelRight.Create(DeletedText + #13), True);
ChangeInLine(FCursorY);
end;
procedure TSHTextEdit.EditUndo;
var
info: TUndoInfo;
begin
if LastUndoInfo = nil then exit;
info := LastUndoInfo;
LastUndoInfo := LastRedoInfo;
info.DoUndo(Self);
LastRedoInfo := LastUndoInfo;
LastUndoInfo := info;
// Free undo info
if info.Prev <> nil then
info.Prev.Next := info.Next
else
FDoc.Modified := False;
LastUndoInfo := info.Prev;
info.Free;
end;
procedure TSHTextEdit.EditRedo;
var
info: TUndoInfo;
begin
if LastRedoInfo = nil then exit;
info := LastRedoInfo;
info.DoUndo(Self);
// Free redo info
if info.Prev <> nil then
info.Prev.Next := info.Next;
LastRedoInfo := info.Prev;
info.Free;
end;
procedure TSHTextEdit.ClipboardCut;
begin
WriteLn('ClipboardCut: Not implemented yet');
ClipboardCopy;
end;
procedure TSHTextEdit.ClipboardCopy;
var
cbtext: String;
y: Integer;
begin
if FSel.OStartY = FSel.OEndY then
cbtext := Copy(FDoc.LineText[FSel.OStartY],
FSel.OStartX + 1, FSel.OEndX - FSel.OStartX)
else begin
cbtext := Copy(FDoc.LineText[FSel.OStartY],
FSel.OStartX + 1, FDoc.LineLen[FSel.OStartY]) + #10;
for y := FSel.OStartY + 1 to FSel.OEndY - 1 do
cbtext := cbtext + FDoc.LineText[y] + #10;
cbtext := cbtext + Copy(FDoc.LineText[FSel.OEndY], 1, FSel.OEndX);
end;
FWidget.SetClipboard(cbtext);
end;
procedure TSHTextEdit.ClipboardPaste;
var
cbtext: String;
begin
cbtext := FWidget.GetClipboard;
ExecKeys(cbtext, True);
end;
procedure TSHTextEdit.KeyReturn; begin end;
function TSHTextEdit.ExecKey(Key: Char; BlockMode: Boolean): Boolean;
var
s, s2: String;
i: Integer;
begin
Result := True;
case Key of
#9: begin
s := FDoc.LineText[FCursorY];
s2 := ' ';
i := 1;
while ((FCursorX + i) mod 4) <> 0 do begin
s2 := s2 + ' ';
Inc(i);
end;
s := Copy(s, 1, FCursorX) + s2 + Copy(s, FCursorX + 1, Length(s));
FDoc.LineText[FCursorY] := s;
Inc(FCursorX, i);
AddUndoInfo(TUndoEdit.Create(i), True);
ChangeInLine(FCursorY);
end;
#13: begin
s := FDoc.LineText[FCursorY];
FDoc.LineText[FCursorY] := Copy(s, 1, FCursorX);
FDoc.InsertLine(FCursorY + 1, Copy(s, FCursorX + 1, Length(s)));
CursorX := 0;
Inc(FCursorY);
AddUndoInfo(TUndoEdit.Create, True);
if not BlockMode then KeyReturn;
end;
#32..#255:
begin
s := FDoc.LineText[FCursorY];
if FCursorX>=Length(s) then
s := s + Space(FCursorX-length(s)) + Key
else
if OverwriteMode then
s := Copy(s, 1, FCursorX) + Key + Copy(s, FCursorX + 2, Length(s))
else
s := Copy(s, 1, FCursorX) + Key + Copy(s, FCursorX + 1, Length(s));
FDoc.LineText[FCursorY] := s;
Inc(FCursorX);
AddUndoInfo(TUndoEdit.Create, True);
ChangeInLine(FCursorY);
end;
else Result := False;
end;
end;
procedure TSHTextEdit.ExecKeys(Keys: String; BlockMode: Boolean);
var
s, s2: String;
KeysPos, i: Integer;
Key: Char;
begin
if BlockMode then
AddUndoInfo(TUndoEdit.Create(0), False); // Initialize new undo block
KeysPos := 1;
while KeysPos <= Length(Keys) do begin
case Keys[KeysPos] of
#9: begin
s := FDoc.LineText[FCursorY];
s2 := ' ';
i := 1;
while ((FCursorX + i) mod 4) <> 0 do begin
s2 := s2 + ' ';
Inc(i);
end;
s := Copy(s, 1, FCursorX) + s2 + Copy(s, FCursorX + 1, Length(s));
FDoc.LineText[FCursorY] := s;
Inc(FCursorX, i);
AddUndoInfo(TUndoEdit.Create(i), True);
ChangeInLine(FCursorY);
Inc(KeysPos);
end;
#13, #10: begin
s := FDoc.LineText[FCursorY];
FDoc.LineText[FCursorY] := Copy(s, 1, FCursorX);
FDoc.InsertLine(FCursorY + 1, Copy(s, FCursorX + 1, Length(s)));
CursorX := 0;
Inc(FCursorY);
AddUndoInfo(TUndoEdit.Create, True);
if not BlockMode then KeyReturn;
Inc(KeysPos);
end;
#32..#255: begin
i := 0;
while (KeysPos <= Length(Keys)) and (Keys[KeysPos] >= #32) do begin
Key := Keys[KeysPos];
s := FDoc.LineText[FCursorY];
if FCursorX>=Length(s) then
s := s + Space(FCursorX-length(s)) + Key
else
s := Copy(s, 1, FCursorX) + Key + Copy(s, FCursorX + 1 + Ord(OverwriteMode), Length(s));
FDoc.LineText[FCursorY] := s;
Inc(FCursorX);
Inc(i);
Inc(KeysPos);
end;
AddUndoInfo(TUndoEdit.Create(i), True);
ChangeInLine(FCursorY);
end;
else Inc(KeysPos);
end;
end;
end;
procedure TSHTextEdit.MultiDelLeft(count: Integer);
var
s: String;
begin
while count > 0 do begin
if FCursorX > 0 then begin
while (FCursorX > 0) and (count > 0) do begin
s := FDoc.LineText[FCursorY];
Dec(FCursorX);
AddUndoInfo(TUndoDelLeft.Create(s[FCursorX + 1]), True);
s := Copy(s, 1, FCursorX) + Copy(s, FCursorX + 2, Length(s));
FDoc.LineText[FCursorY] := s;
Dec(count);
end;
ChangeInLine(FCursorY);
end else if FCursorY > 0 then begin
FCursorX := FDoc.LineLen[FCursorY - 1];
FDoc.LineText[FCursorY - 1] := FDoc.LineText[FCursorY - 1] +
FDoc.LineText[FCursorY];
Dec(FCursorY);
FDoc.RemoveLine(FCursorY + 1);
AddUndoInfo(TUndoDelLeft.Create(#13), True);
Dec(count);
end else break;
end;
end;
function TSHTextEdit.KeyPressed(KeyCode: LongWord; ShiftState: TShiftState): Boolean;
var
i: Integer;
shortcut: TShortcut;
ShortcutFound: Boolean;
begin
// WriteLn('TSHTextEdit: Key pressed: ', KeyCode);
LastCursorX := FCursorX;
LastCursorY := FCursorY;
StartSelectionChange;
// Check for keyboard shortcuts
ShortcutFound := False;
for i := 0 to Shortcuts.Count - 1 do begin
shortcut := TShortcut(Shortcuts.Items[i]);
if (KeyCode = shortcut.KeyCode) and
(ShiftState * [ssShift, ssCtrl, ssAlt] = shortcut.ShiftState) then begin
ShortcutFound := True;
break;
end;
end;
Result := True;
if ShortcutFound then begin
// WriteLn(shortcut.Action.Descr);
shortcut.Action.Method; // Execute associated action
// Handle the selection extending
case shortcut.Action.SelectionAction of
selNothing: ;
selExtend: begin
if not FSel.IsValid then begin
FSel.StartX:=LastCursorX;
FSel.StartY:=LastCursorY;
end;
FSel.EndX:=FCursorX;
FSel.EndY:=FCursorY;
end;
selClear:
FSel.Clear;
end;
end else
if (KeyCode <= 255) and (ShiftState * [ssCtrl, ssAlt] = []) then
ExecKey(Chr(KeyCode), False)
else
Result := False; // Key has not been processed
EndSelectionChange;
AdjustRangeToCursor;
end;