keys.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. {
  2. $Id$
  3. "SHEdit" - Text editor with syntax highlighting
  4. Copyright (C) 1999-2000 by Sebastian Guenther ([email protected])
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. }
  11. // TSHTextEdit: Implementation of keyboard handling methods
  12. function TSHTextEdit.AddKeyboardAction(AMethod: TKeyboardActionProc;ASelectionAction:TSelectionAction;ADescr: String): TKeyboardActionDescr;
  13. begin
  14. Result := TKeyboardActionDescr(KeyboardActions.Add);
  15. Result.Descr := ADescr;
  16. Result.Method := AMethod;
  17. Result.SelectionAction := ASelectionAction;
  18. end;
  19. function TSHTextEdit.AddKeyboardAssignment(AKeyCode: Integer; AShiftState: TShiftState; AAction: TKeyboardActionDescr): TShortcut;
  20. begin
  21. Result := TShortcut(Shortcuts.Add);
  22. Result.KeyCode := AKeyCode;
  23. Result.ShiftState := AShiftState;
  24. Result.Action := AAction;
  25. end;
  26. procedure TSHTextEdit.AddKeyDef(AMethod: TKeyboardActionProc; ASelectionAction:TSelectionAction; ADescr: String; AKeyCode: Integer; AShiftState: TShiftState);
  27. begin
  28. AddKeyboardAssignment(AKeyCode, AShiftState,AddKeyboardAction(AMethod, ASelectionAction, ADescr));
  29. end;
  30. procedure TSHTextEdit.ToggleOverwriteMode;
  31. begin
  32. OverwriteMode := not OverwriteMode; // *** specify signal for change
  33. end;
  34. procedure TSHTextEdit.AdjustCursorToRange;
  35. begin
  36. if FCursorY < FWidget.VertPos then begin
  37. HideCursor;
  38. FCursorY := FWidget.VertPos;
  39. ShowCursor;
  40. end else if FCursorY > FWidget.VertPos + FWidget.PageHeight then begin
  41. HideCursor;
  42. FCursorY := FWidget.VertPos + FWidget.PageHeight - 1;
  43. ShowCursor;
  44. end;
  45. if FCursorX < FWidget.HorzPos then begin
  46. HideCursor;
  47. FCursorX := FWidget.HorzPos;
  48. ShowCursor;
  49. end else if FCursorX > FWidget.HorzPos + FWidget.PageWidth then begin
  50. HideCursor;
  51. FCursorX := FWidget.HorzPos + FWidget.PageWidth - 1;
  52. ShowCursor;
  53. end;
  54. end;
  55. procedure TSHTextEdit.AdjustRangeToCursor;
  56. var
  57. py : integer;
  58. begin
  59. if FCursorY < FWidget.VertPos then
  60. FWidget.VertPos := FCursorY
  61. else if FCursorY >= FWidget.VertPos + FWidget.PageHeight then begin
  62. py := FCursorY - FWidget.PageHeight + 1;
  63. if py < 0 then
  64. FWidget.VertPos:=0
  65. else
  66. FWidget.VertPos:=py;
  67. end;
  68. if FCursorX < FWidget.HorzPos then
  69. FWidget.HorzPos := FCursorX
  70. else if FCursorX >= FWidget.HorzPos + FWidget.PageWidth then begin
  71. py := FCursorX - FWidget.PageWidth + 1;
  72. if py < 0 then
  73. FWidget.HorzPos := 0
  74. else
  75. FWidget.HorzPos := py;
  76. end;
  77. end;
  78. procedure TSHTextEdit.CursorUp;
  79. begin
  80. if FCursorY > 0 then
  81. Dec(FCursorY);
  82. end;
  83. procedure TSHTextEdit.CursorDown;
  84. begin
  85. if FCursorY < FDoc.LineCount - 1 then
  86. Inc(FCursorY);
  87. end;
  88. procedure TSHTextEdit.CursorLeft;
  89. begin
  90. Dec(FCursorX);
  91. if FCursorX < 0 then
  92. if FCursorY>0 then begin
  93. Dec(FCursorY);
  94. FCursorX := FDoc.LineLen[FCursorY];
  95. end else
  96. FCursorX := 0;
  97. end;
  98. procedure TSHTextEdit.CursorRight;
  99. begin
  100. Inc(FCursorX);
  101. end;
  102. procedure TSHTextEdit.CursorDocBegin;
  103. begin
  104. FCursorX := 0;
  105. FCursorY := 0;
  106. end;
  107. procedure TSHTextEdit.CursorDocEnd;
  108. begin
  109. FCursorY := FDoc.LineCount-1;
  110. FCursorX := FDoc.LineLen[FCursorY];
  111. end;
  112. procedure TSHTextEdit.CursorHome;
  113. begin
  114. FCursorX := 0;
  115. AdjustRangeToCursor;
  116. end;
  117. procedure TSHTextEdit.CursorEnd;
  118. begin
  119. FCursorX := FDoc.LineLen[FCursorY];
  120. AdjustRangeToCursor;
  121. end;
  122. procedure TSHTextEdit.CursorPageUp;
  123. begin
  124. Dec(FCursorY, FWidget.PageHeight);
  125. if FCursorY < 0 then
  126. FCursorY := 0;
  127. end;
  128. procedure TSHTextEdit.CursorPageDown;
  129. begin
  130. Inc(FCursorY, FWidget.PageHeight);
  131. if FCursorY > FDoc.LineCount - 1 then
  132. FCursorY := FDoc.LineCount - 1;
  133. end;
  134. procedure TSHTextEdit.EditDelLeft;
  135. var
  136. s: String;
  137. begin
  138. if FCursorX > 0 then begin
  139. s := FDoc.LineText[FCursorY];
  140. Dec(FCursorX);
  141. AddUndoInfo(TUndoDelLeft.Create(s[FCursorX + 1]), True);
  142. s := Copy(s, 1, FCursorX) + Copy(s, FCursorX + 2, Length(s));
  143. FDoc.LineText[FCursorY] := s;
  144. ChangeInLine(FCursorY);
  145. end else if FCursorY > 0 then begin
  146. FCursorX := FDoc.LineLen[FCursorY - 1];
  147. FDoc.LineText[FCursorY - 1] := FDoc.LineText[FCursorY - 1] +
  148. FDoc.LineText[FCursorY];
  149. Dec(FCursorY);
  150. FDoc.RemoveLine(FCursorY + 1);
  151. AddUndoInfo(TUndoDelLeft.Create(#13), True);
  152. end;
  153. end;
  154. procedure TSHTextEdit.EditDelRight;
  155. var
  156. s: String;
  157. begin
  158. if FCursorX < FDoc.LineLen[FCursorY] then begin
  159. s := FDoc.LineText[FCursorY];
  160. AddUndoInfo(TUndoDelRight.Create(s[FCursorX + 1]), True);
  161. s := Copy(s, 1, FCursorX) + Copy(s, FCursorX + 2, Length(s));
  162. FDoc.LineText[FCursorY] := s;
  163. ChangeInLine(FCursorY);
  164. end else if FCursorY < FDoc.LineCount - 1 then begin
  165. FDoc.LineText[FCursorY] := FDoc.LineText[FCursorY] +
  166. FDoc.LineText[FCursorY + 1];
  167. FDoc.RemoveLine(FCursorY + 1);
  168. AddUndoInfo(TUndoDelRight.Create(#13), True);
  169. end;
  170. end;
  171. procedure TSHTextEdit.EditDelLine;
  172. var
  173. DeletedText: String;
  174. begin
  175. DeletedText := FDoc.LineText[FCursorY];
  176. if FDoc.LineCount = 1 then
  177. FDoc.LineText[FCursorY] := ''
  178. else
  179. FDoc.RemoveLine(FCursorY);
  180. if FCursorY >= FDoc.LineCount then
  181. FCursorY := FDoc.LineCount - 1;
  182. FCursorX := 0;
  183. AddUndoInfo(TUndoDelRight.Create(DeletedText + #13), True);
  184. ChangeInLine(FCursorY);
  185. end;
  186. procedure TSHTextEdit.EditUndo;
  187. var
  188. info: TUndoInfo;
  189. begin
  190. if LastUndoInfo = nil then exit;
  191. info := LastUndoInfo;
  192. LastUndoInfo := LastRedoInfo;
  193. info.DoUndo(Self);
  194. LastRedoInfo := LastUndoInfo;
  195. LastUndoInfo := info;
  196. // Free undo info
  197. if info.Prev <> nil then
  198. info.Prev.Next := info.Next
  199. else
  200. FDoc.Modified := False;
  201. LastUndoInfo := info.Prev;
  202. info.Free;
  203. end;
  204. procedure TSHTextEdit.EditRedo;
  205. var
  206. info: TUndoInfo;
  207. begin
  208. if LastRedoInfo = nil then exit;
  209. info := LastRedoInfo;
  210. info.DoUndo(Self);
  211. // Free redo info
  212. if info.Prev <> nil then
  213. info.Prev.Next := info.Next;
  214. LastRedoInfo := info.Prev;
  215. info.Free;
  216. end;
  217. procedure TSHTextEdit.ClipboardCut;
  218. begin
  219. WriteLn('ClipboardCut: Not implemented yet');
  220. ClipboardCopy;
  221. end;
  222. procedure TSHTextEdit.ClipboardCopy;
  223. var
  224. cbtext: String;
  225. y: Integer;
  226. begin
  227. if FSel.OStartY = FSel.OEndY then
  228. cbtext := Copy(FDoc.LineText[FSel.OStartY],
  229. FSel.OStartX + 1, FSel.OEndX - FSel.OStartX)
  230. else begin
  231. cbtext := Copy(FDoc.LineText[FSel.OStartY],
  232. FSel.OStartX + 1, FDoc.LineLen[FSel.OStartY]) + #10;
  233. for y := FSel.OStartY + 1 to FSel.OEndY - 1 do
  234. cbtext := cbtext + FDoc.LineText[y] + #10;
  235. cbtext := cbtext + Copy(FDoc.LineText[FSel.OEndY], 1, FSel.OEndX);
  236. end;
  237. FWidget.SetClipboard(cbtext);
  238. end;
  239. procedure TSHTextEdit.ClipboardPaste;
  240. var
  241. cbtext: String;
  242. begin
  243. cbtext := FWidget.GetClipboard;
  244. ExecKeys(cbtext, True);
  245. end;
  246. procedure TSHTextEdit.KeyReturn; begin end;
  247. function TSHTextEdit.ExecKey(Key: Char; BlockMode: Boolean): Boolean;
  248. var
  249. s, s2: String;
  250. i: Integer;
  251. begin
  252. Result := True;
  253. case Key of
  254. #9: begin
  255. s := FDoc.LineText[FCursorY];
  256. s2 := ' ';
  257. i := 1;
  258. while ((FCursorX + i) mod 4) <> 0 do begin
  259. s2 := s2 + ' ';
  260. Inc(i);
  261. end;
  262. s := Copy(s, 1, FCursorX) + s2 + Copy(s, FCursorX + 1, Length(s));
  263. FDoc.LineText[FCursorY] := s;
  264. Inc(FCursorX, i);
  265. AddUndoInfo(TUndoEdit.Create(i), True);
  266. ChangeInLine(FCursorY);
  267. end;
  268. #13: begin
  269. s := FDoc.LineText[FCursorY];
  270. FDoc.LineText[FCursorY] := Copy(s, 1, FCursorX);
  271. FDoc.InsertLine(FCursorY + 1, Copy(s, FCursorX + 1, Length(s)));
  272. CursorX := 0;
  273. Inc(FCursorY);
  274. AddUndoInfo(TUndoEdit.Create, True);
  275. if not BlockMode then KeyReturn;
  276. end;
  277. #32..#255:
  278. begin
  279. s := FDoc.LineText[FCursorY];
  280. if FCursorX>=Length(s) then
  281. s := s + Space(FCursorX-length(s)) + Key
  282. else
  283. if OverwriteMode then
  284. s := Copy(s, 1, FCursorX) + Key + Copy(s, FCursorX + 2, Length(s))
  285. else
  286. s := Copy(s, 1, FCursorX) + Key + Copy(s, FCursorX + 1, Length(s));
  287. FDoc.LineText[FCursorY] := s;
  288. Inc(FCursorX);
  289. AddUndoInfo(TUndoEdit.Create, True);
  290. ChangeInLine(FCursorY);
  291. end;
  292. else Result := False;
  293. end;
  294. end;
  295. procedure TSHTextEdit.ExecKeys(Keys: String; BlockMode: Boolean);
  296. var
  297. s, s2: String;
  298. KeysPos, i: Integer;
  299. Key: Char;
  300. begin
  301. if BlockMode then
  302. AddUndoInfo(TUndoEdit.Create(0), False); // Initialize new undo block
  303. KeysPos := 1;
  304. while KeysPos <= Length(Keys) do begin
  305. case Keys[KeysPos] of
  306. #9: begin
  307. s := FDoc.LineText[FCursorY];
  308. s2 := ' ';
  309. i := 1;
  310. while ((FCursorX + i) mod 4) <> 0 do begin
  311. s2 := s2 + ' ';
  312. Inc(i);
  313. end;
  314. s := Copy(s, 1, FCursorX) + s2 + Copy(s, FCursorX + 1, Length(s));
  315. FDoc.LineText[FCursorY] := s;
  316. Inc(FCursorX, i);
  317. AddUndoInfo(TUndoEdit.Create(i), True);
  318. ChangeInLine(FCursorY);
  319. Inc(KeysPos);
  320. end;
  321. #13, #10: begin
  322. s := FDoc.LineText[FCursorY];
  323. FDoc.LineText[FCursorY] := Copy(s, 1, FCursorX);
  324. FDoc.InsertLine(FCursorY + 1, Copy(s, FCursorX + 1, Length(s)));
  325. CursorX := 0;
  326. Inc(FCursorY);
  327. AddUndoInfo(TUndoEdit.Create, True);
  328. if not BlockMode then KeyReturn;
  329. Inc(KeysPos);
  330. end;
  331. #32..#255: begin
  332. i := 0;
  333. while (KeysPos <= Length(Keys)) and (Keys[KeysPos] >= #32) do begin
  334. Key := Keys[KeysPos];
  335. s := FDoc.LineText[FCursorY];
  336. if FCursorX>=Length(s) then
  337. s := s + Space(FCursorX-length(s)) + Key
  338. else
  339. s := Copy(s, 1, FCursorX) + Key + Copy(s, FCursorX + 1 + Ord(OverwriteMode), Length(s));
  340. FDoc.LineText[FCursorY] := s;
  341. Inc(FCursorX);
  342. Inc(i);
  343. Inc(KeysPos);
  344. end;
  345. AddUndoInfo(TUndoEdit.Create(i), True);
  346. ChangeInLine(FCursorY);
  347. end;
  348. else Inc(KeysPos);
  349. end;
  350. end;
  351. end;
  352. procedure TSHTextEdit.MultiDelLeft(count: Integer);
  353. var
  354. s: String;
  355. begin
  356. while count > 0 do begin
  357. if FCursorX > 0 then begin
  358. while (FCursorX > 0) and (count > 0) do begin
  359. s := FDoc.LineText[FCursorY];
  360. Dec(FCursorX);
  361. AddUndoInfo(TUndoDelLeft.Create(s[FCursorX + 1]), True);
  362. s := Copy(s, 1, FCursorX) + Copy(s, FCursorX + 2, Length(s));
  363. FDoc.LineText[FCursorY] := s;
  364. Dec(count);
  365. end;
  366. ChangeInLine(FCursorY);
  367. end else if FCursorY > 0 then begin
  368. FCursorX := FDoc.LineLen[FCursorY - 1];
  369. FDoc.LineText[FCursorY - 1] := FDoc.LineText[FCursorY - 1] +
  370. FDoc.LineText[FCursorY];
  371. Dec(FCursorY);
  372. FDoc.RemoveLine(FCursorY + 1);
  373. AddUndoInfo(TUndoDelLeft.Create(#13), True);
  374. Dec(count);
  375. end else break;
  376. end;
  377. end;
  378. function TSHTextEdit.KeyPressed(KeyCode: LongWord; ShiftState: TShiftState): Boolean;
  379. var
  380. i: Integer;
  381. shortcut: TShortcut;
  382. ShortcutFound: Boolean;
  383. begin
  384. // WriteLn('TSHTextEdit: Key pressed: ', KeyCode);
  385. LastCursorX := FCursorX;
  386. LastCursorY := FCursorY;
  387. StartSelectionChange;
  388. // Check for keyboard shortcuts
  389. ShortcutFound := False;
  390. for i := 0 to Shortcuts.Count - 1 do begin
  391. shortcut := TShortcut(Shortcuts.Items[i]);
  392. if (KeyCode = shortcut.KeyCode) and
  393. (ShiftState * [ssShift, ssCtrl, ssAlt] = shortcut.ShiftState) then begin
  394. ShortcutFound := True;
  395. break;
  396. end;
  397. end;
  398. Result := True;
  399. if ShortcutFound then begin
  400. // WriteLn(shortcut.Action.Descr);
  401. shortcut.Action.Method; // Execute associated action
  402. // Handle the selection extending
  403. case shortcut.Action.SelectionAction of
  404. selNothing: ;
  405. selExtend: begin
  406. if not FSel.IsValid then begin
  407. FSel.StartX:=LastCursorX;
  408. FSel.StartY:=LastCursorY;
  409. end;
  410. FSel.EndX:=FCursorX;
  411. FSel.EndY:=FCursorY;
  412. end;
  413. selClear:
  414. FSel.Clear;
  415. end;
  416. end else
  417. if (KeyCode <= 255) and (ShiftState * [ssCtrl, ssAlt] = []) then
  418. ExecKey(Chr(KeyCode), False)
  419. else
  420. Result := False; // Key has not been processed
  421. EndSelectionChange;
  422. AdjustRangeToCursor;
  423. end;
  424. {
  425. $Log$
  426. Revision 1.2 2000-07-13 11:33:02 michael
  427. + removed logs
  428. }