Index: CHANGES.txt ================================================================== --- CHANGES.txt +++ CHANGES.txt @@ -1,9 +1,11 @@ Version [next] -[Feature] On Windows, Ghostscript replaced pdfroff. +[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. ------------------------------- Version 0.13.2 2024-04-30 Index: src/groffstudio.lpi ================================================================== --- src/groffstudio.lpi +++ src/groffstudio.lpi @@ -21,11 +21,11 @@ - + Index: src/unit1.lfm ================================================================== --- src/unit1.lfm +++ src/unit1.lfm @@ -11,12 +11,12 @@ LCLVersion = '3.99.0.0' OnClose = FormClose OnCreate = FormCreate object MainStatusBar: TStatusBar Left = 0 - Height = 18 - Top = 674 + Height = 23 + Top = 669 Width = 847 Panels = < item Text = 'file name with save status' Width = 200 @@ -34,47 +34,47 @@ object ExtendedNotebook1: TExtendedNotebook Left = 8 Height = 662 Top = 8 Width = 827 - ActivePage = tsEdit + ActivePage = tsSettings Anchors = [akTop, akLeft, akRight, akBottom] Style = tsFlatButtons - TabIndex = 0 + TabIndex = 1 TabOrder = 1 object tsEdit: TTabSheet Caption = 'edit a groff document' - ClientHeight = 626 - ClientWidth = 821 + ClientHeight = 631 + ClientWidth = 819 ParentFont = False object GroupBox1: TGroupBox Left = 10 Height = 66 - Top = 555 - Width = 801 + Top = 560 + Width = 799 Align = alBottom BorderSpacing.Left = 10 BorderSpacing.Right = 10 BorderSpacing.Bottom = 5 Caption = 'build' - ClientHeight = 39 - ClientWidth = 791 + ClientHeight = 46 + ClientWidth = 795 TabOrder = 0 object Label1: TLabel Left = 184 - Height = 16 + Height = 15 Top = -4 - Width = 83 + Width = 72 Caption = 'macro to use:' ParentColor = False end object cmbMacro: TComboBox Left = 184 - Height = 20 + Height = 23 Top = 16 Width = 100 - ItemHeight = 19 + ItemHeight = 15 Items.Strings = ( 'man' 'me' 'mm' 'mom' @@ -82,50 +82,50 @@ ) TabOrder = 0 Text = '[ select ]' end object Label2: TLabel - Left = 659 - Height = 16 + Left = 672 + Height = 15 Top = -4 - Width = 87 + Width = 78 Anchors = [akTop, akRight] Caption = 'output format:' ParentColor = False end object rdPs: TRadioButton - Left = 655 - Height = 18 + Left = 673 + Height = 19 Top = 16 - Width = 85 + Width = 71 Anchors = [akTop, akRight] Caption = 'PostScript' TabOrder = 1 end object rdPdf: TRadioButton - Left = 738 - Height = 18 + Left = 753 + Height = 19 Top = 16 - Width = 50 + Width = 39 Anchors = [akTop, akRight] Caption = 'PDF' TabOrder = 2 end object Label3: TLabel - Left = 400 - Height = 16 + Left = 419 + Height = 15 Top = -4 - Width = 91 + Width = 76 Anchors = [akTop, akRight] Caption = 'preprocessors:' ParentColor = False end object Label4: TLabel - Left = 533 - Height = 16 + Left = 544 + Height = 15 Top = -4 - Width = 41 + Width = 34 Anchors = [akTop, akRight] Caption = 'extras:' ParentColor = False end object btnBuild: TButton @@ -141,21 +141,21 @@ TabOrder = 3 OnClick = btnBuildClick end object chkLogFile: TCheckBox Left = 80 - Height = 18 + Height = 19 Hint = 'If enabled, a log file containing the groff output will be placed alongside the source document.' Top = 16 - Width = 79 + Width = 68 Caption = 'log to file' Enabled = False TabOrder = 4 end object chkBoxPreprocessors: TCheckComboBox - Left = 415 - Height = 20 + Left = 419 + Height = 22 Top = 15 Width = 100 Anchors = [akTop, akRight] ItemHeight = 16 Items.Strings = ( @@ -165,68 +165,66 @@ 'pic' 'refer' 'tbl' ) TabOrder = 5 - Text = '0' end object chkBoxExtras: TCheckComboBox - Left = 540 - Height = 20 + Left = 544 + Height = 22 Top = 15 Width = 100 Anchors = [akTop, akRight] ItemHeight = 16 Items.Strings = ( 'hdtbl' 'Pdfmark' ) TabOrder = 6 - Text = '0' end end object btnSaveGroff: TButton - Left = 736 + Left = 734 Height = 28 - Top = 523 + Top = 528 Width = 75 Anchors = [akRight, akBottom] Caption = 'save' Font.Style = [fsBold] ParentFont = False TabOrder = 1 OnClick = btnSaveGroffClick end object btnLoadGroff: TButton - Left = 655 + Left = 653 Height = 28 - Top = 523 + Top = 528 Width = 75 Anchors = [akRight, akBottom] Caption = 'load' Font.Style = [fsBold] ParentFont = False TabOrder = 2 OnClick = btnLoadGroffClick end object Label5: TLabel - Left = 128 - Height = 16 - Top = 535 - Width = 509 + Left = 197 + Height = 15 + Top = 541 + Width = 438 Anchors = [akRight, akBottom] Caption = 'note that everything build-related will be stored in the document''s storage directory' Font.Color = clBlue Font.Style = [fsItalic] ParentColor = False ParentFont = False end inline SynEdit1: TSynEdit Left = 10 - Height = 518 + Height = 523 Top = 0 - Width = 801 + Width = 799 Anchors = [akTop, akLeft, akRight, akBottom] Font.CharSet = 4 Font.Height = -13 Font.Name = 'Andale Mono' Font.Pitch = fpFixed @@ -737,85 +735,113 @@ end end end object tsSettings: TTabSheet Caption = 'groffstudio settings' - ClientHeight = 626 - ClientWidth = 821 + ClientHeight = 631 + ClientWidth = 819 object chkAutoSaveBuildSettings: TCheckBox Left = 0 - Height = 18 + Height = 19 Top = 16 - Width = 341 + Width = 309 Caption = 'save and restore the chosen build settings for next time' TabOrder = 0 end object btnSaveSettings: TButton - Left = 732 + Left = 730 Height = 25 - Top = 595 + Top = 600 Width = 91 Anchors = [akRight, akBottom] Caption = 'save settings' TabOrder = 1 OnClick = btnSaveSettingsClick end object Label14: TLabel Left = 0 - Height = 16 - Top = 80 - Width = 150 + Height = 15 + Top = 168 + Width = 129 Caption = 'yes, that''s all for now. :-)' ParentColor = False end object chkUpdateCheckOnStart: TCheckBox Left = 0 - Height = 18 + Height = 19 Top = 40 - Width = 190 + Width = 169 Caption = 'check for updates on startup' TabOrder = 2 + end + object GroupBox3: TGroupBox + Left = 0 + Height = 81 + Top = 72 + Width = 320 + Caption = 'pdf output settings' + ClientHeight = 61 + ClientWidth = 316 + TabOrder = 3 + object chkUseGhostscript: TCheckBox + Left = 8 + Height = 19 + Top = 8 + Width = 193 + Caption = 'use ghostscript instead of pdfroff' + TabOrder = 0 + OnChange = chkUseGhostscriptChange + end + object chkKeepPostscriptFile: TCheckBox + Left = 8 + Height = 19 + Top = 32 + Width = 264 + Caption = 'keep the postscript file after writing the pdf file' + Enabled = False + TabOrder = 1 + end end end object tsGroff: TTabSheet Caption = 'groff version' - ClientHeight = 626 - ClientWidth = 821 + ClientHeight = 631 + ClientWidth = 819 object GroupBox2: TGroupBox Left = 20 Height = 57 - Top = 561 - Width = 781 + Top = 566 + Width = 779 Align = alBottom BorderSpacing.Left = 20 BorderSpacing.Right = 20 BorderSpacing.Bottom = 8 Caption = 'groff for Windows' - ClientHeight = 30 - ClientWidth = 771 + ClientHeight = 37 + ClientWidth = 775 TabOrder = 0 object Label6: TLabel Left = 8 - Height = 16 + Height = 15 Top = 8 - Width = 125 + Width = 108 Caption = 'latest version online:' ParentColor = False end object edtOnlineGroffVersionWindows: TEdit Left = 136 - Height = 17 + Height = 15 Top = 8 - Width = 538 + Width = 542 Anchors = [akTop, akLeft, akRight] BorderStyle = bsNone Enabled = False TabOrder = 0 Text = 'fetching ...' end object btnDownloadGroffWindows: TButton - Left = 682 + Left = 686 Height = 25 Top = 5 Width = 80 Anchors = [akTop, akRight] Caption = 'download it' @@ -823,42 +849,42 @@ OnClick = btnDownloadGroffWindowsClick end end object Label7: TLabel Left = 8 - Height = 32 + Height = 30 Top = 8 - Width = 809 + Width = 807 Anchors = [akTop, akLeft, akRight] Caption = 'as you might guess, groffstudio requires a working installation of groff. this page performs the basic checks for you. note that on windows, everything is harder than it should. :-)' Constraints.MaxHeight = 582 ParentColor = False WordWrap = True end object Label9: TLabel Left = 8 - Height = 16 + Height = 15 Top = 56 - Width = 81 + Width = 70 Caption = 'groff version:' ParentColor = False end object edtGroffInstalledVersion: TEdit Left = 144 - Height = 17 + Height = 15 Top = 56 - Width = 673 + Width = 671 Anchors = [akTop, akLeft, akRight] BorderStyle = bsNone Enabled = False TabOrder = 1 end object lblTroffCommandNotFound: TLabel Left = 8 - Height = 48 + Height = 45 Top = 112 - Width = 808 + 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 ParentFont = False @@ -865,95 +891,95 @@ Visible = False WordWrap = True end object edtGroffstudioInstalledVersion: TEdit Left = 144 - Height = 17 + Height = 15 Top = 77 - Width = 673 + Width = 671 Anchors = [akTop, akLeft, akRight] BorderStyle = bsNone Enabled = False TabOrder = 2 end object Label10: TLabel Left = 8 - Height = 16 + Height = 15 Top = 77 - Width = 118 + Width = 103 Caption = 'groffstudio version:' ParentColor = False end end object tsAbout: TTabSheet Caption = 'about groffstudio' - ClientHeight = 626 - ClientWidth = 821 + ClientHeight = 631 + ClientWidth = 819 object lblAboutProductName: TLabel Left = 0 - Height = 53 + Height = 61 Top = 16 - Width = 297 + Width = 315 Caption = 'groffstudio x.y.z' Font.Color = clBlue Font.Height = -45 ParentColor = False ParentFont = False end object Label8: TLabel Left = 20 - Height = 16 + Height = 15 Top = 80 - Width = 246 + Width = 217 Caption = 'brought to you by tux0r and contributors' ParentColor = False end object Label11: TLabel Left = 0 - Height = 16 + Height = 15 Top = 128 - Width = 53 + Width = 45 Caption = 'Website:' Font.Style = [fsItalic] ParentColor = False ParentFont = False end object Label12: TLabel Left = 0 - Height = 16 + Height = 15 Top = 152 - Width = 69 + Width = 57 Caption = 'Repository:' Font.Style = [fsItalic] ParentColor = False ParentFont = False end object Label13: TLabel Left = 0 - Height = 16 + Height = 15 Top = 176 - Width = 119 + Width = 99 Caption = 'Repository (mirror):' Font.Style = [fsItalic] ParentColor = False ParentFont = False end object mLicense: TMemo Left = 0 Height = 418 Top = 216 - Width = 828 + Width = 826 Anchors = [akTop, akLeft, akRight] ScrollBars = ssAutoBoth TabOrder = 0 end object lblWebsite: TLabel Cursor = crHandPoint Left = 120 - Height = 16 + Height = 15 Top = 128 - Width = 113 + Width = 99 Caption = 'groff.tuxproject.de' Font.Color = clBlue Font.Style = [fsUnderline] ParentColor = False ParentFont = False @@ -960,13 +986,13 @@ OnClick = lblWebsiteClick end object lblFossilRepo: TLabel Cursor = crHandPoint Left = 120 - Height = 16 + Height = 15 Top = 152 - Width = 140 + Width = 121 Caption = 'code.rosaelefanten.org' Font.Color = clBlue Font.Style = [fsUnderline] ParentColor = False ParentFont = False @@ -973,13 +999,13 @@ OnClick = lblFossilRepoClick end object lblGithubRepo: TLabel Cursor = crHandPoint Left = 120 - Height = 16 + Height = 15 Top = 176 - Width = 68 + Width = 62 Caption = 'github.com' Font.Color = clBlue Font.Style = [fsUnderline] ParentColor = False ParentFont = False Index: src/unit1.pas ================================================================== --- src/unit1.pas +++ src/unit1.pas @@ -40,10 +40,12 @@ btnSaveGroff: TButton; btnLoadGroff: TButton; btnBuild: TButton; btnDownloadGroffWindows: TButton; btnSaveSettings: TButton; + chkKeepPostscriptFile: TCheckBox; + chkUseGhostscript: TCheckBox; chkBoxExtras: TCheckComboBox; chkBoxPreprocessors: TCheckComboBox; chkUpdateCheckOnStart: TCheckBox; chkLogFile: TCheckBox; chkAutoSaveBuildSettings: TCheckBox; @@ -52,10 +54,11 @@ edtGroffstudioInstalledVersion: TEdit; edtOnlineGroffVersionWindows: TEdit; ExtendedNotebook1: TExtendedNotebook; GroupBox1: TGroupBox; GroupBox2: TGroupBox; + GroupBox3: TGroupBox; iniStorage: TIniPropStorage; Label1: TLabel; Label10: TLabel; Label11: TLabel; Label12: TLabel; @@ -88,10 +91,11 @@ procedure btnBuildClick(Sender: TObject); procedure btnDownloadGroffWindowsClick(Sender: TObject); procedure btnLoadGroffClick(Sender: TObject); procedure btnSaveGroffClick(Sender: TObject); procedure btnSaveSettingsClick(Sender: TObject); + procedure chkUseGhostscriptChange(Sender: TObject); procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); procedure lblFossilRepoClick(Sender: TObject); procedure lblGithubRepoClick(Sender: TObject); procedure lblWebsiteClick(Sender: TObject); @@ -105,10 +109,11 @@ currentGroffFileName: string; unsavedChanges: boolean; {$IFDEF WINDOWS} latestGroffWindowsUrl: String; {$ENDIF} + // Settings: storeBuildSettings: boolean; updateCheck: boolean; public end; @@ -122,15 +127,13 @@ var MainForm: TMainForm; BuildWindow: TBuildStatusWindow; hasGroff: boolean; - GroffOutputVersion: string; - {$IFDEF WINDOWS} hasGhostscript: boolean; + GroffOutputVersion: string; ps2pdfOutput: string; - {$ENDIF} implementation {$R *.lfm} @@ -151,24 +154,32 @@ begin hasGroff := True; MainForm.edtGroffInstalledVersion.Text := GroffOutputVersion; end; - {$IFDEF WINDOWS} - // Try to find ps2pdf (Windows-only): + // Try to find ps2pdf: if pos('ps2pdf', ps2pdfOutput) = 0 then begin + {$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.exe in your %PATH%, so ' - + 'writing PDF files will not be supported.'); - hasGhostscript := False; + + 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} + hasGhostscript := False; + MainForm.chkUseGhostscript.Checked := False; + MainForm.chkUseGhostscript.Enabled := False; end else begin hasGhostscript := True; + {$IFDEF WINDOWS} MainForm.rdPdf.Enabled := True; + MainForm.chkUseGhostscript.Checked := True; + {$ENDIF} + MainForm.chkUseGhostscript.Enabled := True; end; - {$ENDIF} end; procedure TDetectGroffThread.Execute; begin FreeOnTerminate := True; @@ -177,10 +188,11 @@ RunCommand('cmd', ['/c', 'troff --version'], GroffOutputVersion, [], swoHIDE); RunCommand('cmd', ['/c', 'ps2pdf'], ps2pdfOutput, [], swoHIDE); {$ELSE} RunCommand('/bin/sh', ['-c', 'troff --version'], GroffOutputVersion, [], swoHIDE); + RunCommand('/bin/sh', ['-c', 'ps2pdf'], ps2pdfOutput, [], swoHIDE); {$ENDIF} Synchronize(@UpdateUI); end; { TMainForm } @@ -211,10 +223,16 @@ try mLicense.Lines.LoadFromStream(ResStream); finally ResStream.Free; end; + + {$IFNDEF WINDOWS} + // Ghostscript is not optional on Windows. + // On other platforms, let's use the stored setting. + chkUseGhostscript.Checked := iniStorage.ReadBoolean('UseGhostscript', False); + {$ENDIF} // Restore the settings iniStorage.Restore; storeBuildSettings := iniStorage.ReadBoolean('AutoSaveBuildSettings', False); chkAutoSaveBuildSettings.Checked := storeBuildSettings; @@ -397,11 +415,11 @@ {$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 then + if rdPdf.Checked and not chkUseGhostscript.Checked then begin buildOpts := buildOpts + ' -Tpdf'; if chkBoxExtras.Checked[1] then buildOpts := buildOpts + ' -mpdfmark'; outputFileName := currentGroffFilePath + '.pdf'; end @@ -419,20 +437,24 @@ // Build: buildSuccess := BuildWindow.BuildDocument(buildOpts, logFileName); {$IFDEF WINDOWS} if buildSuccess and hasGhostscript and rdPdf.Checked then + {$ELSE} + // On non-Windows systems, Ghostscript is entirely optional. + if buildSuccess and hasGhostscript and chkUseGhostscript.Checked and rdPdf.Checked then + {$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 then - DeleteFile(outputFileName); // get rid of the .ps file + + if buildSuccess and not chkKeepPostscriptFile.Checked then; + DeleteFile(outputFileName); // get rid of the .ps fil end; - {$ENDIF} if buildSuccess then MainStatusBar.Panels[1].Text := 'build successful' else MainStatusBar.Panels[1].Text := 'build problem'; @@ -515,12 +537,21 @@ // Store the IDE settings: iniStorage.WriteBoolean('AutoSaveBuildSettings', chkAutoSaveBuildSettings.Checked); iniStorage.WriteBoolean('AutoUpdateCheck', chkUpdateCheckOnStart.Checked); + // Store the PDF settings: + iniStorage.WriteBoolean('UseGhostscript', chkUseGhostscript.Checked); + iniStorage.WriteBoolean('KeepPsFile', chkKeepPostscriptFile.Checked); + iniStorage.Save; end; + +procedure TMainForm.chkUseGhostscriptChange(Sender: TObject); +begin + chkKeepPostscriptFile.Enabled := chkUseGhostscript.Checked; +end; procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction); var Reply, BoxStyle: integer; begin