浏览代码

* first things for selection
* Better Adjusting of range/cursor

peter 26 年之前
父节点
当前提交
ddbb8aea45
共有 4 个文件被更改,包括 341 次插入417 次删除
  1. 83 55
      fcl/shedit/drawing.inc
  2. 59 37
      fcl/shedit/gtkshedit.pp
  3. 185 307
      fcl/shedit/keys.inc
  4. 14 18
      fcl/shedit/shedit.pp

+ 83 - 55
fcl/shedit/drawing.inc

@@ -140,6 +140,8 @@ begin
   end;
 
 
+//  if FSel.IsValid then writeln('Selection: ',FSel.OStartX,',',FSel.OStartY,'-',FSel.OEndX,',',FSel.OEndY);
+
   while (LineNumber < FDoc.LineCount) and (py <= y2) do begin
     i := 0;
 
@@ -152,64 +154,86 @@ begin
 
     // Handle current selection
     if FSel.IsValid then
-      if (LineNumber > FSel.OStartY) and (LineNumber < FSel.OEndY) then begin
-        s[0] := LF_Escape;
-        s[1] := Chr(shSelected);
-        StrCopy(@s[2], OrigStr);
-      end else if OrigStr[0] = #0 then begin
-        if LineNumber = FSel.OStartY then begin
-          s[0] := LF_Escape;
-          s[1] := Chr(shSelected);
-          s[2] := #0;
-        end;
-      end else if (LineNumber = FSel.OStartY) or
-        (LineNumber = FSel.OEndY) then begin
-        s2 := StrNew(s);
-        spos := 0;
-        i := 0;
-        x := 0;
-        if LineNumber > FSel.OStartY then begin
+     begin
+       if (LineNumber > FSel.OStartY) and (LineNumber < FSel.OEndY) then
+        begin
           s[0] := LF_Escape;
           s[1] := Chr(shSelected);
-          InSel := True;
-          spos := 2;
-        end else
-          InSel := False;
-        LastCol := Chr(shDefault);
-        while True do begin
-          if s2[i] = LF_Escape then begin
-            LastCol := s2[i + 1];
-            if not InSel then begin
-              s[spos] := LF_Escape;
-              s[spos + 1] := LastCol;
-              Inc(spos, 2);
+          StrCopy(@s[2], OrigStr);
+        end
+       else
+        if OrigStr[0] = #0 then
+         begin
+           if LineNumber = FSel.OStartY then
+            begin
+              s[0] := LF_Escape;
+              s[1] := Chr(shSelected);
+              s[2] := #0;
             end;
-            Inc(i, 2);
-          end else begin
-            if InSel then begin
-              if (LineNumber = FSel.OEndY) and (x = FSel.OEndX) then begin
-                s[spos] := LF_Escape;
-                s[spos + 1] := LastCol;
-                Inc(spos, 2);
-                InSel := False;
-              end;
-            end else
-              if (LineNumber = FSel.OStartY) and (x = FSel.OStartX) then begin
-                s[spos] := LF_Escape;
-                s[spos + 1] := Chr(shSelected);
-                Inc(spos, 2);
-                InSel := True;
-              end;
-            if s2[i] = #0 then break;    // only exit of 'while' loop!
-            s[spos] := s2[i];
-            Inc(spos);
-            Inc(i);
-            Inc(x);
+         end
+        else
+         if (LineNumber = FSel.OStartY) or
+            (LineNumber = FSel.OEndY) then
+          begin
+            s2 := StrNew(s);
+            spos := 0;
+            i := 0;
+            x := 0;
+            if LineNumber > FSel.OStartY then
+             begin
+               s[0] := LF_Escape;
+               s[1] := Chr(shSelected);
+               InSel := True;
+               spos := 2;
+             end
+            else
+             InSel := False;
+            LastCol := Chr(shDefault);
+            while True do
+             begin
+               if s2[i] = LF_Escape then
+                begin
+                  LastCol := s2[i + 1];
+                  if not InSel then
+                   begin
+                     s[spos] := LF_Escape;
+                     s[spos + 1] := LastCol;
+                     Inc(spos, 2);
+                   end;
+                  Inc(i, 2);
+                end
+               else
+                begin
+                  if InSel then
+                   begin
+                     if (LineNumber = FSel.OEndY) and (x = FSel.OEndX) then
+                      begin
+                        s[spos] := LF_Escape;
+                        s[spos + 1] := LastCol;
+                        Inc(spos, 2);
+                        InSel := False;
+                      end;
+                   end
+                  else
+                   if (LineNumber = FSel.OStartY) and (x = FSel.OStartX) then
+                    begin
+                      s[spos] := LF_Escape;
+                      s[spos + 1] := Chr(shSelected);
+                      Inc(spos, 2);
+                      InSel := True;
+                    end;
+                  if s2[i] = #0 then
+                   break;    // only exit of 'while' loop!
+                  s[spos] := s2[i];
+                  Inc(spos);
+                  Inc(i);
+                  Inc(x);
+                end;
+             end;
+            s[spos] := #0;
+            StrDispose(s2);
           end;
-        end;
-        s[spos] := #0;
-        StrDispose(s2);
-      end;
+     end;
 
     Renderer.DrawTextLine(x1, x2, py, s);
 
