PB Editor, print command

Working on new editor enhancements?
Behnood
User
User
Posts: 72
Joined: Fri Apr 25, 2003 10:07 pm
Location: Australia
Contact:

PB Editor, print command

Post by Behnood »

it's not a big issue or a problem any way. but it will be good if we can print source code within the editor(almost all ide have this command in file menu)
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

Below is an addin tool to print the currently selected source code from within the IDE.

Compile the source code to an .exe file.
From the PB IDE take the menu path Tools -> Configure Tools -> New
Fill in details as follows:
Command line = Pathname to the .exe file (preferably in double quotes, but this may cause a 'Memory Write' error)
Arguments = "%TEMPFILE"
Name = Print Source Code
Event = Menu or Shortcut
Tick only the box 'Wait until tool quits'

To print your source code, ensure the printer is online then take the menu path Tools -> Print source Code

Here is the program to be compiled:

Code: Select all

; PrintFile  AKJ  15-Mar-06
; Print a text file whose path is given as the command line parameter
; Lines too wide for the page are cut and resulting overflow lines prepended with "¬"

;{ Constants
#program$="PrintFile"
#version$="1.1"
#file=1
; The following constants may be edited by the user:
#gap=5       ; Vertical gap (leading) in pixels between print lines
#Lmargin=200 ; Left hand margin in pixels
#Rmargin=100 ; Right margin in pixels
#Tmargin=200 ; Top margin in pixels
#Bmargin=0   ; Bottom margin in pixels
#indent=0    ; Additional left indentation in pixels for non-empty overflow lines
#continue$="¬" ; Continuation character shown at the start of non-empty overflow lines
;}

;{ Declarations
Declare PrintLine(ln$, indent, lineh, lpp)
EnableExplicit
Define pagew, pageh, lineh, lpp
Define path$, ln$, indent, cut, p, tmp$, indent$
;}

;{ Get text file's pathname
path$ = ProgramParameter()
If path$ = "": End: EndIf ; Quit without error message
If FileSize(path$)<=0: : End: EndIf ; Quit without error message
;}

