View Issue Details

IDProjectCategoryView StatusLast Update
0013479LazarusIDEpublic2013-09-23 12:09
ReporterAndrea MauriAssigned ToMartin Friebe 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version0.9.27 (SVN)Product Build 
Target Version1.2.0Fixed in Version0.9.31 (SVN) 
Summary0013479: printing from IDE trunk long lines
DescriptionWhen I print the source from the IDE long lines (longer than page) are trunked and the final part of the line is not printed
TagsNo tags attached.
Fixed in Revision36529
LazTarget1.2
WidgetsetWin32/Win64
Attached Files
  • break_lines.patch (3,874 bytes)
    Index: sourceprinter.pas
    ===================================================================
    --- sourceprinter.pas	(revision 26652)
    +++ sourceprinter.pas	(working copy)
    @@ -26,21 +26,25 @@
       Classes, SysUtils, Printers, Graphics, PrintersDlgs, ExtCtrls, GraphType;
     
     type
    +
    +  { TSourcePrinter }
    +
       TSourcePrinter = class(TObject)
       private
         FFont: TFont;
         FShowLineNumbers: boolean;
    +    CharWidth: double;
    +    CharsPerLine:integer;
         LineHeight: double;
         LinesPerPage: integer;
         FMargin: integer;
         PageCount: integer;
         PrintDialog: TPrintDialog;
    -
         procedure PrintPage(Text: TStrings; PageNum: integer);
    +    function  AddLineBreaks(Text: TStrings):TStrings;
       public
         constructor Create;
         destructor Destroy; override;
    -
         procedure Execute(Text: TStrings);
       published
         property Font: TFont read FFont write FFont;
    @@ -84,16 +88,34 @@
         LineNum := Pred(PageNum) * LinesPerPage + l;
     
         //check if end of text is reached
    -    if LineNum <= Text.Count then
    -    begin
    -      if ShowLineNumbers then
    -        s := Format('%4d: ',[LineNum])
    -      else
    -        s := '      ';
    +    if LineNum > Text.Count then continue;
    +    if ShowLineNumbers then
    +      s := Format('%4d: ',[LineNum])
    +    else
    +      s := '      ';
     
    -      s := s + Text[Pred(LineNum)];
    +    s := s + Text[Pred(LineNum)];
     
    -      Printer.Canvas.TextOut(Margin, Round(LineHeight * l), s);
    +    Printer.Canvas.TextOut(Margin, Round(LineHeight * l), s);
    +  end;
    +end;
    +
    +function TSourcePrinter.AddLineBreaks(Text: TStrings):TStrings;
    +var
    +  i:integer;
    +  OriginalLine:string;
    +  NewLine:string;
    +begin
    +  result:=TStringList.create;
    +  for i:=0 to Text.count-1 do begin
    +    OriginalLine:=Text[i];
    +    NewLine:=Copy(OriginalLine,1,CharsPerLine);
    +    Delete(OriginalLine,1,CharsPerLine);
    +    result.add(NewLine);
    +    while OriginalLine<>'' do begin
    +      NewLine:=Copy(OriginalLine,1,CharsPerLine);
    +      Delete(OriginalLine,1,CharsPerLine);
    +      result.add(NewLine);
         end;
       end;
     end;
    @@ -102,39 +124,40 @@
     var
       p: integer;
     begin
    -  if PrintDialog.Execute then
    -  begin
    -    Printer.Title := 'Printers4LazIDE: Source Code Printer Package';
    -    Printer.BeginDoc;
    -    Printer.Canvas.Font := FFont;
    +  if not PrintDialog.Execute then exit;
    +  Printer.Title := 'Printers4LazIDE: Source Code Printer Package';
    +  Printer.BeginDoc;
    +  Printer.Canvas.Font := FFont;
     
    -    //calculate page dimensions
    -    LineHeight := Printer.Canvas.TextHeight('X') * 1.2;
    -    LinesPerPage := Round(Printer.PageHeight / LineHeight - 3);
    +  //calculate page dimensions
    +  LineHeight   := Printer.Canvas.TextHeight('X') * 1.2;
    +  LinesPerPage := Round(Printer.PageHeight / LineHeight - 3);
    +  CharWidth    := Printer.Canvas.TextWidth('X');
    +  CharsPerLine := Round(Printer.PageWidth/CharWidth)-8;
     
    -    PageCount := Text.Count div LinesPerPage;
    -    if Text.Count mod LinesPerPage <> 0 then
    -      Inc(PageCount);
    -    
    -    try
    -      //print each page
    -      for p := 1 to PageCount do
    -      begin
    -        PrintPage(Text, p);
    +  Text:=AddLineBreaks(Text);  // break lines which are longer than <CharsPerLine>.
     
    -        //create a new page
    -        if p <> PageCount then
    -          Printer.NewPage;
    -      end;
    -      
    -      Printer.EndDoc;
    -    except
    -      on E:Exception do
    -      begin
    -        Printer.Abort;
    -        raise Exception.Create(e.message);
    -      end;
    +  PageCount := Text.Count div LinesPerPage;
    +  if Text.Count mod LinesPerPage <> 0 then Inc(PageCount);
    +
    +  try
    +    //print each page
    +    for p := 1 to PageCount do
    +    begin
    +      PrintPage(Text, p);
    +
    +      //create a new page
    +      if p <> PageCount then
    +        Printer.NewPage;
         end;
    +
    +    Printer.EndDoc;
    +  except
    +    on E:Exception do
    +    begin
    +      Printer.Abort;
    +      raise Exception.Create(e.message);
    +    end;
       end;
     end;
     
    
    break_lines.patch (3,874 bytes)

