Index: CHANGES.txt
==================================================================
--- CHANGES.txt
+++ CHANGES.txt
@@ -2,10 +2,11 @@
[Feature] On Windows, Ghostscript replaced pdfroff (thanks @wysardry).
[Bugfix] The groff detection logic was not as logical as it should have been.
[Feature] There is an option to keep both the .ps and the .pdf file now.
[Feature] Non-Windows users can choose to use Ghostscript (if installed) or pdfroff.
+[Feature] The installed Ghostscript version is now displayed in the settings.
-------------------------------
Version 0.13.2
2024-04-30
Index: src/buildoutputwindow.pas
==================================================================
--- src/buildoutputwindow.pas
+++ src/buildoutputwindow.pas
@@ -29,32 +29,32 @@
TBuildStatusWindow = class(TForm)
Label1: TLabel;
private
public
- function BuildDocument(CommandLine: String; LogFile: String): Boolean;
+ function BuildDocument(CommandLine: string; LogFile: string): boolean;
end;
var
- OutputText: String;
+ OutputText: string;
implementation
{$R *.lfm}
-function TBuildStatusWindow.BuildDocument(CommandLine: String; LogFile: String): Boolean;
+function TBuildStatusWindow.BuildDocument(CommandLine: string; LogFile: string): boolean;
var
- str: String;
+ str: string;
lh: TextFile;
- ret: Boolean;
+ ret: boolean;
begin
-{$IFDEF WINDOWS}
+ {$IFDEF WINDOWS}
ret := RunCommand('cmd', ['/c', CommandLine], str, [], swoHIDE);
{$ELSE}
ret := RunCommand('sh', ['-c', CommandLine], str, [], swoHIDE);
-{$ENDIF}
+ {$ENDIF}
if Length(str) = 0 then str := 'No problems have occurred. :-)';
if LogFile <> '' then
begin
@@ -72,6 +72,5 @@
Result := ret;
end;
end.
-
Index: src/groffstudio.lpi
==================================================================
--- src/groffstudio.lpi
+++ src/groffstudio.lpi
@@ -21,11 +21,11 @@
-
+
Index: src/groffstudio.lpr
==================================================================
--- src/groffstudio.lpr
+++ src/groffstudio.lpr
@@ -18,24 +18,27 @@
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
- {$ENDIF}
+{$ENDIF}
{$IFDEF HASAMIGA}
athreads,
- {$ENDIF}
+{$ENDIF}
Interfaces,
- Forms, lazcontrols, Unit1, Helpers, BuildOutputWindow;
+ Forms,
+ lazcontrols,
+ Unit1,
+ Helpers,
+ BuildOutputWindow;
-{$R *.res}
+ {$R *.res}
begin
- RequireDerivedFormResource:=True;
- Application.Scaled:=True;
+ RequireDerivedFormResource := True;
+ Application.Scaled := True;
Application.Initialize;
-
+
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
-
Index: src/helpers.pas
==================================================================
--- src/helpers.pas
+++ src/helpers.pas
@@ -23,41 +23,41 @@
Classes, SysUtils;
type
TGroffHelpers = class
public
- procedure VerStrCompare(newVersion, oldVersion: String; out comp: Integer);
-end;
+ procedure VerStrCompare(newVersion, oldVersion: string; out comp: integer);
+ end;
implementation
-procedure TGroffHelpers.VerStrCompare(newVersion, oldVersion: String; out comp: Integer);
-var
- nE1, nE2, nV1, nV2: Integer;
-
-begin
- if (Length(newVersion) > 0) or (Length(oldVersion) > 0) then begin
- nE1 := Pos('.', newVersion + '.');
- nE2 := Pos('.', oldVersion + '.');
- if nE1 > 1 then
- nV1 := StrToInt(Copy(newVersion,1,(nE1-1)))
- else
- nV1 := 0;
-
- if nE2 > 1 then
- nV2 := StrToInt(Copy(oldVersion,1,(nE2-1)))
- else
- nV2 := 0;
-
- if nV1 = nV2 then
- VerStrCompare(Copy(newVersion, nE1 + 1, Length(newVersion)), Copy(oldVersion, nE2 + 1, Length(oldVersion)), comp)
- else if nV1 > nV2 then
- comp := 1
- else if nV1 < nV2 then
- comp := -1;
- end
- else
- comp := 0;
+procedure TGroffHelpers.VerStrCompare(newVersion, oldVersion: string; out comp: integer);
+var
+ nE1, nE2, nV1, nV2: integer;
+begin
+ if (Length(newVersion) > 0) or (Length(oldVersion) > 0) then
+ begin
+ nE1 := Pos('.', newVersion + '.');
+ nE2 := Pos('.', oldVersion + '.');
+ if nE1 > 1 then
+ nV1 := StrToInt(Copy(newVersion, 1, (nE1 - 1)))
+ else
+ nV1 := 0;
+
+ if nE2 > 1 then
+ nV2 := StrToInt(Copy(oldVersion, 1, (nE2 - 1)))
+ else
+ nV2 := 0;
+
+ if nV1 = nV2 then
+ VerStrCompare(Copy(newVersion, nE1 + 1, Length(newVersion)),
+ Copy(oldVersion, nE2 + 1, Length(oldVersion)), comp)
+ else if nV1 > nV2 then
+ comp := 1
+ else if nV1 < nV2 then
+ comp := -1;
+ end
+ else
+ comp := 0;
end;
end.
-
Index: src/unit1.lfm
==================================================================
--- src/unit1.lfm
+++ src/unit1.lfm
@@ -6,11 +6,10 @@
Caption = 'groffstudio'
ClientHeight = 692
ClientWidth = 847
DefaultMonitor = dmPrimary
Position = poScreenCenter
- LCLVersion = '3.99.0.0'
OnClose = FormClose
OnCreate = FormCreate
object MainStatusBar: TStatusBar
Left = 0
Height = 23
@@ -34,14 +33,14 @@
object ExtendedNotebook1: TExtendedNotebook
Left = 8
Height = 662
Top = 8
Width = 827
- ActivePage = tsSettings
+ ActivePage = tsEdit
Anchors = [akTop, akLeft, akRight, akBottom]
Style = tsFlatButtons
- TabIndex = 1
+ TabIndex = 0
TabOrder = 1
object tsEdit: TTabSheet
Caption = 'edit a groff document'
ClientHeight = 631
ClientWidth = 819
@@ -879,11 +878,11 @@
TabOrder = 1
end
object lblTroffCommandNotFound: TLabel
Left = 8
Height = 45
- Top = 112
+ Top = 130
Width = 806
Anchors = [akTop, akLeft, akRight]
Caption = 'groff was not found. in order to use groffstudio, you absolutely need groff in your PATH variable. on unix and unix-like systems, you''ll need to edit the $PATH variable. on windows, i warmly recommend the Rapid Environment Editor for that.'#13#10'please exit groffstudio at your nearest convenience and adjust your PATH variables. then try again.'
Font.Color = clRed
ParentColor = False
@@ -906,10 +905,27 @@
Height = 15
Top = 77
Width = 103
Caption = 'groffstudio version:'
ParentColor = False
+ end
+ object Label15: TLabel
+ Left = 8
+ Height = 15
+ Top = 98
+ Width = 103
+ Caption = 'ghostscript version:'
+ end
+ object edtGhostscriptInstalledVersion: TEdit
+ Left = 144
+ Height = 15
+ Top = 98
+ Width = 671
+ Anchors = [akTop, akLeft, akRight]
+ BorderStyle = bsNone
+ Enabled = False
+ TabOrder = 3
end
end
object tsAbout: TTabSheet
Caption = 'about groffstudio'
ClientHeight = 631
Index: src/unit1.pas
==================================================================
--- src/unit1.pas
+++ src/unit1.pas
@@ -21,17 +21,17 @@
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls,
ExtCtrls, Buttons, ExtendedNotebook, SynEdit, fphttpclient, RegExpr, LCLIntf,
LCLType, IniPropStorage, ComboEx, Process, Helpers, fileinfo,
- {$IF DEFINED(WINDOWS)}
+{$IF DEFINED(WINDOWS)}
winpeimagereader, opensslsockets,
- {$ELSEIF DEFINED(DARWIN)}
+{$ELSEIF DEFINED(DARWIN)}
machoreader, ssockets, sslsockets, sslbase, opensslsockets,
- {$ELSEIF DEFINED(LINUX)}
+{$ELSEIF DEFINED(LINUX)}
elfreader,
- {$ENDIF}
+{$ENDIF}
BuildOutputWindow;
type
{ TMainForm }
@@ -50,10 +50,11 @@
chkLogFile: TCheckBox;
chkAutoSaveBuildSettings: TCheckBox;
cmbMacro: TComboBox;
edtGroffInstalledVersion: TEdit;
edtGroffstudioInstalledVersion: TEdit;
+ edtGhostscriptInstalledVersion: TEdit;
edtOnlineGroffVersionWindows: TEdit;
ExtendedNotebook1: TExtendedNotebook;
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
GroupBox3: TGroupBox;
@@ -62,10 +63,11 @@
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
Label13: TLabel;
Label14: TLabel;
+ Label15: TLabel;
lblGithubRepo: TLabel;
lblFossilRepo: TLabel;
lblWebsite: TLabel;
Label2: TLabel;
Label3: TLabel;
@@ -98,21 +100,21 @@
procedure FormCreate(Sender: TObject);
procedure lblFossilRepoClick(Sender: TObject);
procedure lblGithubRepoClick(Sender: TObject);
procedure lblWebsiteClick(Sender: TObject);
procedure SynEdit1Change(Sender: TObject);
- {$IFDEF DARWIN}
+{$IFDEF DARWIN}
procedure GetSocketHandler(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);
- {$ENDIF}
+{$ENDIF}
private
var
currentGroffFilePath: string;
currentGroffFileName: string;
unsavedChanges: boolean;
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
latestGroffWindowsUrl: String;
- {$ENDIF}
+{$ENDIF}
// Settings:
storeBuildSettings: boolean;
updateCheck: boolean;
public
@@ -130,10 +132,11 @@
BuildWindow: TBuildStatusWindow;
hasGroff: boolean;
hasGhostscript: boolean;
GroffOutputVersion: string;
ps2pdfOutput: string;
+ GhostscriptOutputVersion: string;
implementation
{$R *.lfm}
@@ -157,62 +160,73 @@
end;
// Try to find ps2pdf:
if pos('ps2pdf', ps2pdfOutput) = 0 then
begin
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
// ps2pdf is mandatory on Windows.
ShowMessage('On Windows, for creating PDF files, you need Ghostscript installed.'
+ LineEnding + 'Sadly, groffstudio could not find ps2pdf.bat in your %PATH%, so '
+ 'writing PDF files will not be supported. Please install Ghostscript and make sure '
+ 'that the folder that contains ps2pdf.bat is in your %PATH%.');
MainForm.rdPdf.Enabled := False;
- {$ENDIF}
+{$ENDIF}
hasGhostscript := False;
MainForm.chkUseGhostscript.Checked := False;
MainForm.chkUseGhostscript.Enabled := False;
- end else begin
+ end
+ else
+ begin
hasGhostscript := True;
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
MainForm.rdPdf.Enabled := True;
MainForm.chkUseGhostscript.Checked := True;
- {$ENDIF}
+{$ENDIF}
MainForm.chkUseGhostscript.Enabled := True;
end;
+
+ // Try to find Ghostscript, just for displaying the version:
+ if hasGhostscript then
+ MainForm.edtGhostscriptInstalledVersion.Text := GhostscriptOutputVersion
+ else
+ MainForm.edtGhostscriptInstalledVersion.Text := 'n/a';
end;
procedure TDetectGroffThread.Execute;
begin
FreeOnTerminate := True;
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
RunCommand('cmd', ['/c', 'troff --version'], GroffOutputVersion, [], swoHIDE);
+ RunCommand('cmd', ['/c', 'gs --version'], GhostscriptOutputVersion, [], swoHIDE);
RunCommand('cmd', ['/c', 'ps2pdf'], ps2pdfOutput, [], swoHIDE);
- {$ELSE}
+{$ELSE}
RunCommand('/bin/sh', ['-c', 'troff --version'], GroffOutputVersion,
[], swoHIDE);
+ RunCommand('/bin/sh', ['-c', 'gs --version'], GhostscriptOutputVersion,
+ [], swoHIDE);
RunCommand('/bin/sh', ['-c', 'ps2pdf'], ps2pdfOutput, [], swoHIDE);
- {$ENDIF}
+{$ENDIF}
Synchronize(@UpdateUI);
end;
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
var
OnlineVersionsFile: string;
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
reGroffVersion: TRegExpr;
- {$ENDIF}
+{$ENDIF}
reGroffStudioVersion: TRegExpr;
FileVerInfo: TFileVersionInfo;
HasVersionUpdate: integer;
GroffHelpers: TGroffHelpers;
ResStream: TResourceStream;
- {$IFDEF DARWIN}
+{$IFDEF DARWIN}
HTTPClient: TFPHttpClient;
- {$ENDIF}
+{$ENDIF}
begin
// What's the current running groff version?
TDetectGroffThread.Create(False);
// Default file name
@@ -224,29 +238,29 @@
mLicense.Lines.LoadFromStream(ResStream);
finally
ResStream.Free;
end;
- {$IFNDEF WINDOWS}
+{$IFNDEF WINDOWS}
// Ghostscript is not optional on Windows.
// On other platforms, let's use the stored setting.
chkUseGhostscript.Checked := iniStorage.ReadBoolean('UseGhostscript', False);
- {$ENDIF}
+{$ENDIF}
// Restore the settings
iniStorage.Restore;
storeBuildSettings := iniStorage.ReadBoolean('AutoSaveBuildSettings', False);
chkAutoSaveBuildSettings.Checked := storeBuildSettings;
- {$IF DEFINED(LINUX) OR DEFINED(BSD)}
+{$IF DEFINED(LINUX) OR DEFINED(BSD)}
// On platforms which probably use a package manager (currently, Linux and
// BSDs), the "update check" checkbox is disabled.
chkUpdateCheckOnStart.Enabled := False;
- {$ELSE}
+{$ELSE}
updateCheck := iniStorage.ReadBoolean('UpdateCheckOnStart', False);
chkUpdateCheckOnStart.Checked := updateCheck;
- {$ENDIF}
+{$ENDIF}
if storeBuildSettings then
begin
chkLogFile.Checked := iniStorage.ReadBoolean('BuildLogFile', False);
cmbMacro.Text := iniStorage.ReadString('BuildChosenMacro', '[ select ]');
@@ -272,11 +286,11 @@
lblAboutProductName.Caption :=
FileVerInfo.VersionStrings.Values['ProductName'] + ' ' +
FileVerInfo.VersionStrings.Values['FileVersion'];
MainStatusBar.Panels[2].Text := '';
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
if updateCheck then
begin
OnlineVersionsFile := TFPCustomHTTPClient.SimpleGet('https://groff.tuxproject.de/updates/versions.txt');
// 1. groff update check
@@ -303,11 +317,11 @@
end;
end else begin
edtOnlineGroffVersionWindows.Text := 'n/a';
btnDownloadGroffWindows.Enabled := False;
end;
- {$ELSE}
+{$ELSE}
// Non-Windows platforms won't need some of that.
{$IFDEF DARWIN}
// What's the latest available version?
try
if updateCheck then
@@ -335,11 +349,11 @@
if updateCheck then HTTPClient.Free;
end;
{$ENDIF}
edtOnlineGroffVersionWindows.Text := 'n/a';
btnDownloadGroffWindows.Enabled := False;
- {$ENDIF}
+{$ENDIF}
finally
FileVerInfo.Free;
end;
// Loaded file display
@@ -371,14 +385,14 @@
unsavedChanges := True;
end;
procedure TMainForm.btnDownloadGroffWindowsClick(Sender: TObject);
begin
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
// On other systems, the button is disabled anyway.
OpenURL(latestGroffWindowsUrl);
- {$ENDIF}
+{$ENDIF}
end;
procedure TMainForm.btnBuildClick(Sender: TObject);
var
buildSuccess: boolean;
@@ -410,11 +424,11 @@
if chkBoxPreprocessors.Checked[5] then buildOpts := buildOpts + ' -tbl';
if chkBoxExtras.Checked[0] then buildOpts := buildOpts + ' -mhdtbl';
// - PDF-specifics:
- {$IFNDEF WINDOWS}
+{$IFNDEF WINDOWS}
// On Windows, we use a two-step program:
// 1) Output to PostScript,
// 2) ps2pdf to PDF.
// This is because there is no pdfroff.exe. Requires Ghostscript.
if rdPdf.Checked and not chkUseGhostscript.Checked then
@@ -422,11 +436,11 @@
buildOpts := buildOpts + ' -Tpdf';
if chkBoxExtras.Checked[1] then buildOpts := buildOpts + ' -mpdfmark';
outputFileName := currentGroffFilePath + '.pdf';
end
else
- {$ENDIF}
+{$ENDIF}
outputFileName := currentGroffFilePath + '.ps';
// - Input file:
buildOpts := buildOpts + ' ' + currentGroffFilePath;
buildOpts := buildOpts + ' > ' + outputFileName;
@@ -435,25 +449,25 @@
if chkLogFile.Checked then logFileName := currentGroffFilePath + '.log';
// Build:
buildSuccess := BuildWindow.BuildDocument(buildOpts, logFileName);
- {$IFDEF WINDOWS}
+{$IFDEF WINDOWS}
if buildSuccess and hasGhostscript and rdPdf.Checked then
- {$ELSE}
+{$ELSE}
// On non-Windows systems, Ghostscript is entirely optional.
if buildSuccess and hasGhostscript and chkUseGhostscript.Checked and rdPdf.Checked then
- {$ENDIF}
+{$ENDIF}
begin
// Invoke ps2pdf:
buildOpts := 'ps2pdf';
// outputFileName is still the .ps file. Just use it as the input name.
buildOpts := buildOpts + ' ' + outputFileName;
buildSuccess := BuildWindow.BuildDocument(buildOpts, logFileName);
- if buildSuccess and not chkKeepPostscriptFile.Checked then;
- DeleteFile(outputFileName); // get rid of the .ps fil
+ if buildSuccess and not chkKeepPostscriptFile.Checked then
+ DeleteFile(outputFileName); // get rid of the .ps file
end;
if buildSuccess then
MainStatusBar.Panels[1].Text := 'build successful'
else