@@ -224,7 +248,11 @@ end;
 
 {
   $Log$
-  Revision 1.2  1999-12-08 00:42:54  sg
+  Revision 1.3  1999-12-10 15:01:02  peter
+    * first things for selection
+    * Better Adjusting of range/cursor
+
+  Revision 1.2  1999/12/08 00:42:54  sg
   * The cursor should be displayed correctly now
 
   Revision 1.1  1999/10/29 15:59:04  peter

+ 59 - 37
fcl/shedit/gtkshedit.pp

@@ -88,6 +88,7 @@ type
 
     // ISHRenderer Implemenation:
 
+    procedure InvalidateRect(x1, y1, x2, y2: Integer); override;
     procedure InvalidateLines(y1, y2: Integer); override;
 
     // Drawing
@@ -128,6 +129,7 @@ type
 
 implementation
 
+
 {*****************************************************************************
                               GTK/GDK Callbacks
 *****************************************************************************}
@@ -144,16 +146,18 @@ begin
   x2:=(x2+edit.CharW-1) div edit.CharW;
   y1 := event^.area.y div edit.CharH;
   y2 := (event^.area.y + event^.area.height - 1) div edit.CharH;
-  WriteLn(Format('Expose(%d/%d - %d/%d) for %s', [x1, y1, x2, y2, edit.ClassName]));
+//  WriteLn(Format('Expose(%d/%d - %d/%d) for %s', [x1, y1, x2, y2, edit.ClassName]));
 
   edit.GdkWnd := edit.PaintBox^.window;
   edit.GC := gdk_gc_new(edit.GdkWnd);
   gdk_gc_copy(edit.GC, PGtkStyle(edit.PaintBox^.thestyle)^.
     fg_gc[edit.PaintBox^.state]);
 
+  edit.Edit.AdjustCursorToRange;
   edit.Edit.DrawContent(x1, y1, x2, y2);
 end;
 
+
 function TGtkSHEdit_KeyPressed(GtkWidget: PGtkWidget; Event: PGdkEventKey; edit: TGtkSHEdit): Integer; cdecl;
 var
   KeyState,
@@ -184,7 +188,7 @@ begin
   end;
   KeyState:=Event^.State;
 
-  WriteLn('KeyCode ', KeyCode,'   keystate ',KeyState);
+//  WriteLn('KeyCode ', KeyCode,'   keystate ',KeyState);
 
   // Calculate the Key modifiers (shiftstate)
   KeyMods := [];
@@ -201,10 +205,9 @@ begin
   if (KeyState and $2000) <> 0 then KeyMods := KeyMods + [ssAltGr];
 
   edit.Edit.KeyPressed(KeyCode,KeyMods);
-
-  writeln(edit.Edit.Selection.StartX);
 end;
 
+
 function TGtkSHEdit_ButtonPressEvent(GtkWidget: PGtkWidget; event: PGdkEventButton ;  edit: TGtkSHEdit): Integer; cdecl;
 begin
   Writeln('button press');
@@ -214,7 +217,7 @@ end;
 
 function TGtkShEdit_FocusInEvent(GtkWidget: PGtkWidget; event: PGdkEventFocus; edit: TGtkSHEdit): Integer; cdecl;
 begin
-  Writeln('focus in');
+//  Writeln('focus in');
   edit.Edit.FocusIn;
   result:=1;
 end;
@@ -222,7 +225,7 @@ end;
 
 function TGtkShEdit_FocusOutEvent(GtkWidget: PGtkWidget; event: PGdkEventFocus; edit: TGtkSHEdit): Integer; cdecl;
 begin
-  Writeln('focus out');
+//  Writeln('focus out');
   edit.Edit.FocusOut;
   result:=1;
 end;
@@ -283,6 +286,7 @@ begin
   gtk_widget_show(Widget);
 end;
 
+
 procedure TGtkSHEdit.SetEdit(AEdit: TSHTextEdit);
 begin
   Edit := AEdit;
@@ -290,34 +294,34 @@ begin
   Edit.shDefault    := AddSHStyle('Default',    colBlack, colWhite, fsNormal);
   Edit.shSelected   := AddSHStyle('Selected',   colWhite, colBlue, fsNormal);
 { Install keys }
-  Edit.AddKeyDef(@Edit.CursorUp, 'Cursor up', GDK_Up, []);
-  Edit.AddKeyDef(@Edit.CursorDown, 'Cursor down', GDK_Down, []);
-  Edit.AddKeyDef(@Edit.CursorLeft, 'Cursor left', GDK_Left, []);
-  Edit.AddKeyDef(@Edit.CursorRight, 'Cursor right', GDK_Right, []);
-  Edit.AddKeyDef(@Edit.CursorHome, 'Cursor Home', GDK_Home, []);
-  Edit.AddKeyDef(@Edit.CursorEnd, 'Cursor Home', GDK_End, []);
-  Edit.AddKeyDef(@Edit.CursorPageUp, 'Cursor PageUp', GDK_Page_Up, []);
-  Edit.AddKeyDef(@Edit.CursorPageDown, 'Cursor PageDown', GDK_Page_Down, []);
-  Edit.AddKeyDef(@Edit.CursorDocBegin, 'Cursor Document Start', GDK_Page_Up, [ssCtrl]);
-  Edit.AddKeyDef(@Edit.CursorDocEnd, 'Cursor Document End', GDK_Page_Down, [ssCtrl]);
-
-  Edit.AddKeyDef(@Edit.SelectionUp, 'Selection up', GDK_Up, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionDown, 'Selection down', GDK_Down, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionLeft, 'Selection left', GDK_Left, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionRight, 'Selection right', GDK_Right, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionHome, 'Selection Home', GDK_Home, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionEnd, 'Selection Home', GDK_End, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionPageUp, 'Selection PageUp', GDK_Page_Up, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionPageDown, 'Selection PageDown', GDK_Page_Down, [ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionDocBegin, 'Selection Document Start', GDK_Page_Up, [ssCtrl,ssShift]);
-  Edit.AddKeyDef(@Edit.SelectionDocEnd, 'Selection Document End', GDK_Page_Down, [ssCtrl,ssShift]);
-
-  Edit.AddKeyDef(@Edit.ToggleOverwriteMode, 'Toggle overwrite mode', GDK_Insert, []);
-  Edit.AddKeyDef(@Edit.EditDelLeft, 'Delete char left of cursor', GDK_Backspace, []);
-  Edit.AddKeyDef(@Edit.EditDelRight, 'Delete char right of cursor', GDK_Delete, []);
-  Edit.AddKeyDef(@Edit.EditDelLine, 'Delete current line', Ord('Y'), [ssCtrl]);
-  Edit.AddKeyDef(@Edit.EditUndo, 'Undo last action', GDK_Backspace, [ssAlt]);
-  Edit.AddKeyDef(@Edit.EditRedo, 'Redo last undone action', GDK_Backspace, [ssShift, ssAlt]);
+  Edit.AddKeyDef(@Edit.CursorUp, selClear, 'Cursor up', GDK_Up, []);
+  Edit.AddKeyDef(@Edit.CursorDown, selClear, 'Cursor down', GDK_Down, []);
+  Edit.AddKeyDef(@Edit.CursorLeft, selClear, 'Cursor left', GDK_Left, []);
+  Edit.AddKeyDef(@Edit.CursorRight, selClear, 'Cursor right', GDK_Right, []);
+  Edit.AddKeyDef(@Edit.CursorHome, selClear, 'Cursor Home', GDK_Home, []);
+  Edit.AddKeyDef(@Edit.CursorEnd, selClear, 'Cursor Home', GDK_End, []);
+  Edit.AddKeyDef(@Edit.CursorPageUp, selClear, 'Cursor PageUp', GDK_Page_Up, []);
+  Edit.AddKeyDef(@Edit.CursorPageDown, selClear, 'Cursor PageDown', GDK_Page_Down, []);
+  Edit.AddKeyDef(@Edit.CursorDocBegin, selClear, 'Cursor Document Start', GDK_Page_Up, [ssCtrl]);
+  Edit.AddKeyDef(@Edit.CursorDocEnd, selClear, 'Cursor Document End', GDK_Page_Down, [ssCtrl]);
+
+  Edit.AddKeyDef(@Edit.CursorUp, selExtend, 'Selection up', GDK_Up, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorDown, selExtend, 'Selection down', GDK_Down, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorLeft, selExtend, 'Selection left', GDK_Left, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorRight, selExtend, 'Selection right', GDK_Right, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorHome, selExtend, 'Selection Home', GDK_Home, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorEnd, selExtend, 'Selection Home', GDK_End, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorPageUp, selExtend, 'Selection PageUp', GDK_Page_Up, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorPageDown, selExtend, 'Selection PageDown', GDK_Page_Down, [ssShift]);
+  Edit.AddKeyDef(@Edit.CursorDocBegin, selExtend, 'Selection Document Start', GDK_Page_Up, [ssCtrl,ssShift]);
+  Edit.AddKeyDef(@Edit.CursorDocEnd, selExtend, 'Selection Document End', GDK_Page_Down, [ssCtrl,ssShift]);
+
+  Edit.AddKeyDef(@Edit.ToggleOverwriteMode, selNothing, 'Toggle overwrite mode', GDK_Insert, []);
+  Edit.AddKeyDef(@Edit.EditDelLeft, selClear, 'Delete char left of cursor', GDK_Backspace, []);
+  Edit.AddKeyDef(@Edit.EditDelRight, selClear, 'Delete char right of cursor', GDK_Delete, []);
+  Edit.AddKeyDef(@Edit.EditDelLine, selClear, 'Delete current line', Ord('Y'), [ssCtrl]);
+  Edit.AddKeyDef(@Edit.EditUndo, selClear, 'Undo last action', GDK_Backspace, [ssAlt]);
+  Edit.AddKeyDef(@Edit.EditRedo, selClear, 'Redo last undone action', GDK_Backspace, [ssShift, ssAlt]);
 end;
 
 
@@ -332,6 +336,7 @@ begin
   Result := SHStyleCount;
 end;
 
+
 procedure TGtkSHEdit.SetGCColor(AColor: LongWord);
 var
   c: TGdkColor;
@@ -347,6 +352,7 @@ begin
   end;
 end;
 
+
 procedure TGtkSHEdit.ClearRect(x1, y1, x2, y2: Integer);
 begin
   SetGCColor(SHStyles^[shWhitespace].Background);
@@ -356,6 +362,18 @@ begin
 end;
 
 
+procedure TGtkSHEdit.InvalidateRect(x1, y1, x2, y2: Integer);
+var
+  r : TGdkRectangle;
+begin
+  r.x:=x1*CharW+LeftIndent;
+  r.y:=y1*CharH;
+  r.Width:=(x1 - x2 + 1) * CharW;
+  r.Height:=(y2 - y1 + 1) * CharH;
+  gtk_widget_draw(PGtkWidget(PaintBox), @r);
+end;
+
+
 procedure TGtkSHEdit.InvalidateLines(y1, y2: Integer);
 var
   r : TGdkRectangle;
@@ -530,7 +548,7 @@ end;
 
 procedure TGtkSHEdit.SetLineCount(count: Integer);
 begin
-  vadj^.upper := count * CharH;
+  vadj^.upper := (count+1) * CharH;
   gtk_adjustment_changed(vadj);
   gtk_widget_set_usize(PaintBox, Trunc(hadj^.upper), Trunc(vadj^.upper));
 end;
@@ -554,7 +572,7 @@ end;
 
 function TGtkSHEdit.GetVertPos: Integer;
 begin
-  Result := Trunc(vadj^.value) div CharH;
+  Result := (Trunc(vadj^.value)+CharH-1) div CharH;
 end;
 
 
@@ -578,7 +596,11 @@ end;
 end.
 {
   $Log$
-  Revision 1.5  1999-12-09 23:16:41  peter
+  Revision 1.6  1999-12-10 15:01:02  peter
+    * first things for selection
+    * Better Adjusting of range/cursor
+
+  Revision 1.5  1999/12/09 23:16:41  peter
     * cursor walking is now possible, both horz and vert ranges are now
       adapted
     * filter key modifiers

+ 185 - 307
fcl/shedit/keys.inc

@@ -23,16 +23,16 @@
 // TSHTextEdit: Implementation of keyboard handling methods
 
 
-function TSHTextEdit.AddKeyboardAction(AMethod: TKeyboardActionProc;
-  ADescr: String): TKeyboardActionDescr;
+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;
+
+function TSHTextEdit.AddKeyboardAssignment(AKeyCode: Integer; AShiftState: TShiftState; AAction: TKeyboardActionDescr): TShortcut;
 begin
   Result := TShortcut(Shortcuts.Add);
   Result.KeyCode := AKeyCode;
@@ -40,11 +40,10 @@ begin
   Result.Action := AAction;
 end;
 
-procedure TSHTextEdit.AddKeyDef(AMethod: TKeyboardActionProc; ADescr: String;
-  AKeyCode: Integer; AShiftState: TShiftState);
+
+procedure TSHTextEdit.AddKeyDef(AMethod: TKeyboardActionProc; ASelectionAction:TSelectionAction; ADescr: String; AKeyCode: Integer; AShiftState: TShiftState);
 begin
-  AddKeyboardAssignment(AKeyCode, AShiftState,
-    AddKeyboardAction(AMethod, ADescr));
+  AddKeyboardAssignment(AKeyCode, AShiftState,AddKeyboardAction(AMethod, ASelectionAction, ADescr));
 end;
 
 
@@ -54,231 +53,151 @@ begin
 end;
 
 
-procedure TSHTextEdit.CursorUp;
+procedure TSHTextEdit.AdjustCursorToRange;
 begin
-  if FCursorY > 0 then
-    Dec(FCursorY);
   if FCursorY<Renderer.VertPos then
-   Renderer.VertPos := Renderer.VertPos - 1;
-end;
-
-
-procedure TSHTextEdit.CursorDown;
-begin
-  if FCursorY < FDoc.LineCount - 1 then
-   Inc(FCursorY);
-  if FCursorY>=Renderer.VertPos+Renderer.PageHeight then
-   Renderer.VertPos := Renderer.VertPos + 1;
-end;
-
-
-procedure TSHTextEdit.CursorLeft;
-begin
-  if FCursorX > 0 then
    begin
-     Dec(FCursorX);
-     if FCursorX<Renderer.HorzPos then
-      Renderer.HorzPos:=Renderer.HorzPos-1;
+     HideCursor;
+     FCursorY:=Renderer.VertPos;
+     ShowCursor;
    end
   else
-    if FCursorY > 0 then
-      begin
-        Dec(FCursorY);
-        FCursorX := FDoc.LineLen[FCursorY];
-        if FCursorY<Renderer.VertPos then
-         Renderer.VertPos := Renderer.VertPos - 1;
-        if FCursorX>=Renderer.HorzPos+Renderer.PageWidth then
-         Renderer.HorzPos:=Renderer.HorzPos+1;
-      end;
-end;
-
-
-procedure TSHTextEdit.CursorRight;
-begin
-  Inc(FCursorX);
-  if FCursorX>=Renderer.HorzPos+Renderer.PageWidth then
-   Renderer.HorzPos:=FCursorX-Renderer.PageWidth+1;
-  if FCursorX>=Renderer.LineWidth then
-   Renderer.LineWidth:=FCursorX+1;
-end;
-
-
-procedure TSHTextEdit.CursorDocBegin;
-begin
-  FCursorX := 0;
-  FCursorY := 0;
-  Renderer.HorzPos:=0;
-  Renderer.VertPos:=0;
+   if FCursorY>Renderer.VertPos+Renderer.PageHeight then
+    begin
+      HideCursor;
+      FCursorY:=Renderer.VertPos+Renderer.PageHeight-1;
+      ShowCursor;
+    end;
+  if FCursorX<Renderer.HorzPos then
+   begin
+     HideCursor;
+     FCursorX:=Renderer.HorzPos;
+     ShowCursor;
+   end
+  else
+   if FCursorX>Renderer.HorzPos+Renderer.PageWidth then
+    begin
+      HideCursor;
+      FCursorX:=Renderer.HorzPos+Renderer.PageWidth-1;
+      ShowCursor;
+    end;
 end;
 
 
-procedure TSHTextEdit.CursorDocEnd;
+procedure TSHTextEdit.AdjustRangeToCursor;
 var
   py : integer;
 begin
-  FCursorY:=FDoc.LineCount-1;
-  FCursorX := FDoc.LineLen[FCursorY];
-  py := FDoc.LineCount - Renderer.PageHeight;
-  if py < 0 then
-    py:=0;
-  Renderer.VertPos := py;
-  if FCursorX >= Renderer.HorzPos+Renderer.PageWidth then
-   Renderer.HorzPos:=FCursorX-Renderer.PageWidth+1;
-end;
-
-
-procedure TSHTextEdit.CursorHome;
-begin
-  FCursorX := 0;
-  Renderer.HorzPos:=0;
-end;
-
-
-procedure TSHTextEdit.CursorEnd;
-begin
-  FCursorX := FDoc.LineLen[FCursorY];
-  if FCursorX >= Renderer.HorzPos+Renderer.PageWidth then
-   Renderer.HorzPos:=FCursorX-Renderer.PageWidth+1;
-end;
-
-
-procedure TSHTextEdit.CursorPageUp;
-begin
-  if FCursorY > 0 then
+  if FCursorY< Renderer.VertPos then
+   Renderer.VertPos:=FCursorY
+  else
+   if FCursorY>=Renderer.VertPos+Renderer.PageHeight then
     begin
-      Dec(FCursorY, Renderer.PageHeight);
-      if FCursorY < 0 then
-       begin
-         FCursorY := 0;
-         Renderer.VertPos := 0;
-       end
+      py := FCursorY - Renderer.PageHeight + 1;
+      if py < 0 then
+       Renderer.VertPos:=0
       else
-       Renderer.VertPos := Renderer.VertPos - Renderer.PageHeight;
+       Renderer.VertPos:=py;
     end;
-end;
-
-
-procedure TSHTextEdit.CursorPageDown;
-var
-  py : integer;
-begin
-  if FCursorY < FDoc.LineCount - 1 then
+  if FCursorX<Renderer.HorzPos then
+   Renderer.HorzPos:=FCursorX
+  else
+   if FCursorX>=Renderer.HorzPos+Renderer.PageWidth then
     begin
-      Inc(FCursorY, Renderer.PageHeight);
-      if FCursorY >= FDoc.LineCount then
-       begin
-         FCursorY:=FDoc.LineCount-1;
-         py := FDoc.LineCount - Renderer.PageHeight;
-         if py < 0 then
-          py:=0;
-         Renderer.VertPos := py;
-       end
+      py := FCursorX - Renderer.PageWidth +1;
+      if py < 0 then
+       Renderer.HorzPos:=0
       else
-       Renderer.VertPos := Renderer.VertPos + Renderer.PageHeight;
+       Renderer.HorzPos:=py;
     end;
 end;
 
 
-
-procedure TSHTextEdit.SetSelectionStart;
-begin
-  if not FSel.IsValid then
-   begin
-     FSel.StartX := FCursorX;
-     FSel.StartY := FCursorY;
-     FSel.EndX := FCursorX;
-     FSel.EndY := FCursorY;
-   end;
-end;
-
-
-procedure TSHTextEdit.SetSelectionEnd;
-begin
-  if FSel.IsValid then
-   begin
-     FSel.EndX := FCursorX;
-     FSel.EndY := FCursorY;
-   end;
-end;
-
-
-procedure TSHTextEdit.SelectionUp;
+procedure TSHTextEdit.CursorUp;
 begin
-  SetSelectionStart;
-  CursorUp;
-  SetSelectionEnd;
+  if FCursorY>0 then
+   dec(FCursorY);
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionDown;
+procedure TSHTextEdit.CursorDown;
 begin
-  SetSelectionStart;
-  CursorDown;
-  SetSelectionEnd;
+  if FCursorY<FDoc.LineCount-1 then
+   inc(FCursorY);
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionLeft;
+procedure TSHTextEdit.CursorLeft;
 begin
-  SetSelectionStart;
-  CursorLeft;
-  SetSelectionEnd;
+  dec(FCursorX);
+  if FCursorX < 0 then
+   begin
+     if FCursorY>0 then
+      begin
+        dec(FCursorY);
+        FCursorX:=FDoc.LineLen[FCursorY];
+      end
+     else
+      FCursorX:=0;
+   end;
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionRight;
+procedure TSHTextEdit.CursorRight;
 begin
-  SetSelectionStart;
-  CursorRight;
-  SetSelectionEnd;
+  inc(FCursorX);
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionHome;
+procedure TSHTextEdit.CursorDocBegin;
 begin
-  SetSelectionStart;
-  CursorHome;
-  SetSelectionEnd;
+  FCursorX:=0;
+  FCursorY:=0;
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionEnd;
+procedure TSHTextEdit.CursorDocEnd;
 begin
-  SetSelectionStart;
-  CursorEnd;
-  SetSelectionEnd;
+  FCursorY:=FDoc.LineCount-1;
+  FCursorX:=FDoc.LineLen[FCursorY];
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionDocBegin;
+procedure TSHTextEdit.CursorHome;
 begin
-  SetSelectionStart;
-  CursorDocBegin;
-  SetSelectionEnd;
+  FCursorX:=0;
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionDocEnd;
+procedure TSHTextEdit.CursorEnd;
 begin
-  SetSelectionStart;
-  CursorDocEnd;
-  SetSelectionEnd;
+  FCursorX:=FDoc.LineLen[FCursorY];
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionPageUp;
+procedure TSHTextEdit.CursorPageUp;
 begin
-  SetSelectionStart;
-  CursorPageUp;
-  SetSelectionEnd;
+  dec(FCursorY,Renderer.PageHeight);
+  if FCursorY<0 then
+   FCursorY:=0;
+  AdjustRangeToCursor;
 end;
 
 
-procedure TSHTextEdit.SelectionPageDown;
+procedure TSHTextEdit.CursorPageDown;
 begin
-  SetSelectionStart;
-  CursorPageDown;
-  SetSelectionEnd;
+  inc(FCursorY,Renderer.PageHeight);
+  if FCursorY>FDoc.LineCount-1 then
+   FCursorY:=FDoc.LineCount-1;
+  AdjustRangeToCursor;
 end;
 
 
@@ -549,62 +468,19 @@ begin
 end;
 
 procedure TSHTextEdit.KeyPressed(KeyCode: LongWord; ShiftState: TShiftState);
-var
-  RemoveSel: Boolean;
-
-  function CheckEditingKeys: Boolean;
-
-    procedure CheckSelKeys;
-    begin
-      if ssShift in ShiftState then begin
-        RemoveSel := False;
-        if not FSel.IsValid then begin
-          FSel.StartX := LastCursorX;
-          FSel.StartY := LastCursorY;
-        end;
-        FSel.EndX := FCursorX;
-        FSel.EndY := FCursorY;
-      end;
-    end;
-
-  begin
-    if ShiftState * [ssCtrl, ssAlt] = [] then
-      Result := ExecKey(Chr(KeyCode), False)
-    else
-      Result := False;
-  end;
 
   procedure RedrawArea(x1, y1, x2, y2: Integer);
-  var
-    r: TRect;
   begin
-    // WriteLn('Redraw: ', x1, '/', y1, ' - ', x2, '/', y2);
-    {###if y1 = y2 then begin
-      r.Left := FLeftIndent + x1 * CharW;
-      r.Right := FLeftIndent + x2 * CharW;
-      r.Top := y1 * CharH;
-      r.Bottom := r.Top + CharH;
-      PaintBox.Redraw(r);
-    end else begin
-      r.Left := FLeftIndent + x1 * CharW;
-      r.Right := PaintBox.Width;
-      r.Top := y1 * CharH;
-      r.Bottom := r.Top + CharH;
-      PaintBox.Redraw(r);
-
-      if y1 < y2 - 1 then begin
-        r.Left := FLeftIndent;
-        r.Top := (y1 + 1) * CharH;
-        r.Bottom := y2 * CharH;
-        PaintBox.Redraw(r);
-      end else
-        r.Left := FLeftIndent;
-
-      r.Right := FLeftIndent + x2 * CharW;
-      r.Top := y2 * CharH;
-      r.Bottom := r.Top + CharH;
-      PaintBox.Redraw(r);
-    end;}
+    WriteLn('Redraw: ', x1, '/', y1, ' - ', x2, '/', y2);
+    if y1 = y2 then
+     Renderer.InvalidateRect(x1,y1,x2,y2)
+    else
+     begin
+       Renderer.InvalidateRect(x1,y1,x1+Renderer.PageWidth,y1);
+       if y1 < y2 - 1 then
+        Renderer.InvalidateRect(0,y1+1,Renderer.PageWidth,y2 - 1);
+       Renderer.InvalidateRect(0,y2,x2,y2+1);
+     end;
   end;
 
 var
@@ -619,95 +495,93 @@ begin
   LastCursorX := FCursorX;
   LastCursorY := FCursorY;
   OldSelValid := FSel.IsValid;
-  if OldSelValid then begin
-    OldSelStartX := FSel.OStartX;
-    OldSelStartY := FSel.OStartY;
-    OldSelEndX := FSel.OEndX;
-    OldSelEndY := FSel.OEndY;
-  end;
-
-  RemoveSel := True;
+  if OldSelValid then
+   begin
+     OldSelStartX := FSel.OStartX;
+     OldSelStartY := FSel.OStartY;
+     OldSelEndX := FSel.OEndX;
+     OldSelEndY := FSel.OEndY;
+   end;
 
   // Check for keyboard shortcuts
   AssignmentMatched := 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
-      shortcut.Action.Method;
-      AssignmentMatched := True;
-      break;
-    end;
-  end;
+  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
+        shortcut.Action.Method;
+        // 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 :
+            begin
+              FSel.Clear;
+            end;
+        end;
+        AssignmentMatched := True;
+        break;
+      end;
+   end;
 
   if not AssignmentMatched then
-    if not CheckEditingKeys then RemoveSel := False;
-
-  // Check selection
-  if FSel.IsValid then begin
-    if (FSel.StartX = FSel.EndX) and (FSel.StartY = FSel.EndY) then
-      FSel.Clear
-  end;
-
-//if RemoveSel then FSel.Clear;
-//PaintBox.Redraw;
+   begin
+     if ShiftState * [ssCtrl, ssAlt] = [] then
+      ExecKey(Chr(KeyCode), False);
+   end;
 
   {Write('Sel = ', FSel.StartX, '/', FSel.StartY, ' - ', FSel.EndX, '/', FSel.EndY);
   if OldSelValid then WriteLn('  Old = ', OldSelStartX, '/', OldSelStartY, ' - ', OldSelEndX, '/', OldSelEndY)
   else WriteLn;}
 
-
-  if RemoveSel then FSel.Clear;
-
-  if not OldSelValid then begin
-    if FSel.IsValid then
+  // Handle the rewriting of selections
+  if not OldSelValid then
+   begin
+     if FSel.IsValid then
       RedrawArea(FSel.OStartX, FSel.OStartY, FSel.OEndX, FSel.OEndY);
-  end else begin
-    if not FSel.IsValid then
+   end
+  else
+   begin
+     if not FSel.IsValid then
       RedrawArea(OldSelStartX, OldSelStartY, OldSelEndX, OldSelEndY)
-    else begin
-      // Do OldSel and FSel intersect?
-      if (OldSelEndY < FSel.OStartY) or (OldSelStartY > FSel.OEndY) or
-         ((OldSelEndY = FSel.OStartY) and (OldSelEndX <= FSel.OStartX)) or
-         ((OldSelStartY = FSel.OEndY) and (OldSelStartX >= FSel.OEndX)) then begin
-         RedrawArea(OldSelStartX, OldSelStartY, OldSelEndX, OldSelEndY);
-         RedrawArea(FSel.OStartX, FSel.OStartY, FSel.OEndX, FSel.OEndY);
-      end else begin
-        // Intersection => determine smallest possible area(s) to redraw
-        // 1. Check if the start position has changed
-        if (OldSelStartX <> FSel.OStartX) or (OldSelStartY <> FSel.OStartY) then
-          if (OldSelStartY < FSel.OStartY) or ((OldSelStartY = FSel.OStartY) and
-             (OldSelStartX < FSel.OStartX)) then
-            RedrawArea(OldSelStartX, OldSelStartY, FSel.OStartX, FSel.OStartY)
-          else
-            RedrawArea(FSel.OStartX, FSel.OStartY, OldSelStartX, OldSelStartY);
-        // 2. Check if end position has changed
-        if (OldSelEndX <> FSel.OEndX) or (OldSelEndY <> FSel.OEndY) then
-          if (OldSelEndY < FSel.OEndY) or ((OldSelEndY = FSel.OEndY) and
-             (OldSelEndX < FSel.OEndX)) then
-            RedrawArea(OldSelEndX, OldSelEndY, FSel.OEndX, FSel.OEndY)
-          else
-            RedrawArea(FSel.OEndX, FSel.OEndY, OldSelEndX, OldSelEndY);
-
-        {if OldSelEndY = FSel.OEndY then begin
-          if OldSelStartX > FSel.OStartX  then
-            RedrawArea(FSel.OStartX, FSel.OEndY, OldSelStartX, FSel.OEndY)
-          else if OldSelStartX < FSel.OStartX then
-            RedrawArea(OldSelStartX, FSel.OEndY, FSel.OStartX, FSel.OEndY);
-          if OldSelEndX < FSel.OEndX then
-            RedrawArea(OldSelEndX, FSel.OEndY, FSel.OEndX, FSel.OEndY)
-          else if OldSelEndX > FSel.OEndX then
-            RedrawArea(FSel.OEndX, FSel.OEndY, OldSelEndX, FSel.OEndY);
-        end else begin
-          if OldSelStartY > FSel.OStartY then
-            RedrawArea(FSel.OStartX, FSel.OStartY, OldSelStartX, OldSelStartY)
-          else if OldSelStartY < FSel.OStartY then
-            RedrawArea(OldSelStartX, OldSelStartY, FSel.OStartX, FSel.OStartY);
-          if OldSelEndY < FSel.OEndY then
-            RedrawArea(OldSelEndX, OldSelEndY, FSel.OEndX, FSel.OEndY)
-          else if OldSelEndY > FSel.OEndY then
-            RedrawArea(FSel.OEndX, FSel.OEndY, OldSelEndX, OldSelEndY);
-        end;}
+     else
+      begin
+        // Do OldSel and FSel intersect?
+        if (OldSelEndY < FSel.OStartY) or (OldSelStartY > FSel.OEndY) or
+           ((OldSelEndY = FSel.OStartY) and (OldSelEndX <= FSel.OStartX)) or
+           ((OldSelStartY = FSel.OEndY) and (OldSelStartX >= FSel.OEndX)) then
+         begin
+           RedrawArea(OldSelStartX, OldSelStartY, OldSelEndX, OldSelEndY);
+           RedrawArea(FSel.OStartX, FSel.OStartY, FSel.OEndX, FSel.OEndY);
+         end
+        else
+         begin
+           // Intersection => determine smallest possible area(s) to redraw
+           // 1. Check if the start position has changed
+           if (OldSelStartX <> FSel.OStartX) or (OldSelStartY <> FSel.OStartY) then
+            if (OldSelStartY < FSel.OStartY) or ((OldSelStartY = FSel.OStartY) and
+               (OldSelStartX < FSel.OStartX)) then
+             RedrawArea(OldSelStartX, OldSelStartY, FSel.OStartX, FSel.OStartY)
+            else
+             RedrawArea(FSel.OStartX, FSel.OStartY, OldSelStartX, OldSelStartY);
+           // 2. Check if end position has changed
+           if (OldSelEndX <> FSel.OEndX) or (OldSelEndY <> FSel.OEndY) then
+            if (OldSelEndY < FSel.OEndY) or ((OldSelEndY = FSel.OEndY) and
+               (OldSelEndX < FSel.OEndX)) then
+             RedrawArea(OldSelEndX, OldSelEndY, FSel.OEndX, FSel.OEndY)
+            else
+             RedrawArea(FSel.OEndX, FSel.OEndY, OldSelEndX, OldSelEndY);
       end;
     end;
   end;
@@ -717,7 +591,11 @@ end;
 
 {
   $Log$
-  Revision 1.4  1999-12-09 23:16:41  peter
+  Revision 1.5  1999-12-10 15:01:02  peter
+    * first things for selection
+    * Better Adjusting of range/cursor
+
+  Revision 1.4  1999/12/09 23:16:41  peter
     * cursor walking is now possible, both horz and vert ranges are now
       adapted
     * filter key modifiers

+ 14 - 18
fcl/shedit/shedit.pp

@@ -44,10 +44,13 @@ type
 
   TKeyboardActionProc = procedure of object;
 
+  TSelectionAction = (selNothing,selExtend,selClear);
+
   TKeyboardActionDescr = class(TCollectionItem)
   public
     Descr: String;                      // Human readable description
     Method: TKeyboardActionProc;
+    SelectionAction : TSelectionAction;
   end;
 
   TShortcut = class(TCollectionItem)
@@ -116,6 +119,7 @@ type
 
   ISHRenderer = class
 
+    procedure InvalidateRect(x1, y1, x2, y2: Integer); virtual; abstract;
     procedure InvalidateLines(y1, y2: Integer); virtual; abstract;
 
     // Drawing
@@ -201,6 +205,8 @@ type
   public
     // Keyboard command handlers
     // Cursor movement
+    procedure AdjustCursorToRange;
+    procedure AdjustRangeToCursor;
     procedure CursorUp;
     procedure CursorDown;
     procedure CursorLeft;
@@ -211,19 +217,7 @@ type
     procedure CursorDocEnd;
     procedure CursorPageUp;
     procedure CursorPageDown;
-    // Selection movement
-    procedure SetSelectionStart;
-    procedure SetSelectionEnd;
-    procedure SelectionUp;
-    procedure SelectionDown;
-    procedure SelectionLeft;
-    procedure SelectionRight;
-    procedure SelectionHome;
-    procedure SelectionEnd;
-    procedure SelectionDocBegin;
-    procedure SelectionDocEnd;
-    procedure SelectionPageUp;
-    procedure SelectionPageDown;
+
     // Misc
     procedure ToggleOverwriteMode;
     procedure EditDelLeft;
@@ -240,12 +234,10 @@ type
 
   public
     constructor Create(ADoc: TTextDoc; ARenderer: ISHRenderer); virtual;
-    function AddKeyboardAction(AMethod: TKeyboardActionProc;
-      ADescr: String): TKeyboardActionDescr;
+    function  AddKeyboardAction(AMethod: TKeyboardActionProc;ASelectionAction:TSelectionAction;ADescr: String): TKeyboardActionDescr;
     function AddKeyboardAssignment(AKeyCode: Integer; AShiftState: TShiftState;
       AAction: TKeyboardActionDescr): TShortcut;
-    procedure AddKeyDef(AMethod: TKeyboardActionProc; ADescr: String;
-      AKeyCode: Integer; AShiftState: TShiftState);
+    procedure AddKeyDef(AMethod: TKeyboardActionProc; ASelectionAction:TSelectionAction; ADescr: String; AKeyCode: Integer; AShiftState: TShiftState);
 
     procedure FocusIn;
     procedure FocusOut;
@@ -410,7 +402,11 @@ end.
 
 {
   $Log$
-  Revision 1.4  1999-12-09 23:16:41  peter
+  Revision 1.5  1999-12-10 15:01:03  peter
+    * first things for selection
+    * Better Adjusting of range/cursor
+
+  Revision 1.4  1999/12/09 23:16:41  peter
     * cursor walking is now possible, both horz and vert ranges are now
       adapted
     * filter key modifiers