Activities

samuel herzog

2009-07-07 21:47

developer   ~0028967

Yes, this is reproducable with todays SVN 20806 and FPC 2.2.5 on win32.
Lines which are longer than the paper widht are just cut off instead of wrapped onto the next line.

Paul Ishenin

2010-07-12 10:28

manager   ~0039280

Someone need to write an algorithm for line breaking or we need to use a DrawText function which supports line breaking. The problem is in file lazarus\components\printers\design\sourceprinter.pas

2010-07-14 21:44

 

break_lines.patch (3,874 bytes)
Index: sourceprinter.pas
===================================================================
--- sourceprinter.pas	(revision 26652)
+++ sourceprinter.pas	(working copy)
@@ -26,21 +26,25 @@
   Classes, SysUtils, Printers, Graphics, PrintersDlgs, ExtCtrls, GraphType;
 
 type
+
+  { TSourcePrinter }
+
   TSourcePrinter = class(TObject)
   private
     FFont: TFont;
     FShowLineNumbers: boolean;
+    CharWidth: double;
+    CharsPerLine:integer;
     LineHeight: double;
     LinesPerPage: integer;
     FMargin: integer;
     PageCount: integer;
     PrintDialog: TPrintDialog;
-
     procedure PrintPage(Text: TStrings; PageNum: integer);
+    function  AddLineBreaks(Text: TStrings):TStrings;
   public
     constructor Create;
     destructor Destroy; override;
-
     procedure Execute(Text: TStrings);
   published
     property Font: TFont read FFont write FFont;
@@ -84,16 +88,34 @@
     LineNum := Pred(PageNum) * LinesPerPage + l;
 
     //check if end of text is reached
-    if LineNum <= Text.Count then
-    begin
-      if ShowLineNumbers then
-        s := Format('%4d: ',[LineNum])
-      else
-        s := '      ';
+    if LineNum > Text.Count then continue;
+    if ShowLineNumbers then
+      s := Format('%4d: ',[LineNum])
+    else
+      s := '      ';
 
-      s := s + Text[Pred(LineNum)];
+    s := s + Text[Pred(LineNum)];
 
-      Printer.Canvas.TextOut(Margin, Round(LineHeight * l), s);
+    Printer.Canvas.TextOut(Margin, Round(LineHeight * l), s);
+  end;
+end;
+
+function TSourcePrinter.AddLineBreaks(Text: TStrings):TStrings;
+var
+  i:integer;
+  OriginalLine:string;
+  NewLine:string;
+begin
+  result:=TStringList.create;
+  for i:=0 to Text.count-1 do begin
+    OriginalLine:=Text[i];
+    NewLine:=Copy(OriginalLine,1,CharsPerLine);
+    Delete(OriginalLine,1,CharsPerLine);
+    result.add(NewLine);
+    while OriginalLine<>'' do begin
+      NewLine:=Copy(OriginalLine,1,CharsPerLine);
+      Delete(OriginalLine,1,CharsPerLine);
+      result.add(NewLine);
     end;
   end;
 end;
@@ -102,39 +124,40 @@
 var
   p: integer;
 begin
-  if PrintDialog.Execute then
-  begin
-    Printer.Title := 'Printers4LazIDE: Source Code Printer Package';
-    Printer.BeginDoc;
-    Printer.Canvas.Font := FFont;
+  if not PrintDialog.Execute then exit;
+  Printer.Title := 'Printers4LazIDE: Source Code Printer Package';
+  Printer.BeginDoc;
+  Printer.Canvas.Font := FFont;
 
