Browse Source

* Fixed drawing of selection
* Several small corrections (removed superfluous local variables etc.)

sg 26 years ago
parent
commit
e3ab54a015
3 changed files with 176 additions and 184 deletions
  1. 88 91
      fcl/shedit/drawing.inc
  2. 76 86
      fcl/shedit/gtkshedit.pp
  3. 12 7
      fcl/shedit/keys.inc

+ 88 - 91
fcl/shedit/drawing.inc

@@ -95,15 +95,22 @@ procedure TSHTextEdit.DrawContent(x1, y1, x2, y2: Integer);
       ShowCursor;
       ShowCursor;
   end;
   end;
 
 
+  // If Lenght(s) < x, add as many spaces to s so that x will be at
+  // the end of s.
+  procedure ProvideSpace(var s: String; x: Integer);
+  begin
+    while Length(s) < x do
+      s := s + ' ';
+  end;
+
 var
 var
-  i, j, py, LineNumber, CheckLine: Integer;
+  i, LineNumber, CheckLine: Integer;
   OrigStr, sh, s, s2: PChar;
   OrigStr, sh, s, s2: PChar;
-  i, spos, x: Integer;
+  spos, x: Integer;
   flags: Byte;
   flags: Byte;
-  r: TRect;
   InSel: Boolean;
   InSel: Boolean;
-
-  RequestedColor, LastCol: Char;
+  LastCol: Char;
+  LineWithSpace: String;	// used for virtual whitespace expanding
 
 
 begin
 begin
 
 
@@ -117,7 +124,6 @@ begin
   end;
   end;
 
 
   LineNumber := y1;
   LineNumber := y1;
-  py := LineNumber;
 
 
   // Check if syntax highlighting flags are valid:
   // Check if syntax highlighting flags are valid:
   if (FDoc.LineFlags[LineNumber] and LF_SH_Valid) <> 0 then
   if (FDoc.LineFlags[LineNumber] and LF_SH_Valid) <> 0 then
@@ -140,115 +146,106 @@ begin
   end;
   end;
 
 
 
 
-//  if FSel.IsValid then writeln('Selection: ',FSel.OStartX,',',FSel.OStartY,'-',FSel.OEndX,',',FSel.OEndY);
+  // if FSel.IsValid then writeln('Selection: ',FSel.OStartX,',',FSel.OStartY,'-',FSel.OEndX,',',FSel.OEndY);
 
 
-  while (LineNumber < FDoc.LineCount) and (py <= y2) do begin
+  while (LineNumber < FDoc.LineCount) and (LineNumber <= y2) do begin
     i := 0;
     i := 0;
 
 
+    // Do virtual whitespace expanding
+    LineWithSpace := FDoc.LineText[LineNumber];
+    if LineNumber = FSel.OStartY then
+      ProvideSpace(LineWithSpace, FSel.OStartX);
+    if LineNumber = FSel.OEndY then
+      ProvideSpace(LineWithSpace, FSel.OEndX);
+    if LineNumber = FCursorY then
+      ProvideSpace(LineWithSpace, FCursorX);
+
     // Call syntax highlighter for this line
     // Call syntax highlighter for this line
-    GetMem(sh, FDoc.LineLen[LineNumber] * 3 + 8);
+
+    GetMem(sh, Length(LineWithSpace) * 3 + 8);
     s := sh;
     s := sh;
     FDoc.LineFlags[LineNumber] := flags or LF_SH_Valid;
     FDoc.LineFlags[LineNumber] := flags or LF_SH_Valid;
-    OrigStr := PChar(FDoc.LineText[LineNumber]);
+    OrigStr := PChar(LineWithSpace);
     DoHighlighting(flags, OrigStr, s);
     DoHighlighting(flags, OrigStr, s);
 
 
     // Handle current selection
     // Handle current selection
     if FSel.IsValid then
     if FSel.IsValid then
-     begin
-       if (LineNumber > FSel.OStartY) and (LineNumber < FSel.OEndY) then
-        begin
+      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
           s[0] := LF_Escape;
           s[0] := LF_Escape;
           s[1] := Chr(shSelected);
           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;
+          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;
             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
-               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);
+            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;
-     end;
+        end;
+        s[spos] := #0;
+        StrDispose(s2);
+      end;
 
 
-    Renderer.DrawTextLine(x1, x2, py, s);
+    Renderer.DrawTextLine(x1, x2, LineNumber, s);
 
 
-    FreeMem(sh, FDoc.LineLen[LineNumber] * 3 + 8);
+    FreeMem(sh);
     Inc(LineNumber);
     Inc(LineNumber);