;{ Initialise printer and get printer metrics
If DefaultPrinter()=0
  MessageRequester(#program$+" Error", "Cannot open default printing device")
  End
EndIf
StartPrinting("Text File")
pagew=PrinterPageWidth()-#Lmargin-#Rmargin
pageh=PrinterPageHeight()-#Tmargin-#Bmargin
StartDrawing(PrinterOutput())
; !!! DrawingFont(LoadFont(0, "Arial", 10))
lineh=TextHeight("bgj_~QX")+#gap
lpp=(pageh+#gap)/lineh ; Lines that will fit on a page
;}

;{ Print the file
If ReadFile(#file, path$)=0: End: EndIf ; Quit without error message
While Not Eof(#file)
  ln$=RTrim(ReadString(#file)) ; Preserve any whitespace on the left
  indent=0 ; Indentation (if any) beyond the left margin
  ; Does the line need to be split because it is too long for the page width?
  Repeat
    If TextWidth(ln$)<=pagew-indent ; If line will fit on page
      PrintLine(ln$, indent, lineh, lpp)
      ln$=""
    Else ; Line too wide for page
      cut=Len(ln$) ; Point [just before] where the line will eventually be cut
      Repeat ; Large steps
        cut-12 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=pagew-indent ; Until it will fit
      cut+12
      Repeat ; Small steps
        cut-1 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=pagew-indent ; Until it will fit
      ; Try not to split the last word, except at a hyphen
      For p=cut To cut-12 Step -1
        If FindString(" -"+#TAB$, Mid(ln$,p,1), 1) ; If whitespace or hyphen
          Break ; Found a better cut point
        EndIf
      Next p
      If p>=cut-12: cut=p: EndIf ; If a better cut point was found
      ; Now print and cut the line, removing trailing whitespace
      tmp$=RTrim(Left(ln$, cut))
      If indent ; If an overflow line
        If Len(tmp$) ; Do not print empty overflow (indented) lines      
          PrintLine(tmp$, indent, lineh, lpp)
        EndIf
      Else ; Not an overflow line
          indent$=Left(tmp$, Len(tmp$)-Len(LTrim(tmp$))) ; Remember the leading whitespace
          PrintLine(tmp$, indent, lineh, lpp) ; Print, even if empty
          indent=#indent ; Indentation (if any) beyond the left margin
      EndIf
      ln$=LTrim(Mid(ln$,cut+1,9999)) ; Build the overflow line
      If Len(ln$): ln$=indent$+#continue$+ln$: EndIf ; Prepend the same leading whitespace
    EndIf
  Until Len(ln$)=0
Wend
;}

;{ Windup
CloseFile(#file)
StopDrawing()
StopPrinting()
End
;}

Procedure PrintLine(ln$, indent, lineh, lpp)
Static line=0 ; Lines printed on the current page
Static y=#Tmargin ; Vertical print position
DrawText(#Lmargin+indent, y, ln$) ; "Print" the line
line+1: y+lineh
If line>=lpp ; If the current page is full
  line=0: y=#Tmargin
  NewPrinterPage()
EndIf
EndProcedure
Note that on the printout, if a long source line is wrapped onto multiple printer lines, each of those printer lines (except the first) is prefixed with the continuation character "¬".
Anthony Jordan
yrret
User
User
Posts: 26
Joined: Wed May 26, 2004 9:05 pm

Post by yrret »

Thanks for the code. I missed that feature too. But your code got me
going, as I wanted to add Line #'s and Page #'s to the print out too, as
it is easier to reference when examining the code with those #'s.
I modified your code to include Line #'s and Page #'s, plus some
other commented stuff, and compiled with version 4.0 beta 7.
I'm new to Purebasic and don't quit understand the your use of indent
the way you did, so I did it another way. It works on both ver 3.94
and 4.0 as far as printing goes. But both your code and mine, cause 4.0
to crash after it is done printing, which may be a beta bug.

Error: An attemped read or write to/from an address to which that process
isn't allowed.

Here is the code if any one wants these features also.

Code: Select all

 
;PrintFile  AKJ  15-Mar-06
; PrintFile2  yrret  16-Mar-06  added Line #'s and Page #'s, plus a few other commented edits.
; Print a text file whose path is given as the command line parameter
; Lines too wide for the page are cut and resulting overflow lines prepended with "¬"

;{ Constants
#program$="PrintFile"
#version$="1.1"
#file=1
; The following constants may be edited by the user:
#gap=5       ; Vertical gap (leading) in pixels between print lines
#Lmargin=200 ; Left hand margin in pixels
#Rmargin=260 ; Right margin in pixels        (adj for line #'s)
#Tmargin=200 ; Top margin in pixels
#Bmargin=0   ; Bottom margin in pixels
#continue$="¬" ; Continuation character shown at the start of non-empty overflow lines
;}

;{ Declarations
Declare PrintLine(ln$, indent, lineh, lpp, pgline)
EnableExplicit
Define lnum, lnum$, nonum, pgn
Define pagew, pageh, lineh, lpp, pgline
Define path$, ln$, indent, cut, p, tmp$, indent$
;}

;{ Get text file's pathname
path$ = ProgramParameter()

If path$ = "": End: EndIf ; Quit without error message
If FileSize(path$)<=0: : End: EndIf ; Quit without error message
;}

;{ Initialise printer and get printer metrics
If DefaultPrinter()=0
  MessageRequester(#program$+" Error", "Cannot open default printing device")
  End
EndIf
StartPrinting("Text File")
pagew=PrinterPageWidth()-#Lmargin-#Rmargin    ;Return the width of the drawing area, in pixel.
pageh=PrinterPageHeight()-#Tmargin-#Bmargin   ;Return the height of the drawing area, in pixel.
StartDrawing(PrinterOutput())
; !!! DrawingFont(LoadFont(0, "Arial", 10))
lineh=TextHeight("bgj_~QX")+#gap
lpp=((pageh+#gap)/lineh)-3                    ; Lines that will fit on a page.  Make room for Page #'s
;}

;{ Print the file
If ReadFile(#file, path$)=0: End: EndIf ; Quit without error message
;add line numbers
lnum=1
pgline=0
nonum=0
pgn=1
indent=0 ; Use only for Page # positioning

While Not Eof(#file)
  ln$=RTrim(ReadString(#file)) ; Preserve any whitespace on the left
  
  If nonum=0 And Left(ln$,1)=" "        ;Double indent space as it makes code look better.
    indent$=Left(ln$,Len(ln$)-Len(LTrim(ln$)))
    ln$=indent$+ln$
  EndIf
     
  ; Does the line need to be split because it is too long for the page width?
  Repeat
    lnum$=Str(lnum)                ;space line #'s for 5 positions
    If Len(lnum$)<5
      lnum$=Left(lnum$+"    ",5)
    EndIf                         ;add two spaces between line # and text
    lnum$=lnum$+"  "
    If TextWidth(ln$)<=pagew ; If line will fit on page
      If pgline=lpp ; If the current page is full
        PrintLine(" ", indent, lineh, lpp, pgline)
        pgline+1
        PrintLine("Page "+Str(pgn), indent+2000, lineh, lpp, pgline)
        pgline=0
        pgn+1
      EndIf
      If nonum=0
        PrintLine(lnum$+ln$, indent, lineh, lpp, pgline)
        pgline+1
      Else
        PrintLine(ln$, indent, lineh, lpp, pgline)
        pgline+1
        nonum=0
      EndIf
      ln$=""
      
    Else ; Line too wide for page
      
      ;first get line indent and add line number spaces to it.
      indent$=Left(ln$,Len(ln$)-Len(LTrim(ln$)))+"     "+Space(Len(Str(lnum)))
      
      cut=Len(ln$) ; Point [just before] where the line will eventually be cut
      Repeat ; Large steps
        cut-12 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=pagew ; Until it will fit
      cut+12
      Repeat ; Small steps
        cut-1 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=pagew ; Until it will fit
      ; Try not to split the last word, except at a hyphen
      For p=cut To cut-12 Step -1
        If FindString(" -_"+#TAB$, Mid(ln$,p,1), 1) ; If whitespace or hyphen
          Break ; Found a better cut point
        EndIf
      Next p
      If p>=cut-12: cut=p: EndIf ; If a better cut point was found
      
      ;Now print and cut the first part of the line.
      tmp$=Left(ln$, cut-1)
      If pgline=lpp ; If the current page is full
        PrintLine(" ", indent, lineh, lpp, pgline)
        pgline+1
        PrintLine("Page "+Str(pgn), indent+2000, lineh, lpp, pgline)
        pgline=0
        pgn+1
      EndIf
      PrintLine(lnum$+tmp$, indent, lineh, lpp, pgline)
      pgline+1
      
      ;Now build the overflow line
      ln$=Mid(ln$,cut,Len(ln$)-cut) 
      If Len(ln$)
        ln$=indent$+#continue$+ln$
        nonum=1    
      EndIf 
    EndIf
    
    If nonum=0
      lnum+1
    EndIf
  Until Len(ln$)=0
Wend
;}

;{ Windup
CloseFile(#file)
If pgline<lpp+1       ;print page # on last page at bottom of page.
  Repeat
    PrintLine(" ", indent, lineh, lpp, pgline)
    pgline+1
  Until pgline>lpp
  pgline-1      ;don't need new print page, as this is the last page.
  PrintLine("Page "+Str(pgn), indent+2000, lineh, lpp, pgline)
EndIf
StopDrawing()
StopPrinting()
End
;}

Procedure PrintLine(ln$, indent, lineh, lpp, pgline)
;Static pgline=0 ; Lines printed on the current page
Static y=#Tmargin ; Vertical print position
DrawText(#Lmargin+indent, y, ln$) ; "Print" the line
y+lineh
If pgline>lpp ; If the current page is full
  y=#Tmargin
  NewPrinterPage()
EndIf
EndProcedure

;Note that on the printout, If a long source line is wrapped onto multiple printer lines, 
;each of those printer lines (except the first) is prefixed with the continuation character "¬".]
Forgot to add.
I didn't write the program to also print the file name on the page top.
I just put the name and comments at the source beginning under
;comments instead. So you may want to do that before you print
out some code later, so you know what it is from.
Last edited by yrret on Thu Mar 16, 2006 9:35 pm, edited 1 time in total.
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

and here another method with Syntax-Highlightning: http://www.purebasic.fr/german/viewtopic.php?t=5159
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

I have amended my code to include most/all of yrret's additional ideas.

However most of the responsibility for generating page numbers and line numbers is now within the procedure PrintLine() which - I think - greatly simplifies the logic.

The continuation character has been changed from "¬" to "" (i.e. omitted) as it is now redundant, because the absence of line numbers on continuation lines now makes them easy to detect.

Code: Select all

; PrintFile  AKJ  17-Mar-06
; Print a text file whose path is given as the command line parameter
; Lines too wide for the page are cut
; Page numbers and line numbers are printed (as suggested by yrret)

;{ Constants
#program$="PrintFile"
#version$="2.0"
#file=1
; The following constants may be edited by the user:
#gap=5       ; Vertical gap (leading) in pixels between print lines
#Lmargin=200 ; Left hand margin in pixels
#Rmargin=100 ; Right margin in pixels
#Tmargin=180 ; Top margin in pixels
#Bmargin=0   ; Bottom margin in pixels
#continue$="" ; Continuation character shown at the start of non-empty overflow lines
;}

;{ Declarations
Declare PrintLine(ln$, overflow, linenumw, lineh, lpp)
EnableExplicit
Define pagew, pageh, linenumw, printw, lineh, lpp
Define path$, ln$, cut, p, tmp$, whitespace$, overflow
;}

;{ Get text file's pathname
path$ = ProgramParameter()
If path$ = "": End: EndIf ; Quit without error message
If FileSize(path$)<=0: : End: EndIf ; Quit without error message
;}

;{ Initialise printer and get printer metrics
If DefaultPrinter()=0
  MessageRequester(#program$+" Error", "Cannot open default printing device")
  End
EndIf
StartPrinting("Text File")
pagew=PrinterPageWidth()-#Lmargin-#Rmargin
pageh=PrinterPageHeight()-#Tmargin-#Bmargin
StartDrawing(PrinterOutput())
; !!! DrawingFont(LoadFont(0, "Arial", 10))
linenumw=TextWidth("1000  ") ; Width of line number column
printw=pagew-linenumw ; Width available for printing file text
lineh=TextHeight("bgj_~QX")+#gap
lpp=(pageh+#gap)/lineh ; Lines that will fit on a page
;}

;{ Print the file
If ReadFile(#file, path$)=0: End: EndIf ; Quit without error message
While Not Eof(#file)
  ln$=RTrim(ReadString(#file)) ; Preserve any whitespace on the left
  overflow=#False ; Not a continuation line
  ; Does the line need to be split because it is too long for the page width?
  Repeat
    If TextWidth(ln$)<=printw ; If line will fit on page
      PrintLine(ln$, overflow, linenumw, lineh, lpp)
      ln$=""
    Else ; Line too wide for page
      cut=Len(ln$) ; Point [just before] where the line will eventually be cut
      Repeat ; Large steps
        cut-12 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      cut+12
      Repeat ; Small steps
        cut-1 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      ; Try not to split the last word, except at a hyphen
      For p=cut To cut-12 Step -1
        If FindString(" -_"+#TAB$, Mid(ln$,p,1), 1) ; If whitespace, hyphen or underscore
          Break ; Found a better cut point
        EndIf
      Next p
      If p>=cut-12: cut=p: EndIf ; If a better cut point was found
      ; Now print and cut the line, removing trailing whitespace
      tmp$=RTrim(Left(ln$, cut))
      If overflow ; If a continuation line
        If Len(tmp$) ; Do not print empty continuation lines      
          PrintLine(tmp$, overflow, linenumw, lineh, lpp)
        EndIf
      Else ; Not an overflow line
          whitespace$=Left(tmp$, Len(tmp$)-Len(LTrim(tmp$))) ; Remember the leading whitespace
          PrintLine(tmp$, overflow, linenumw, lineh, lpp) ; Print, even if empty
          overflow=#True
      EndIf
      ln$=LTrim(Mid(ln$,cut+1,9999)) ; Build the next continuation line
      If Len(ln$): ln$=whitespace$+#continue$+ln$: EndIf ; Prepend the same leading whitespace
    EndIf
  Until Len(ln$)=0
Wend
;}

;{ Windup
CloseFile(#file)
StopDrawing()
StopPrinting()
End
;}

Procedure PrintLine(ln$, overflow, linenumw, lineh, lpp)
; Print the line in ln$
; overflow is True if the line is a continuation line, printed without a line number
; linenumw is the width in pixels of the line number column
; lineh is the vertical distance in pixels between lines
; lpp is the number of lines that will physically print on a page
Static pagenum=0 ; Current page number
Static linenum=0 ; Current line number within source file
Static line=0 ; Lines printed on the current page
Static y=#Tmargin ; Vertical print position
If line=0 ; If starting a new page
  pagenum+1
  DrawText(#Lmargin, y, "Page "+Str(pagenum)) ; Print page number
  line=2: y+lineh*2 ; Leave a blank line
EndIf
If Not overflow ; If not an overflow line
  linenum+1
  DrawText(#Lmargin+TextWidth("1999")-TextWidth(Str(linenum)), y, Str(linenum)) ; "Print" linenumber
EndIf
DrawText(#Lmargin+linenumw, y, ln$) ; "Print" text to the right of the line number column
line+1: y+lineh
If line>=lpp ; If the current page is full
  line=0: y=#Tmargin
  NewPrinterPage()
EndIf
EndProcedure
Anthony Jordan
yrret
User
User
Posts: 26
Joined: Wed May 26, 2004 9:05 pm

Post by yrret »

Thank you for provide version 2.0 :D
I like how you simplified it, and how you set up that new proceedure to
handle it. I also as a new person to this language, appreciate how well you
commented the different sections, to help explain what was being done.
yrret
User
User
Posts: 26
Joined: Wed May 26, 2004 9:05 pm

Post by yrret »

First of all I'm not trying to compete with you akj, as you can probably
program circles around me. I liked your code, but the fun of learning is
to improve on it. So I added page # from and to, and filename, and
build #, if using PureBUILD Build, in print out.
Example in printing this code: (1st line page 1)
Page 1 of 5 D:\Purebasic4_0\work\print_file.pb build # 6
(and last page)
Page 5 of 5 D:\Purebasic4_0\work\print_file.pb build # 6

I also re-added double indent space as it makes code look better, like you
see it in the IDE.

Code: Select all

; PrintFile  AKJ  17-Mar-06  
; version 2.0
; Print a text file whose path is given as the command line parameter
; Lines too wide for the page are cut
; Page numbers and line numbers are printed (as suggested by yrret)
;
; PrintFile  yrret  17-Mar-06  
; version 2.0a
; Added page from and to, and filename in print out.
; If using PureBUILD Build, I also added the build #
; Also added indent$ to make indent spacing like in editor and to make code easier to read.
;
;Use as an addin tool to print the currently selected source code from within the IDE.
;Compile the source code (with PB 4.0) to an .exe file.
;From the PB IDE take the menu path Tools -> Configure Tools -> New
;Fill in details as follows:
;Command line = Pathname To the .exe file (Don't use double quotes, as this causes a 'Memory Write' error)
;
;*********
;Arguments = "%FILE"   
;***  NOTE: Remains empty if file has not yet been saved yet.  So always save file before printing. ***
;*********
;
;Name = Print Source Code
;Event = Menu Or Shortcut
;Tick only the box 'Wait until tool quits'
;To print your source code, ensure the printer is online then take the menu path Tools -> Print source Code

;{ Constants
#program$="PrintFile"
#version$="2.0"
#file=1
; The following constants may be edited by the user:
#gap=5       ; Vertical gap (leading) in pixels between print lines
#Lmargin=200 ; Left hand margin in pixels
#Rmargin=100 ; Right margin in pixels
#Tmargin=180 ; Top margin in pixels
#Bmargin=0   ; Bottom margin in pixels
#continue$="" ; Continuation character shown at the start of non-empty overflow lines
;}

;{ Declarations
Declare PrintLine(ln$, overflow, linenumw, lineh, lpp, pt, name$)
EnableExplicit
Define pagew, pageh, linenumw, printw, lineh, lpp
Define path$, ln$, cut, p, tmp$, whitespace$, indent$, overflow
Define ln, pt, name$
;}

;{ Get text file's pathname
path$ = ProgramParameter()
If path$ = "": End: EndIf ; Quit without error message
If FileSize(path$)<=0: : End: EndIf ; Quit without error message
;}

;{ Initialise printer and get printer metrics
If DefaultPrinter()=0
  MessageRequester(#program$+" Error", "Cannot open default printing device")
  End
EndIf
StartPrinting("Text File")
pagew=PrinterPageWidth()-#Lmargin-#Rmargin
pageh=PrinterPageHeight()-#Tmargin-#Bmargin
StartDrawing(PrinterOutput())
; !!! DrawingFont(LoadFont(0, "Arial", 10))
linenumw=TextWidth("1000  ") ; Width of line number column
printw=pagew-linenumw ; Width available for printing file text
lineh=TextHeight("bgj_~QX")+#gap
lpp=(pageh+#gap)/lineh ; Lines that will fit on a page
;}

;{ Get total page #'s, file name and build # if using PureBUILD.
;You need to do basically the same as for printing, but without printing,
;to make sure you have the same number of lines to calculate the total pages.
ln=3 ;start from 3 here to account for starting from 0 and skipping to 2 later in the PrintLine proceedure.
pt=1
name$ = path$    ;Get file name and path, and also print with page #'s.
;name$ = GetFilePart(path$) ;use this if you just want file name
If ReadFile(#file, path$)=0: End: EndIf ; Quit without error message
While Not Eof(#file)
  ln$=RTrim(ReadString(#file)) ; Preserve any whitespace on the left
  
  If FindString(ln$, "; PureBUILD Build =", 1) ; If using PureBUILD Build, get build # and add to name$
    If FindString(ln$, "PureBUILD Plugin", 1)  ; Make sure your using correct data.  eg: if printing this file. 
      name$=name$+"      build # "+Mid(ln$,FindString(ln$, "PureBUILD Build =", 1)+18, 9999)
      name$=Left(name$, FindString(name$, "[", 1)-1)
    EndIf 
  EndIf
  
    overflow=#False ; Not a continuation line
  ; Does the line need to be split because it is too long for the page width?
  Repeat
    If TextWidth(ln$)<=printw ; If line will fit on page
      ln+1
      ln$=""
    Else ; Line too wide for page
      cut=Len(ln$) ; Point [just before] where the line will eventually be cut
      Repeat ; Large steps
        cut-12 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      cut+12
      Repeat ; Small steps
        cut-1 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      ; Try not to split the last word, except at a hyphen
      For p=cut To cut-12 Step -1
        If FindString(" -_"+#TAB$, Mid(ln$,p,1), 1) ; If whitespace, hyphen or underscore
          Break ; Found a better cut point
        EndIf
      Next p
      If p>=cut-12: cut=p: EndIf ; If a better cut point was found
      ; Now print and cut the line, removing trailing whitespace
      tmp$=RTrim(Left(ln$, cut))
      If overflow ; If a continuation line
        If Len(tmp$) ; Do not print empty continuation lines     
          ln+1
        EndIf
      Else ; Not an overflow line
          whitespace$=Left(tmp$, Len(tmp$)-Len(LTrim(tmp$))) ; Remember the leading whitespace
          ln+1
          overflow=#True
      EndIf
      ln$=LTrim(Mid(ln$,cut+1,9999)) ; Build the next continuation line
      If Len(ln$): ln$=whitespace$+#continue$+ln$: EndIf ; Prepend the same leading whitespace
    EndIf
    If ln>=lpp ; If the current page is full
      ln=1
      pt+1
    EndIf
  Until Len(ln$)=0
Wend

CloseFile(#file)
Delay(1000)     ;give time for file to close before re-openning
;}


;{ Print the file
If ReadFile(#file, path$)=0: End: EndIf ; Quit without error message
While Not Eof(#file)
  ln$=RTrim(ReadString(#file)) ; Preserve any whitespace on the left
  
  
  If Not overflow And Left(ln$,1)=" "        ;Added double indent space as it makes code look better.  yrret 03/17/06
    indent$=Left(ln$,Len(ln$)-Len(LTrim(ln$)))
    ln$=indent$+ln$
  EndIf
  
  overflow=#False ; Not a continuation line
  ; Does the line need to be split because it is too long for the page width?
  Repeat
    If TextWidth(ln$)<=printw ; If line will fit on page
      PrintLine(ln$, overflow, linenumw, lineh, lpp, pt, name$)
      ln$=""
    Else ; Line too wide for page
      cut=Len(ln$) ; Point [just before] where the line will eventually be cut
      Repeat ; Large steps
        cut-12 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      cut+12
      Repeat ; Small steps
        cut-1 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      ; Try not to split the last word, except at a hyphen
      For p=cut To cut-12 Step -1
        If FindString(" -_"+#TAB$, Mid(ln$,p,1), 1) ; If whitespace, hyphen or underscore
          Break ; Found a better cut point
        EndIf
      Next p
      If p>=cut-12: cut=p: EndIf ; If a better cut point was found
      ; Now print and cut the line, removing trailing whitespace
      tmp$=RTrim(Left(ln$, cut))
      If overflow ; If a continuation line
        If Len(tmp$) ; Do not print empty continuation lines     
          PrintLine(tmp$, overflow, linenumw, lineh, lpp, pt, name$)
        EndIf
      Else ; Not an overflow line
          whitespace$=Left(tmp$, Len(tmp$)-Len(LTrim(tmp$))) ; Remember the leading whitespace
          PrintLine(tmp$, overflow, linenumw, lineh, lpp, pt, name$) ; Print, even if empty
          overflow=#True
      EndIf
      ln$=LTrim(Mid(ln$,cut+1,9999)) ; Build the next continuation line
      If Len(ln$): ln$=whitespace$+#continue$+ln$: EndIf ; Prepend the same leading whitespace
    EndIf
  Until Len(ln$)=0
Wend
;}

;{ Windup
CloseFile(#file)
StopDrawing()
StopPrinting()
End
;}

Procedure PrintLine(ln$, overflow, linenumw, lineh, lpp, pt, name$)
; Print the line in ln$
; overflow is True if the line is a continuation line, printed without a line number
; linenumw is the width in pixels of the line number column
; lineh is the vertical distance in pixels between lines
; lpp is the number of lines that will physically print on a page
Static pagenum=0 ; Current page number
Static linenum=0 ; Current line number within source file
Static line=0 ; Lines printed on the current page
Static y=#Tmargin ; Vertical print position
If line=0 ; If starting a new page
  pagenum+1
  DrawText(#Lmargin, y, "Page "+Str(pagenum)+" of "+Str(pt)+"        "+name$) ; Print page number of page total and file name.
  line=2: y+lineh*2 ; Leave a blank line
EndIf
If Not overflow ; If not an overflow line
  linenum+1
  DrawText(#Lmargin+TextWidth("1999")-TextWidth(Str(linenum)), y, Str(linenum)) ; "Print" linenumber
EndIf
DrawText(#Lmargin+linenumw, y, ln$) ; "Print" text to the right of the line number column
line+1: y+lineh
If line>=lpp ; If the current page is full
  line=0: y=#Tmargin
  NewPrinterPage()
EndIf
EndProcedure

;
; PureBUILD Build = 6 [generated by PureBUILD Plugin]
Thanks again for the great code.
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

Yrret says:
the fun of learning is to improve on it
I certainly agree. The fun is in the 'doing' not the 'viewing'.

Based on yrret's suggestions, I have enhanced my version of the program still further, but only making one pass of the input text file whilst yrret's code makes two passes. I have not incorporated his suggestion of "double indent spacing", because I think his coding is unnecessary as the spacing on the printer is - I believe - identical to that in the IDE, provided the IDE Editor preference 'Use real Tab (ASCII 9)' is not ticked.

Also, the program will now print just selected text rather than the whole file if the text selection in the IDE is 2 lines long or more.

*** Important ***: In the configuration of this IDE add-in tool, the command line arguments box must now be set to:
"%SELECTION" "%TEMPFILE" "%FILE"

Code: Select all

; PrintFile  AKJ  19-Mar-06  PB Add-in Tool
; Print a text file whose path is given as a command line parameter
; Lines too wide for the page are wrapped onto subsequent print lines
; Page titles, page numbers & line numbers are printed (as suggested by yrret)
; Any PureBUILD build number is included in the title  (as suggested by yrret)
; If multiple text lines are selected, only those lines are printed
; The add-in tool configuration arguments must be "%SELECTION" "%TEMPFILE" "%FILE"

;{ Constants
#program$="PrintFile"
#version$="2.3"
#file=1
; The following constants may be edited by the user:
#gap=5       ; Vertical gap (leading) in pixels between print lines
#Lmargin=200 ; Left hand margin in pixels
#Rmargin=100 ; Right margin in pixels
#Tmargin=180 ; Top margin in pixels
#Bmargin=0   ; Bottom margin in pixels
#continue$="" ; Continuation character shown at the start of non-empty overflow lines
;}

;{ Declarations
EnableExplicit
Global NewList lines$() ; Buffer for storing the print lines prior to printing
Define selection$ ; Limits of selected text
Define linefrst, linelast ; First/last selected text lines
Define path$="" ; Pathname of file to be printed
Define pagew, pageh ; Page dimensions in pixels sans margins
Define linenumw ; Width in pixels of the line number column
Define printw ; Width available for printing file text (excludes the line number column)
Define lineh ; Vertical distance in pixels between lines
Define lpp ; Lines per page available for printing (including title lines)
Define pages ; Number of pages that will physically be printed
Define pagenumx ; Start position of the right-aligned page number
Define title$="" ; Title (excluding page number) at the top of each page
Define titlew ; Width in pixels available for the title
Define ln$ ; The text line currently being processed/printed
Define tmp$ ; Temporary string variable
Define whitespace$ ; A copy of any whitespace at the start of the current line
Define cut; Position at which a text line must be cut to fit on the page
Define p ; Position within text strings and command line parameter number
Define overflow$ ; Flag: "#" (line has a line number) or "+" (continuation line)
Define build$="" ; PureBUILD build number
Define pagenum=0 ; Current page number
Define linenum=0 ; Current printed line number within source file
Define line=0 ; Lines printed on the current page
Define y=#Tmargin ; Vertical print position on the current page
;}

;{ Identify text selection from the command line
selection$=ProgramParameter(0)
linefrst=Val(StringField(selection$, 1, "x"))
linelast=Val(StringField(selection$, 3, "x"))
; If the selection ends at the beginning of a line, treat it as ending on the previous line 
If StringField(selection$, 4, "x")="1": linelast-1: EndIf
; If the selection is confined to one line, treat it as no selection
If linefrst>=linelast: linefrst=1: linelast=99999: EndIf
;}

;{ Get file pathnames from the command line
; path$ will point to the latest in-memory version of the file
; title$ will contain the program's pathname if it has ever been saved
For p=1 To 2
  tmp$ = ProgramParameter(p)
  If FindString(LCase(tmp$), "\compilers\tempfile.pb", 1) ; If a temporary filename
    path$=tmp$
  ElseIf Len(tmp$)
    title$=tmp$
  EndIf
Next p
If path$="": End: EndIf ; Quit without error message
If FileSize(path$)<=0: : End: EndIf ; Quit without error message
;}

;{ Initialise printer and get printer metrics
If DefaultPrinter()=0
  MessageRequester(#program$+" Error", "Cannot open default printing device")
  End
EndIf
StartPrinting("Text File")
pagew=PrinterPageWidth()-#Lmargin-#Rmargin
pageh=PrinterPageHeight()-#Tmargin-#Bmargin
StartDrawing(PrinterOutput())
; !!! DrawingFont(LoadFont(0, "Arial", 10))
linenumw=TextWidth("1999  ") ; Width of line number column
printw=pagew-linenumw ; Width available for printing file text
lineh=TextHeight("bgj_~QX")+#gap
lpp=(pageh+#gap)/lineh ; Lines that will fit on a page
;}

;{ Build print lines in a linked list
If ReadFile(#file, path$)=0: End: EndIf ; Quit without error message
While Not Eof(#file)
  ln$=RTrim(ReadString(#file)) ; Preserve any whitespace on the left
  ; If using PureBUILD, try to get the build number
  If FindString(LCase(ln$), "purebuild plugin", 1)
    p=FindString(LCase(ln$), "purebuild build =", 1)
    If p
      build$="   Build "+Str(Val(Mid(ln$,p+17,9999)))
    EndIf
  EndIf
  overflow$="#" ; Not a continuation line
  linenum+1
  ; Does the line need to be split because it is too long for the page width?
  Repeat
    If TextWidth(ln$)<=printw ; If line will fit on page
      If linenum>=linefrst And linenum<=linelast
        AddElement(lines$()): lines$()=overflow$+ln$
      EndIf
      ln$=""
    Else ; Line too wide for page
      cut=Len(ln$) ; Point [just before] where the line will eventually be cut
      Repeat ; Large steps
        cut-12 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      cut+12
      Repeat ; Small steps
        cut-1 ; New trial cut point
      Until TextWidth(Left(ln$,cut))<=printw ; Until it will fit
      ; Try not to split the last word, except at a hyphen
      For p=cut To cut-12 Step -1
        If FindString(" -_"+#TAB$, Mid(ln$,p,1), 1) ; If whitespace, hyphen or underscore
          cut=p: Break ; Found a better cut point
        EndIf
      Next p
      ; Now cut the line, removing trailing whitespace
      tmp$=RTrim(Left(ln$, cut))
      If overflow$="+" ; If a continuation line
        If Len(tmp$) ; Ignore empty continuation lines
          If linenum>=linefrst And linenum<=linelast
            AddElement(lines$()): lines$()=overflow$+tmp$
          EndIf
        EndIf
      Else ; Not a continuation line
        whitespace$=Left(tmp$, Len(tmp$)-Len(LTrim(tmp$))) ; Remember the leading whitespace
        If linenum>=linefrst And linenum<=linelast
          AddElement(lines$()): lines$()=overflow$+tmp$
        EndIf
        overflow$="+"
      EndIf
      ln$=LTrim(Mid(ln$,cut+1,9999)) ; Build the next continuation line
      If Len(ln$): ln$=whitespace$+#continue$+ln$: EndIf ; Prepend the same leading whitespace
    EndIf
  Until Len(ln$)=0
Wend
CloseFile(#file)
;}

;{ Print the lines
; Calculate the number of pages to be printed
pages=(CountList(lines$())-1)/(lpp-2)+1 ; The -2 allows for the title lines on each page
; Calculate the start position of the [nearly] right-aligned page number
pagenumx=#Lmargin+pagew-TextWidth(Str(pages)+" of "+Str(pages))
; Fit the title [and build number] into the width available
title$+build$
titlew=pagenumx-#Lmargin-40
If TextWidth(title$)>titlew ; If too wide
  titlew-TextWidth("...")
  Repeat
    title$=Mid(title$, FindString(title$,"\",2), 999) ; Truncate at left-most "\"
  Until TextWidth(title$)<=titlew ; Until it will fit
  title$="..."+title$ ; Prepend "..."
EndIf
; Now do the printing
linenum=linefrst-1
ForEach lines$()
  If line=0 ; If starting a new page
    pagenum+1
    DrawText(#Lmargin, y, title$) ; Print title [and build number]
    DrawText(pagenumx, y, Str(pagenum)+" of "+Str(pages)) ; Print page number
    line=2: y+lineh*2 ; Leave a blank line
  EndIf
  If Left(lines$(),1)="#" ; If not a continuation line
    linenum+1
    DrawText(#Lmargin+TextWidth("1999")-TextWidth(Str(linenum)), y, Str(linenum)) ; "Print" linenumber
  EndIf
  DrawText(#Lmargin+linenumw, y, Mid(lines$(),2,9999)) ; "Print" text to the right of the line number column
  line+1: y+lineh
  If line>=lpp ; If the current page is full
    line=0: y=#Tmargin
    NewPrinterPage()
  EndIf
Next lines$()
StopDrawing()
StopPrinting()
End
}
Last edited by akj on Mon Mar 20, 2006 10:45 am, edited 2 times in total.
Anthony Jordan
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

Please note that I have edited my previous post so the program can now print either selected text or the entire file.

In the configuration of this IDE add-in tool, the command line arguments box must now be set to:
"%SELECTION" "%TEMPFILE" "%FILE"
Anthony Jordan
Post Reply