-    //calculate page dimensions
-    LineHeight := Printer.Canvas.TextHeight('X') * 1.2;
-    LinesPerPage := Round(Printer.PageHeight / LineHeight - 3);
+  //calculate page dimensions
+  LineHeight   := Printer.Canvas.TextHeight('X') * 1.2;
+  LinesPerPage := Round(Printer.PageHeight / LineHeight - 3);
+  CharWidth    := Printer.Canvas.TextWidth('X');
+  CharsPerLine := Round(Printer.PageWidth/CharWidth)-8;
 
-    PageCount := Text.Count div LinesPerPage;
-    if Text.Count mod LinesPerPage <> 0 then
-      Inc(PageCount);
-    
-    try
-      //print each page
-      for p := 1 to PageCount do
-      begin
-        PrintPage(Text, p);
+  Text:=AddLineBreaks(Text);  // break lines which are longer than <CharsPerLine>.
 
-        //create a new page
-        if p <> PageCount then
-          Printer.NewPage;
-      end;
-      
-      Printer.EndDoc;
-    except
-      on E:Exception do
-      begin
-        Printer.Abort;
-        raise Exception.Create(e.message);
-      end;
+  PageCount := Text.Count div LinesPerPage;
+  if Text.Count mod LinesPerPage <> 0 then Inc(PageCount);
+
+  try
+    //print each page
+    for p := 1 to PageCount do
+    begin
+      PrintPage(Text, p);
+
+      //create a new page
+      if p <> PageCount then
+        Printer.NewPage;
     end;
+
+    Printer.EndDoc;
+  except
+    on E:Exception do
+    begin
+      Printer.Abort;
+      raise Exception.Create(e.message);
+    end;
   end;
 end;
 
break_lines.patch (3,874 bytes)

samuel herzog

2010-07-14 21:48

developer   ~0039336

I have added a patch to break long lines.
This patch does cut the line exact at the calculated position, but does not analyze for line content. (means it will break words)

Yes, its better than the situation at the moment(lines are just cut off),but not perfect.

If someone likes to write a better method, then just go one!

Paul Ishenin

2010-07-15 04:52

manager   ~0039340

Actually DrawText function knows how to break words itself. I think if we replace TextOut with the DrawText with appropriate arguments we can get the better working solution.

samuel herzog

2010-07-15 06:35

developer   ~0039341

Will DrawText also keep control of Line-Numbering ;-)

Paul Ishenin

2010-07-15 12:57

manager   ~0039348

Depends on how you will use it. If you call the DrawText per line and accumulate the height then it is possible to get the next view:

1. Some long line with
wordwrap.
2. Some small line.
3. Another small line.

Andrea Mauri

2013-09-23 12:09

reporter   ~0070276

tested

Issue History

Date Modified Username Field Change
2009-04-08 15:14 Andrea Mauri New Issue
2009-04-08 15:14 Andrea Mauri Widgetset => Win32
2009-04-16 11:36 Vincent Snijders LazTarget => 1.0
2009-04-16 11:36 Vincent Snijders Status new => acknowledged
2009-04-16 11:36 Vincent Snijders Target Version => 1.0.0
2009-07-07 21:47 samuel herzog Note Added: 0028967
2010-07-12 10:28 Paul Ishenin Note Added: 0039280
2010-07-12 10:28 Paul Ishenin Status acknowledged => confirmed
2010-07-14 21:44 samuel herzog File Added: break_lines.patch
2010-07-14 21:48 samuel herzog Note Added: 0039336
2010-07-15 04:52 Paul Ishenin Note Added: 0039340
2010-07-15 06:35 samuel herzog Note Added: 0039341
2010-07-15 12:57 Paul Ishenin Note Added: 0039348
2011-10-08 18:46 Vincent Snijders LazTarget 1.0 => 1.2
2011-10-08 18:46 Vincent Snijders Target Version 1.0.0 => 1.2.0
2012-04-02 22:32 Martin Friebe Fixed in Revision => 36529
2012-04-02 22:32 Martin Friebe Status confirmed => resolved
2012-04-02 22:32 Martin Friebe Fixed in Version => 0.9.31 (SVN)
2012-04-02 22:32 Martin Friebe Resolution open => fixed
2012-04-02 22:32 Martin Friebe Assigned To => Martin Friebe
2013-09-23 12:09 Andrea Mauri Note Added: 0070276
2013-09-23 12:09 Andrea Mauri Status resolved => closed