-    Inc(py);
   end;
   end;
 
 
-  PostprocessOutput(py);
+  PostprocessOutput(LineNumber);
 end;
 end;
 
 
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.3  1999-12-10 15:01:02  peter
+  Revision 1.4  1999-12-12 17:50:50  sg
+  * Fixed drawing of selection
+  * Several small corrections (removed superfluous local variables etc.)
+
+  Revision 1.3  1999/12/10 15:01:02  peter
     * first things for selection
     * first things for selection
     * Better Adjusting of range/cursor
     * Better Adjusting of range/cursor
 
 

+ 76 - 86
fcl/shedit/gtkshedit.pp

@@ -138,18 +138,19 @@ procedure TGtkSHEdit_Expose(GtkWidget: PGtkWidget; event: PGdkEventExpose; edit:
 var
 var
   x1, y1, x2, y2: Integer;
   x1, y1, x2, y2: Integer;
 begin
 begin
-  x1:=event^.area.x;
-  if x1>0 then
-   dec(x1,edit.LeftIndent);
-  x2:=x1+event^.area.width - 1;
-  x1:=x1 div edit.CharW;
-  x2:=(x2+edit.CharW-1) div edit.CharW;
+  x1 := event^.area.x;
+  if x1 > 0 then
+    Dec(x1, edit.LeftIndent);
+  x2 := x1 + event^.area.width - 1;
+  x1 := x1 div edit.CharW;
+  x2 := (x2 + edit.CharW - 1) div edit.CharW;
   y1 := event^.area.y div edit.CharH;
   y1 := event^.area.y div edit.CharH;
   y2 := (event^.area.y + event^.area.height - 1) 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.GdkWnd := edit.PaintBox^.window;
   edit.GC := gdk_gc_new(edit.GdkWnd);
   edit.GC := gdk_gc_new(edit.GdkWnd);
+  edit.CurGCColor := 0;		// Reset color, because we have a new GC!
   gdk_gc_copy(edit.GC, PGtkStyle(edit.PaintBox^.thestyle)^.
   gdk_gc_copy(edit.GC, PGtkStyle(edit.PaintBox^.thestyle)^.
     fg_gc[edit.PaintBox^.state]);
     fg_gc[edit.PaintBox^.state]);
 
 
@@ -181,6 +182,7 @@ begin
     GDK_Shift_L..GDK_Hyper_R :
     GDK_Shift_L..GDK_Hyper_R :
       begin
       begin
         // Don't let modifier keys trough as normal keys
         // Don't let modifier keys trough as normal keys
+	// *** This doesn't work reliably! (sg)
         exit;
         exit;
       end;
       end;
   else
   else
@@ -366,10 +368,10 @@ procedure TGtkSHEdit.InvalidateRect(x1, y1, x2, y2: Integer);
 var
 var
   r : TGdkRectangle;
   r : TGdkRectangle;
 begin
 begin
-  r.x:=x1*CharW+LeftIndent;
-  r.y:=y1*CharH;
-  r.Width:=(x1 - x2 + 1) * CharW;
-  r.Height:=(y2 - y1 + 1) * CharH;
+  r.x := x1 * CharW + LeftIndent;
+  r.y := y1 * CharH;
+  r.Width := (x2 - x1 + 1) * CharW;
+  r.Height := (y2 - y1 + 1) * CharH;
   gtk_widget_draw(PGtkWidget(PaintBox), @r);
   gtk_widget_draw(PGtkWidget(PaintBox), @r);
 end;
 end;
 
 
@@ -379,11 +381,11 @@ var
   r : TGdkRectangle;
   r : TGdkRectangle;
   w,h : integer;
   w,h : integer;
 begin
 begin
-  gdk_window_get_size(PGdkDrawable(GdkWnd),@w,@h);
-  r.x:=0;
-  r.y:=y1 * CharH;
-  r.Width:=w;
-  r.Height:=(y2 - y1 + 1) * CharH;
+  gdk_window_get_size(PGdkDrawable(GdkWnd), @w, @h);
+  r.x := 0;
+  r.y := y1 * CharH;
+  r.Width := w;
+  r.Height := (y2 - y1 + 1) * CharH;
   gtk_widget_draw(PGtkWidget(PaintBox), @r);
   gtk_widget_draw(PGtkWidget(PaintBox), @r);
 end;
 end;
 
 
@@ -391,108 +393,92 @@ end;
 procedure TGtkSHEdit.DrawTextLine(x1, x2, y: Integer; s: PChar);
 procedure TGtkSHEdit.DrawTextLine(x1, x2, y: Integer; s: PChar);
 var
 var
   CurColor: LongWord;
   CurColor: LongWord;
-  rx1,rx2 : Integer;
+  CurX1, CurX2: Integer;
 
 
-  procedure doerase;
+  procedure DoErase;
   begin
   begin
-    if rx2>x1 then
-     begin
-       SetGCColor(CurColor);
-       gdk_draw_rectangle(PGdkDrawable(GdkWnd), GC, 1,
-                          rx1 * CharW + LeftIndent, y * CharH, (rx2 - rx1 + 1) * CharW, CharH);
-       rx1:=rx2;
-     end;
+    SetGCColor(CurColor);
+    if CurX1 < x1 then
+      CurX1 := x1;
+    if CurX2 > CurX1 then begin
+      gdk_draw_rectangle(PGdkDrawable(GdkWnd), GC, 1,
+        CurX1 * CharW + LeftIndent, y * CharH, (CurX2 - CurX1) * CharW, CharH);
+    end;
+    CurX1 := CurX2;
   end;
   end;
 
 
 var
 var
-  RequestedColor: Char;
-  i, j, px: Integer;
+  RequestedColor: Integer;
   NewColor: LongWord;
   NewColor: LongWord;
-  hs : pchar;
+  hs : PChar;
 begin
 begin
-  // WriteLn(Format('DrawTextLine(%d) for %s ', [y, ClassName]));
+
   // Erase the (potentially multi-coloured) background
   // Erase the (potentially multi-coloured) background
 
 
-  rx1 := x1;
-  rx2 := 0;
-  j := 0;
+  hs := s;
   CurColor := SHStyles^[shWhitespace].Background;
   CurColor := SHStyles^[shWhitespace].Background;
 
 
-  // Clear background
-  hs:=s;
-  rx2:=0;
-  repeat
+  CurX1 := 0;
+  CurX2 := 0;
+  while (hs[0] <> #0) and (CurX2 <= x2) do begin
     case hs[0] of
     case hs[0] of
-      #0 :
-        break;
-      LF_Escape :
-        begin
+      LF_Escape: begin
           NewColor := SHStyles^[Ord(hs[1])].Background;
           NewColor := SHStyles^[Ord(hs[1])].Background;
           if NewColor = colDefault then
           if NewColor = colDefault then
-           NewColor := SHStyles^[shWhitespace].Background;
-          if (NewColor <> CurColor) then
-           begin
-             DoErase;
-             CurColor := NewColor;
-           end;
+            NewColor := SHStyles^[shWhitespace].Background;
+          if NewColor <> CurColor then begin
+            DoErase;
+            CurColor := NewColor;
+          end;
           Inc(hs, 2);
           Inc(hs, 2);
         end;
         end;
-      #9 :
-        begin
+      #9: begin
           repeat
           repeat
-            Inc(rx2, CharW);
-            Inc(i);
-          until (i and 7) = 0;
+            Inc(CurX2);
+          until (CurX2 and 7) = 0;
           Inc(hs);
           Inc(hs);
         end;
         end;
-      else
-        begin
-          Inc(hs);
-          Inc(i);
-          Inc(rx2);
-        end;
+      else begin
+        Inc(hs);
+        Inc(CurX2);
+      end;
     end;
     end;
-  until false;
-  rx2 := x2;
+  end;
+  CurX2 := x2;
   DoErase;
   DoErase;
 
 
+
   // Draw text line
   // Draw text line
-  RequestedColor := #1;
-  CurGCColor := colInvalid;
-  i := 0;
-  px := 0;
-  repeat
+
+  RequestedColor := shWhitespace;
+  CurX1 := 0;
+  while s[0] <> #0 do
     case s[0] of
     case s[0] of
-      #0 :
-        break;
-      LF_Escape :
-        begin
-          RequestedColor := s[1];
+      LF_Escape: begin
+          RequestedColor := Ord(s[1]);
           Inc(s, 2);
           Inc(s, 2);
         end;
         end;
-      #9 :
-        begin
+      #9: begin
           repeat
           repeat
-            Inc(px, CharW);
-            Inc(i);
-          until (i and 7) = 0;
+            Inc(CurX1);
+          until (CurX1 and 7) = 0;
           Inc(s);
           Inc(s);
         end;
         end;
-      else
-        begin
-          if (px >= x1) and (px <= x2) then
-           begin
-             SetGCColor(SHStyles^[Ord(RequestedColor)].Color);
-             gdk_draw_text(PGdkDrawable(GdkWnd),
-                           Font[SHStyles^[Ord(RequestedColor)].FontStyle], GC,
-                           px * CharW + LeftIndent, (y + 1) * CharH - 3, s, 1);
-           end;
+      ' ': begin
           Inc(s);
           Inc(s);
-          Inc(i);
-          Inc(px);
+	  Inc(CurX1);
+	end;
+      else begin
+        if (CurX1 >= x1) and (CurX1 <= x2) then begin
+          SetGCColor(SHStyles^[RequestedColor].Color);
+          gdk_draw_text(PGdkDrawable(GdkWnd),
+            Font[SHStyles^[RequestedColor].FontStyle], GC,
+            CurX1 * CharW + LeftIndent, (y + 1) * CharH - 3, s, 1);
         end;
         end;
+        Inc(s);
+        Inc(CurX1);
+      end;
     end;
     end;
-  until false;
 end;
 end;
 
 
 
 
@@ -596,7 +582,11 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.6  1999-12-10 15:01:02  peter
+  Revision 1.7  1999-12-12 17:50:50  sg
+  * Fixed drawing of selection
+  * Several small corrections (removed superfluous local variables etc.)
+
+  Revision 1.6  1999/12/10 15:01:02  peter
     * first things for selection
     * first things for selection
     * Better Adjusting of range/cursor
     * Better Adjusting of range/cursor
 
 

+ 12 - 7
fcl/shedit/keys.inc

@@ -471,7 +471,7 @@ procedure TSHTextEdit.KeyPressed(KeyCode: LongWord; ShiftState: TShiftState);
 
 
   procedure RedrawArea(x1, y1, x2, y2: Integer);
   procedure RedrawArea(x1, y1, x2, y2: Integer);
   begin
   begin
-    WriteLn('Redraw: ', x1, '/', y1, ' - ', x2, '/', y2);
+    // WriteLn('Redraw: ', x1, '/', y1, ' - ', x2, '/', y2);
     if y1 = y2 then
     if y1 = y2 then
      Renderer.InvalidateRect(x1,y1,x2,y2)
      Renderer.InvalidateRect(x1,y1,x2,y2)
     else
     else
@@ -535,11 +535,12 @@ begin
       end;
       end;
    end;
    end;
 
 
-  if not AssignmentMatched then
-   begin
-     if ShiftState * [ssCtrl, ssAlt] = [] then
-      ExecKey(Chr(KeyCode), False);
-   end;
+  if (not AssignmentMatched) and (ShiftState * [ssCtrl, ssAlt] = []) then
+    ExecKey(Chr(KeyCode), False);
+
+  // Check selection
+  if FSel.IsValid and (FSel.StartX = FSel.EndX) and (FSel.StartY = FSel.EndY) then
+    FSel.Clear;
 
 
   {Write('Sel = ', FSel.StartX, '/', FSel.StartY, ' - ', FSel.EndX, '/', FSel.EndY);
   {Write('Sel = ', FSel.StartX, '/', FSel.StartY, ' - ', FSel.EndX, '/', FSel.EndY);
   if OldSelValid then WriteLn('  Old = ', OldSelStartX, '/', OldSelStartY, ' - ', OldSelEndX, '/', OldSelEndY)
   if OldSelValid then WriteLn('  Old = ', OldSelStartX, '/', OldSelStartY, ' - ', OldSelEndX, '/', OldSelEndY)
@@ -591,7 +592,11 @@ end;
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.5  1999-12-10 15:01:02  peter
+  Revision 1.6  1999-12-12 17:50:50  sg
+  * Fixed drawing of selection
+  * Several small corrections (removed superfluous local variables etc.)
+
+  Revision 1.5  1999/12/10 15:01:02  peter
     * first things for selection
     * first things for selection
     * Better Adjusting of range/cursor
     * Better Adjusting of range/cursor