ADDED CHANGES.txt
Index: CHANGES.txt
==================================================================
--- /dev/null
+++ CHANGES.txt
@@ -0,0 +1,4 @@
+Version 0.9.9.0
+2022-02-24
+
+[Feature] First working version.
ADDED CODE_OF_CONDUCT.md
Index: CODE_OF_CONDUCT.md
==================================================================
--- /dev/null
+++ CODE_OF_CONDUCT.md
@@ -0,0 +1,52 @@
+# Code of Merit
+
+1. The project creators, lead developers, core team, constitute
+the managing members of the project and have final say in every decision
+of the project, technical or otherwise, including overruling previous decisions.
+There are no limitations to this decisional power.
+
+2. Contributions are an expected result of your membership on the project.
+Don't expect others to do your work or help you with your work forever.
+
+3. All members have the same opportunities to seek any challenge they want
+within the project.
+
+4. Authority or position in the project will be proportional
+to the accrued contribution. Seniority must be earned.
+
+5. Software is evolutive: the better implementations must supersede lesser
+implementations. Technical advantage is the primary evaluation metric.
+
+6. This is a space for technical prowess; topics outside of the project
+will not be tolerated.
+
+7. Non technical conflicts will be discussed in a separate space. Disruption
+of the project will not be allowed.
+
+8. Individual characteristics, including but not limited to,
+body, sex, sexual preference, race, language, religion, nationality,
+or political preferences are irrelevant in the scope of the project and
+will not be taken into account concerning your value or that of your contribution
+to the project.
+
+9. Discuss or debate the idea, not the person.
+
+10. There is no room for ambiguity: Ambiguity will be met with questioning;
+further ambiguity will be met with silence. It is the responsibility
+of the originator to provide requested context.
+
+11. If something is illegal outside the scope of the project, it is illegal
+in the scope of the project. This Code of Merit does not take precedence over
+governing law.
+
+12. This Code of Merit governs the technical procedures of the project not the
+activities outside of it.
+
+13. Participation on the project equates to agreement of this Code of Merit.
+
+14. No objectives beyond the stated objectives of this project are relevant
+to the project. Any intent to deviate the project from its original purpose
+of existence will constitute grounds for remedial action which may include
+expulsion from the project.
+
+This document is the Code of Merit, version 1.0.
ADDED LICENSE
Index: LICENSE
==================================================================
--- /dev/null
+++ LICENSE
@@ -0,0 +1,364 @@
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)
+Version 1.1
+
+1. Definitions.
+
+ 1.1. "Contributor" means each individual or entity that creates or
+ contributes to the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Software, prior Modifications used by a Contributor (if any), and
+ the Modifications made by that particular Contributor.
+
+ 1.3. "Covered Software" means (a) the Original Software, or (b)
+ Modifications, or (c) the combination of files containing Original
+ Software with files containing Modifications, in each case including
+ portions thereof.
+
+ 1.4. "Executable" means the Covered Software in any form other than
+ Source Code.
+
+ 1.5. "Initial Developer" means the individual or entity that first
+ makes Original Software available under this License.
+
+ 1.6. "Larger Work" means a work which combines Covered Software or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.7. "License" means this document.
+
+ 1.8. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means the Source Code and Executable form of
+ any of the following:
+
+ A. Any file that results from an addition to, deletion from or
+ modification of the contents of a file containing Original Software
+ or previous Modifications;
+
+ B. Any new file that contains any part of the Original Software or
+ previous Modification; or
+
+ C. Any new file that is contributed or otherwise made available
+ under the terms of this License.
+
+ 1.10. "Original Software" means the Source Code and Executable form
+ of computer software code that is originally released under this
+ License.
+
+ 1.11. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.12. "Source Code" means (a) the common form of computer software
+ code in which modifications are made and (b) associated
+ documentation included in or with such code.
+
+ 1.13. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of,
+ this License. For legal entities, "You" includes any entity which
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants.
+
+ 2.1. The Initial Developer Grant.
+
+ Conditioned upon Your compliance with Section 3.1 below and subject
+ to third party intellectual property claims, the Initial Developer
+ hereby grants You a world-wide, royalty-free, non-exclusive license:
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer, to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Software (or portions thereof), with or without Modifications,
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using or selling of
+ Original Software, to make, have made, use, practice, sell, and
+ offer for sale, and/or otherwise dispose of the Original Software
+ (or portions thereof).
+
+ (c) The licenses granted in Sections 2.1(a) and (b) are effective on
+ the date Initial Developer first distributes or otherwise makes the
+ Original Software available to a third party under the terms of this
+ License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: (1) for code that You delete from the Original Software, or
+ (2) for infringements caused by: (i) the modification of the
+ Original Software, or (ii) the combination of the Original Software
+ with other software or devices.
+
+ 2.2. Contributor Grant.
+
+ Conditioned upon Your compliance with Section 3.1 below and subject
+ to third party intellectual property claims, each Contributor hereby
+ grants You a world-wide, royalty-free, non-exclusive license:
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof), either on an
+ unmodified basis, with other Modifications, as Covered Software
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or selling
+ of Modifications made by that Contributor either alone and/or in
+ combination with its Contributor Version (or portions of such
+ combination), to make, use, sell, offer for sale, have made, and/or
+ otherwise dispose of: (1) Modifications made by that Contributor (or
+ portions thereof); and (2) the combination of Modifications made by
+ that Contributor with its Contributor Version (or portions of such
+ combination).
+
+ (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective
+ on the date Contributor first distributes or otherwise makes the
+ Modifications available to a third party.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: (1) for any code that Contributor has deleted from the
+ Contributor Version; (2) for infringements caused by: (i) third
+ party modifications of Contributor Version, or (ii) the combination
+ of Modifications made by that Contributor with other software
+ (except as part of the Contributor Version) or other devices; or (3)
+ under Patent Claims infringed by Covered Software in the absence of
+ Modifications made by that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Availability of Source Code.
+
+ Any Covered Software that You distribute or otherwise make available
+ in Executable form must also be made available in Source Code form
+ and that Source Code form must be distributed only under the terms
+ of this License. You must include a copy of this License with every
+ copy of the Source Code form of the Covered Software You distribute
+ or otherwise make available. You must inform recipients of any such
+ Covered Software in Executable form as to how they can obtain such
+ Covered Software in Source Code form in a reasonable manner on or
+ through a medium customarily used for software exchange.
+
+ 3.2. Modifications.
+
+ The Modifications that You create or to which You contribute are
+ governed by the terms of this License. You represent that You
+ believe Your Modifications are Your original creation(s) and/or You
+ have sufficient rights to grant the rights conveyed by this License.
+
+ 3.3. Required Notices.
+
+ You must include a notice in each of Your Modifications that
+ identifies You as the Contributor of the Modification. You may not
+ remove or alter any copyright, patent or trademark notices contained
+ within the Covered Software, or any notices of licensing or any
+ descriptive text giving attribution to any Contributor or the
+ Initial Developer.
+
+ 3.4. Application of Additional Terms.
+
+ You may not offer or impose any terms on any Covered Software in
+ Source Code form that alters or restricts the applicable version of
+ this License or the recipients' rights hereunder. You may choose to
+ offer, and to charge a fee for, warranty, support, indemnity or
+ liability obligations to one or more recipients of Covered Software.
+ However, you may do so only on Your own behalf, and not on behalf of
+ the Initial Developer or any Contributor. You must make it
+ absolutely clear that any such warranty, support, indemnity or
+ liability obligation is offered by You alone, and You hereby agree
+ to indemnify the Initial Developer and every Contributor for any
+ liability incurred by the Initial Developer or such Contributor as a
+ result of warranty, support, indemnity or liability terms You offer.
+
+ 3.5. Distribution of Executable Versions.
+
+ You may distribute the Executable form of the Covered Software under
+ the terms of this License or under the terms of a license of Your
+ choice, which may contain terms different from this License,
+ provided that You are in compliance with the terms of this License
+ and that the license for the Executable form does not attempt to
+ limit or alter the recipient's rights in the Source Code form from
+ the rights set forth in this License. If You distribute the Covered
+ Software in Executable form under a different license, You must make
+ it absolutely clear that any terms which differ from this License
+ are offered by You alone, not by the Initial Developer or
+ Contributor. You hereby agree to indemnify the Initial Developer and
+ every Contributor for any liability incurred by the Initial
+ Developer or such Contributor as a result of any such terms You offer.
+
+ 3.6. Larger Works.
+
+ You may create a Larger Work by combining Covered Software with
+ other code not governed by the terms of this License and distribute
+ the Larger Work as a single product. In such a case, You must make
+ sure the requirements of this License are fulfilled for the Covered
+ Software.
+
+4. Versions of the License.
+
+ 4.1. New Versions.
+
+ Oracle is the initial license steward and may publish revised and/or
+ new versions of this License from time to time. Each version will be
+ given a distinguishing version number. Except as provided in Section
+ 4.3, no one other than the license steward has the right to modify
+ this License.
+
+ 4.2. Effect of New Versions.
+
+ You may always continue to use, distribute or otherwise make the
+ Covered Software available under the terms of the version of the
+ License under which You originally received the Covered Software. If
+ the Initial Developer includes a notice in the Original Software
+ prohibiting it from being distributed or otherwise made available
+ under any subsequent version of the License, You must distribute and
+ make the Covered Software available under the terms of the version
+ of the License under which You originally received the Covered
+ Software. Otherwise, You may also choose to use, distribute or
+ otherwise make the Covered Software available under the terms of any
+ subsequent version of the License published by the license steward.
+
+ 4.3. Modified Versions.
+
+ When You are an Initial Developer and You want to create a new
+ license for Your Original Software, You may create and use a
+ modified version of this License if You: (a) rename the license and
+ remove any references to the name of the license steward (except to
+ note that the license differs from this License); and (b) otherwise
+ make it clear that the license contains terms which differ from this
+ License.
+
+5. DISCLAIMER OF WARRANTY.
+
+ COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+ INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE
+ IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+ NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF
+ THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE
+ DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY
+ OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING,
+ REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+ ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS
+ AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+6. TERMINATION.
+
+ 6.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to
+ cure such breach within 30 days of becoming aware of the breach.
+ Provisions which, by their nature, must remain in effect beyond the
+ termination of this License shall survive.
+
+ 6.2. If You assert a patent infringement claim (excluding
+ declaratory judgment actions) against Initial Developer or a
+ Contributor (the Initial Developer or Contributor against whom You
+ assert such claim is referred to as "Participant") alleging that the
+ Participant Software (meaning the Contributor Version where the
+ Participant is a Contributor or the Original Software where the
+ Participant is the Initial Developer) directly or indirectly
+ infringes any patent, then any and all rights granted directly or
+ indirectly to You by such Participant, the Initial Developer (if the
+ Initial Developer is not the Participant) and all Contributors under
+ Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice
+ from Participant terminate prospectively and automatically at the
+ expiration of such 60 day notice period, unless if within such 60
+ day period You withdraw Your claim with respect to the Participant
+ Software against such Participant either unilaterally or pursuant to
+ a written agreement with Participant.
+
+ 6.3. If You assert a patent infringement claim against Participant
+ alleging that the Participant Software directly or indirectly
+ infringes any patent where such claim is resolved (such as by
+ license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 6.4. In the event of termination under Sections 6.1 or 6.2 above,
+ all end user licenses that have been validly granted by You or any
+ distributor hereunder prior to termination (excluding licenses
+ granted to You by any distributor) shall survive termination.
+
+7. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
+ INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
+ COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE
+ TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
+ CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
+ LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER
+ FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
+ LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
+ POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT
+ APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+ PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+ LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR
+ LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION
+ AND LIMITATION MAY NOT APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS.
+
+ The Covered Software is a "commercial item," as that term is defined
+ in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" (as that term is defined at 48 C.F.R. ยง
+ 252.227-7014(a)(1)) and "commercial computer software documentation"
+ as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent
+ with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4
+ (June 1995), all U.S. Government End Users acquire Covered Software
+ with only those rights set forth herein. This U.S. Government Rights
+ clause is in lieu of, and supersedes, any other FAR, DFAR, or other
+ clause or provision that addresses Government rights in computer
+ software under this License.
+
+9. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ the law of the jurisdiction specified in a notice contained within
+ the Original Software (except to the extent applicable law, if any,
+ provides otherwise), excluding such jurisdiction's conflict-of-law
+ provisions. Any litigation relating to this License shall be subject
+ to the jurisdiction of the courts located in the jurisdiction and
+ venue specified in a notice contained within the Original Software,
+ with the losing party responsible for costs, including, without
+ limitation, court costs and reasonable attorneys' fees and expenses.
+ The application of the United Nations Convention on Contracts for
+ the International Sale of Goods is expressly excluded. Any law or
+ regulation which provides that the language of a contract shall be
+ construed against the drafter shall not apply to this License. You
+ agree that You alone are responsible for compliance with the United
+ States export administration regulations (and the export control
+ laws and regulation of any other countries) when You use, distribute
+ or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+----------------------------------------------------------------------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
+DISTRIBUTION LICENSE (CDDL)
+
+For Covered Software in this distribution, this License shall be
+governed by the laws of Germany (excluding conflict-of-law
+provisions).
+
+Any litigation relating to this License shall be subject to the
+jurisdiction and the courts of Braunschweig, Germany, with venue lying
+in Braunschweig, Germany.
ADDED README.md
Index: README.md
==================================================================
--- /dev/null
+++ README.md
@@ -0,0 +1,43 @@
+# groffstudio: An IDE for groff.
+
+You know what was missing with `groff`? A good alternative to TeXstudio. Here we go.
+
+## Screenshot
+
+![Screenshot](https://i.imgur.com/ispa8x4.png)
+
+## Features
+
+* Written in Lazarus (Free Pascal).
+
+ * Should be cross-platform (but Windows support is mediocre yet).
+
+* Can produce PS and PDF files.
+
+* Can handle some macros.
+
+## License
+
+`groffstudio` is free software under the terms of the CDDL-1.1. Feel free to help me with development. I'll happily grant you access to the upstream repository if you are good.
+
+## Links
+
+* Website: [groff.tuxproject.de](https://groff.tuxproject.de)
+
+* Repository: [code.rosaelefanten.org](https://code.rosaelefanten.org/groffstudio)
+
+ * Mirror: [GitHub](https://github.com/dertuxmalwieder/groffstudio)
+
+## Donations
+
+Writing this software and keeping it available is eating some of the time which most people would spend with their friends. Naturally, I absolutely accept financial compensation.
+
+* PayPal: [GebtmireuerGeld](https://paypal.me/gebtmireuergeld)
+* Liberapay: [Cthulhux](https://liberapay.com/Cthulhux/donate)
+
+Thank you.
+
+## Contact
+
+* Twitter: [@tux0r](https://twitter.com/tux0r)
+* Matrix: @Cthulhux:matrix.org
ADDED src/buildoutputwindow.lfm
Index: src/buildoutputwindow.lfm
==================================================================
--- /dev/null
+++ src/buildoutputwindow.lfm
@@ -0,0 +1,20 @@
+object BuildStatusWindow: TBuildStatusWindow
+ Left = 2050
+ Height = 367
+ Top = 149
+ Width = 432
+ BorderStyle = bsDialog
+ Caption = 'build output'
+ ClientHeight = 367
+ ClientWidth = 432
+ LCLVersion = '2.2.0.4'
+ object mBuildOutput: TMemo
+ Left = 0
+ Height = 367
+ Top = 0
+ Width = 432
+ Align = alClient
+ ScrollBars = ssAutoBoth
+ TabOrder = 0
+ end
+end
ADDED src/buildoutputwindow.pas
Index: src/buildoutputwindow.pas
==================================================================
--- /dev/null
+++ src/buildoutputwindow.pas
@@ -0,0 +1,86 @@
+unit BuildOutputWindow;
+
+{
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.1 only
+ (the "License"). You may not use this file except in compliance
+ with the License.
+
+ See the file LICENSE in this distribution for details.
+ A copy of the CDDL is also available via the Internet at
+ https://spdx.org/licenses/CDDL-1.1.html
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the contents of the LICENSE file from this
+ distribution.
+}
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Process;
+
+type
+
+ { TBuildStatusWindow }
+
+ TBuildStatusWindow = class(TForm)
+ mBuildOutput: TMemo;
+ private
+
+ public
+ function BuildDocument(CommandLine: String): Boolean;
+
+ end;
+
+var
+ OutputText: String;
+ BuildStatusWindow: TBuildStatusWindow;
+
+implementation
+
+{$R *.lfm}
+
+// TODO: not working
+function TBuildStatusWindow.BuildDocument(CommandLine: String): Boolean;
+var
+ p: TProcess;
+ AStringList: TStringList;
+begin
+ p := TProcess.Create(nil);
+ p.Options := p.Options + [poWaitOnExit, poUsePipes];
+
+ AStringList := TStringList.Create;
+{$IFDEF WINDOWS}
+ p.Executable := 'cmd';
+ p.Parameters.Add('/c');
+{$ENDIF}
+{$IFDEF UNIX}
+ p.Executable := 'sh';
+ p.Parameters.Add('-c');
+{$ENDIF}
+ p.Parameters.Add(CommandLine);
+ p.Execute;
+
+ AStringList.LoadFromStream(p.Output);
+ p.Free;
+
+ mBuildOutput.Text := AStringList.Text;
+ AStringList.Free;
+
+ if Length(mBuildOutput.Text) = 0 then begin
+ // We don't have any output. We can close the window.
+ BuildStatusWindow.Close;
+ result := True
+ end
+ else begin
+ // There was some output. Chances are that warnings occurred.
+ // Keep it shown.
+ result := False
+ end;
+end;
+
+end.
+
ADDED src/groffstudio.ico
Index: src/groffstudio.ico
==================================================================
--- /dev/null
+++ src/groffstudio.ico
cannot compute difference between binary files
ADDED src/groffstudio.lpi
Index: src/groffstudio.lpi
==================================================================
--- /dev/null
+++ src/groffstudio.lpi
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
ADDED src/groffstudio.lpr
Index: src/groffstudio.lpr
==================================================================
--- /dev/null
+++ src/groffstudio.lpr
@@ -0,0 +1,25 @@
+program groffstudio;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}
+ cthreads,
+ {$ENDIF}
+ {$IFDEF HASAMIGA}
+ athreads,
+ {$ENDIF}
+ Interfaces, // this includes the LCL widgetset
+ Forms, lazcontrols, Unit1, Helpers, BuildOutputWindow
+ { you can add units after this };
+
+{$R *.res}
+
+begin
+ RequireDerivedFormResource:=True;
+ Application.Scaled:=True;
+ Application.Initialize;
+ Application.CreateForm(TMainForm, MainForm);
+ Application.Run;
+end.
+
ADDED src/groffstudio.lps
Index: src/groffstudio.lps
==================================================================
--- /dev/null
+++ src/groffstudio.lps
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED src/helpers.pas
Index: src/helpers.pas
==================================================================
--- /dev/null
+++ src/helpers.pas
@@ -0,0 +1,63 @@
+unit Helpers;
+
+{
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.1 only
+ (the "License"). You may not use this file except in compliance
+ with the License.
+
+ See the file LICENSE in this distribution for details.
+ A copy of the CDDL is also available via the Internet at
+ https://spdx.org/licenses/CDDL-1.1.html
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the contents of the LICENSE file from this
+ distribution.
+}
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+type
+ TGroffHelpers = class
+ public
+ 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;
+end;
+
+end.
+
ADDED src/unit1.lfm
Index: src/unit1.lfm
==================================================================
--- /dev/null
+++ src/unit1.lfm
@@ -0,0 +1,987 @@
+object MainForm: TMainForm
+ Left = 1932
+ Height = 692
+ Top = 147
+ Width = 861
+ Caption = 'groffstudio'
+ ClientHeight = 692
+ ClientWidth = 861
+ OnClose = FormClose
+ OnCreate = FormCreate
+ LCLVersion = '2.2.0.4'
+ object MainStatusBar: TStatusBar
+ Left = 0
+ Height = 23
+ Top = 669
+ Width = 861
+ Panels = <
+ item
+ Text = 'file name with save status'
+ Width = 200
+ end
+ item
+ Text = 'build successful?'
+ Width = 120
+ end
+ item
+ Text = 'update available'
+ Width = 120
+ end>
+ SimplePanel = False
+ end
+ object ExtendedNotebook1: TExtendedNotebook
+ Left = 10
+ Height = 662
+ Top = 8
+ Width = 841
+ ActivePage = tsEdit
+ Anchors = [akTop, akLeft, akRight, akBottom]
+ Style = tsFlatButtons
+ TabIndex = 0
+ TabOrder = 1
+ object tsEdit: TTabSheet
+ Caption = 'edit a groff document'
+ ClientHeight = 631
+ ClientWidth = 833
+ ParentFont = False
+ object GroupBox1: TGroupBox
+ Left = 10
+ Height = 65
+ Top = 561
+ Width = 813
+ Align = alBottom
+ BorderSpacing.Left = 10
+ BorderSpacing.Right = 10
+ BorderSpacing.Bottom = 5
+ Caption = 'build'
+ ClientHeight = 45
+ ClientWidth = 809
+ TabOrder = 0
+ object Label1: TLabel
+ Left = 112
+ Height = 15
+ Top = -4
+ Width = 72
+ Caption = 'macro to use:'
+ end
+ object cmbMacro: TComboBox
+ Left = 112
+ Height = 23
+ Top = 14
+ Width = 100
+ ItemHeight = 15
+ Items.Strings = (
+ 'man'
+ 'me'
+ 'mm'
+ 'mom'
+ 'ms'
+ )
+ TabOrder = 0
+ Text = '[ select ]'
+ end
+ object Label2: TLabel
+ Left = 686
+ Height = 15
+ Top = -4
+ Width = 78
+ Anchors = [akTop, akRight]
+ Caption = 'output format:'
+ end
+ object rdPs: TRadioButton
+ Left = 686
+ Height = 19
+ Top = 14
+ Width = 73
+ Anchors = [akTop, akRight]
+ Caption = 'PostScript'
+ OnChange = rdPsChange
+ TabOrder = 1
+ end
+ object rdPdf: TRadioButton
+ Left = 766
+ Height = 19
+ Top = 14
+ Width = 41
+ Anchors = [akTop, akRight]
+ Caption = 'PDF'
+ OnChange = rdPdfChange
+ TabOrder = 2
+ end
+ object Label3: TLabel
+ Left = 304
+ Height = 15
+ Top = -4
+ Width = 76
+ Anchors = [akTop, akRight]
+ Caption = 'preprocessors:'
+ end
+ object chkEqn: TCheckBox
+ Left = 360
+ Height = 19
+ Top = 14
+ Width = 40
+ Anchors = [akTop, akRight]
+ Caption = 'eqn'
+ TabOrder = 3
+ end
+ object chkPic: TCheckBox
+ Left = 446
+ Height = 19
+ Top = 14
+ Width = 36
+ Anchors = [akTop, akRight]
+ Caption = 'pic'
+ TabOrder = 4
+ end
+ object chkTbl: TCheckBox
+ Left = 534
+ Height = 19
+ Top = 14
+ Width = 34
+ Anchors = [akTop, akRight]
+ Caption = 'tbl'
+ TabOrder = 5
+ end
+ object chkGrn: TCheckBox
+ Left = 404
+ Height = 19
+ Top = 14
+ Width = 38
+ Anchors = [akTop, akRight]
+ Caption = 'grn'
+ TabOrder = 6
+ end
+ object chkChem: TCheckBox
+ Left = 304
+ Height = 19
+ Top = 14
+ Width = 50
+ Anchors = [akTop, akRight]
+ Caption = 'chem'
+ TabOrder = 7
+ end
+ object chkRefer: TCheckBox
+ Left = 486
+ Height = 19
+ Top = 14
+ Width = 44
+ Anchors = [akTop, akRight]
+ Caption = 'refer'
+ TabOrder = 8
+ end
+ object Label4: TLabel
+ Left = 587
+ Height = 15
+ Top = -4
+ Width = 34
+ Anchors = [akTop, akRight]
+ Caption = 'extras:'
+ end
+ object chkPdfMark: TCheckBox
+ Left = 587
+ Height = 19
+ Top = 14
+ Width = 65
+ Anchors = [akTop, akRight]
+ Caption = 'Pdfmark'
+ Enabled = False
+ TabOrder = 9
+ end
+ object btnBuild: TButton
+ Left = 16
+ Height = 29
+ Top = 8
+ Width = 75
+ Caption = 'build'
+ Color = clLime
+ Enabled = False
+ Font.Style = [fsBold, fsItalic]
+ OnClick = btnBuildClick
+ ParentFont = False
+ TabOrder = 10
+ end
+ end
+ object btnSaveGroff: TButton
+ Left = 748
+ Height = 28
+ Top = 530
+ Width = 75
+ Anchors = [akRight, akBottom]
+ Caption = 'save'
+ Font.Style = [fsBold]
+ OnClick = btnSaveGroffClick
+ ParentFont = False
+ TabOrder = 1
+ end
+ object btnLoadGroff: TButton
+ Left = 667
+ Height = 28
+ Top = 530
+ Width = 75
+ Anchors = [akRight, akBottom]
+ Caption = 'load'
+ Font.Style = [fsBold]
+ OnClick = btnLoadGroffClick
+ ParentFont = False
+ TabOrder = 2
+ end
+ object Label5: TLabel
+ Left = 211
+ Height = 15
+ Top = 543
+ 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]
+ ParentFont = False
+ end
+ inline SynEdit1: TSynEdit
+ Left = 10
+ Height = 523
+ Top = 0
+ Width = 813
+ Anchors = [akTop, akLeft, akRight, akBottom]
+ Font.CharSet = 4
+ Font.Height = -13
+ Font.Name = 'Consolas'
+ Font.Pitch = fpFixed
+ Font.Quality = fqCleartypeNatural
+ ParentColor = False
+ ParentFont = False
+ TabOrder = 3
+ Gutter.Width = 55
+ Gutter.MouseActions = <>
+ RightGutter.Width = 0
+ RightGutter.MouseActions = <>
+ Keystrokes = <
+ item
+ Command = ecUp
+ ShortCut = 38
+ end
+ item
+ Command = ecSelUp
+ ShortCut = 8230
+ end
+ item
+ Command = ecScrollUp
+ ShortCut = 16422
+ end
+ item
+ Command = ecDown
+ ShortCut = 40
+ end
+ item
+ Command = ecSelDown
+ ShortCut = 8232
+ end
+ item
+ Command = ecScrollDown
+ ShortCut = 16424
+ end
+ item
+ Command = ecLeft
+ ShortCut = 37
+ end
+ item
+ Command = ecSelLeft
+ ShortCut = 8229
+ end
+ item
+ Command = ecWordLeft
+ ShortCut = 16421
+ end
+ item
+ Command = ecSelWordLeft
+ ShortCut = 24613
+ end
+ item
+ Command = ecRight
+ ShortCut = 39
+ end
+ item
+ Command = ecSelRight
+ ShortCut = 8231
+ end
+ item
+ Command = ecWordRight
+ ShortCut = 16423
+ end
+ item
+ Command = ecSelWordRight
+ ShortCut = 24615
+ end
+ item
+ Command = ecPageDown
+ ShortCut = 34
+ end
+ item
+ Command = ecSelPageDown
+ ShortCut = 8226
+ end
+ item
+ Command = ecPageBottom
+ ShortCut = 16418
+ end
+ item
+ Command = ecSelPageBottom
+ ShortCut = 24610
+ end
+ item
+ Command = ecPageUp
+ ShortCut = 33
+ end
+ item
+ Command = ecSelPageUp
+ ShortCut = 8225
+ end
+ item
+ Command = ecPageTop
+ ShortCut = 16417
+ end
+ item
+ Command = ecSelPageTop
+ ShortCut = 24609
+ end
+ item
+ Command = ecLineStart
+ ShortCut = 36
+ end
+ item
+ Command = ecSelLineStart
+ ShortCut = 8228
+ end
+ item
+ Command = ecEditorTop
+ ShortCut = 16420
+ end
+ item
+ Command = ecSelEditorTop
+ ShortCut = 24612
+ end
+ item
+ Command = ecLineEnd
+ ShortCut = 35
+ end
+ item
+ Command = ecSelLineEnd
+ ShortCut = 8227
+ end
+ item
+ Command = ecEditorBottom
+ ShortCut = 16419
+ end
+ item
+ Command = ecSelEditorBottom
+ ShortCut = 24611
+ end
+ item
+ Command = ecToggleMode
+ ShortCut = 45
+ end
+ item
+ Command = ecCopy
+ ShortCut = 16429
+ end
+ item
+ Command = ecPaste
+ ShortCut = 8237
+ end
+ item
+ Command = ecDeleteChar
+ ShortCut = 46
+ end
+ item
+ Command = ecCut
+ ShortCut = 8238
+ end
+ item
+ Command = ecDeleteLastChar
+ ShortCut = 8
+ end
+ item
+ Command = ecDeleteLastChar
+ ShortCut = 8200
+ end
+ item
+ Command = ecDeleteLastWord
+ ShortCut = 16392
+ end
+ item
+ Command = ecUndo
+ ShortCut = 32776
+ end
+ item
+ Command = ecRedo
+ ShortCut = 40968
+ end
+ item
+ Command = ecLineBreak
+ ShortCut = 13
+ end
+ item
+ Command = ecSelectAll
+ ShortCut = 16449
+ end
+ item
+ Command = ecCopy
+ ShortCut = 16451
+ end
+ item
+ Command = ecBlockIndent
+ ShortCut = 24649
+ end
+ item
+ Command = ecLineBreak
+ ShortCut = 16461
+ end
+ item
+ Command = ecInsertLine
+ ShortCut = 16462
+ end
+ item
+ Command = ecDeleteWord
+ ShortCut = 16468
+ end
+ item
+ Command = ecBlockUnindent
+ ShortCut = 24661
+ end
+ item
+ Command = ecPaste
+ ShortCut = 16470
+ end
+ item
+ Command = ecCut
+ ShortCut = 16472
+ end
+ item
+ Command = ecDeleteLine
+ ShortCut = 16473
+ end
+ item
+ Command = ecDeleteEOL
+ ShortCut = 24665
+ end
+ item
+ Command = ecUndo
+ ShortCut = 16474
+ end
+ item
+ Command = ecRedo
+ ShortCut = 24666
+ end
+ item
+ Command = ecGotoMarker0
+ ShortCut = 16432
+ end
+ item
+ Command = ecGotoMarker1
+ ShortCut = 16433
+ end
+ item
+ Command = ecGotoMarker2
+ ShortCut = 16434
+ end
+ item
+ Command = ecGotoMarker3
+ ShortCut = 16435
+ end
+ item
+ Command = ecGotoMarker4
+ ShortCut = 16436
+ end
+ item
+ Command = ecGotoMarker5
+ ShortCut = 16437
+ end
+ item
+ Command = ecGotoMarker6
+ ShortCut = 16438
+ end
+ item
+ Command = ecGotoMarker7
+ ShortCut = 16439
+ end
+ item
+ Command = ecGotoMarker8
+ ShortCut = 16440
+ end
+ item
+ Command = ecGotoMarker9
+ ShortCut = 16441
+ end
+ item
+ Command = ecSetMarker0
+ ShortCut = 24624
+ end
+ item
+ Command = ecSetMarker1
+ ShortCut = 24625
+ end
+ item
+ Command = ecSetMarker2
+ ShortCut = 24626
+ end
+ item
+ Command = ecSetMarker3
+ ShortCut = 24627
+ end
+ item
+ Command = ecSetMarker4
+ ShortCut = 24628
+ end
+ item
+ Command = ecSetMarker5
+ ShortCut = 24629
+ end
+ item
+ Command = ecSetMarker6
+ ShortCut = 24630
+ end
+ item
+ Command = ecSetMarker7
+ ShortCut = 24631
+ end
+ item
+ Command = ecSetMarker8
+ ShortCut = 24632
+ end
+ item
+ Command = ecSetMarker9
+ ShortCut = 24633
+ end
+ item
+ Command = EcFoldLevel1
+ ShortCut = 41009
+ end
+ item
+ Command = EcFoldLevel2
+ ShortCut = 41010
+ end
+ item
+ Command = EcFoldLevel3
+ ShortCut = 41011
+ end
+ item
+ Command = EcFoldLevel4
+ ShortCut = 41012
+ end
+ item
+ Command = EcFoldLevel5
+ ShortCut = 41013
+ end
+ item
+ Command = EcFoldLevel6
+ ShortCut = 41014
+ end
+ item
+ Command = EcFoldLevel7
+ ShortCut = 41015
+ end
+ item
+ Command = EcFoldLevel8
+ ShortCut = 41016
+ end
+ item
+ Command = EcFoldLevel9
+ ShortCut = 41017
+ end
+ item
+ Command = EcFoldLevel0
+ ShortCut = 41008
+ end
+ item
+ Command = EcFoldCurrent
+ ShortCut = 41005
+ end
+ item
+ Command = EcUnFoldCurrent
+ ShortCut = 41003
+ end
+ item
+ Command = EcToggleMarkupWord
+ ShortCut = 32845
+ end
+ item
+ Command = ecNormalSelect
+ ShortCut = 24654
+ end
+ item
+ Command = ecColumnSelect
+ ShortCut = 24643
+ end
+ item
+ Command = ecLineSelect
+ ShortCut = 24652
+ end
+ item
+ Command = ecTab
+ ShortCut = 9
+ end
+ item
+ Command = ecShiftTab
+ ShortCut = 8201
+ end
+ item
+ Command = ecMatchBracket
+ ShortCut = 24642
+ end
+ item
+ Command = ecColSelUp
+ ShortCut = 40998
+ end
+ item
+ Command = ecColSelDown
+ ShortCut = 41000
+ end
+ item
+ Command = ecColSelLeft
+ ShortCut = 40997
+ end
+ item
+ Command = ecColSelRight
+ ShortCut = 40999
+ end
+ item
+ Command = ecColSelPageDown
+ ShortCut = 40994
+ end
+ item
+ Command = ecColSelPageBottom
+ ShortCut = 57378
+ end
+ item
+ Command = ecColSelPageUp
+ ShortCut = 40993
+ end
+ item
+ Command = ecColSelPageTop
+ ShortCut = 57377
+ end
+ item
+ Command = ecColSelLineStart
+ ShortCut = 40996
+ end
+ item
+ Command = ecColSelLineEnd
+ ShortCut = 40995
+ end
+ item
+ Command = ecColSelEditorTop
+ ShortCut = 57380
+ end
+ item
+ Command = ecColSelEditorBottom
+ ShortCut = 57379
+ end>
+ MouseActions = <>
+ MouseTextActions = <>
+ MouseSelActions = <>
+ Options = [eoAutoIndent, eoGroupUndo, eoHideRightMargin, eoSmartTabs, eoTabsToSpaces, eoTrimTrailingSpaces, eoDragDropEditing, eoDoubleClickSelectsLine]
+ Options2 = [eoEnhanceEndKey, eoFoldedCopyPaste, eoPersistentBlock, eoOverwriteBlock, eoAcceptDragDropEditing]
+ MouseOptions = [emDragDropEditing, emDoubleClickSelectsLine]
+ VisibleSpecialChars = [vscSpace, vscTabAtLast]
+ SelectedColor.BackPriority = 50
+ SelectedColor.ForePriority = 50
+ SelectedColor.FramePriority = 50
+ SelectedColor.BoldPriority = 50
+ SelectedColor.ItalicPriority = 50
+ SelectedColor.UnderlinePriority = 50
+ SelectedColor.StrikeOutPriority = 50
+ BracketHighlightStyle = sbhsBoth
+ BracketMatchColor.Background = clNone
+ BracketMatchColor.Foreground = clNone
+ BracketMatchColor.Style = [fsBold]
+ FoldedCodeColor.Background = clNone
+ FoldedCodeColor.Foreground = clGray
+ FoldedCodeColor.FrameColor = clGray
+ MouseLinkColor.Background = clNone
+ MouseLinkColor.Foreground = clBlue
+ LineHighlightColor.Background = clNone
+ LineHighlightColor.Foreground = clNone
+ WantTabs = False
+ OnChange = SynEdit1Change
+ inline SynLeftGutterPartList1: TSynGutterPartList
+ object SynGutterMarks1: TSynGutterMarks
+ Width = 24
+ MouseActions = <>
+ end
+ object SynGutterLineNumber1: TSynGutterLineNumber
+ Width = 15
+ MouseActions = <>
+ MarkupInfo.Background = clBtnFace
+ MarkupInfo.Foreground = clNone
+ DigitCount = 2
+ ShowOnlyLineNumbersMultiplesOf = 1
+ ZeroStart = False
+ LeadingZeros = False
+ end
+ object SynGutterChanges1: TSynGutterChanges
+ Width = 4
+ MouseActions = <>
+ ModifiedColor = 59900
+ SavedColor = clGreen
+ end
+ object SynGutterSeparator1: TSynGutterSeparator
+ Width = 2
+ MouseActions = <>
+ MarkupInfo.Background = clWhite
+ MarkupInfo.Foreground = clGray
+ end
+ object SynGutterCodeFolding1: TSynGutterCodeFolding
+ MouseActions = <>
+ MarkupInfo.Background = clNone
+ MarkupInfo.Foreground = clGray
+ MouseActionsExpanded = <>
+ MouseActionsCollapsed = <>
+ end
+ end
+ end
+ end
+ object tsSettings: TTabSheet
+ Caption = 'groffstudio settings'
+ ClientHeight = 631
+ ClientWidth = 833
+ object chkAutoSaveBuildSettings: TCheckBox
+ Left = 0
+ Height = 19
+ Top = 16
+ Width = 312
+ Caption = 'Save and restore the chosen build settings for next time'
+ TabOrder = 0
+ end
+ object btnSaveSettings: TButton
+ Left = 744
+ Height = 25
+ Top = 600
+ Width = 91
+ Anchors = [akRight, akBottom]
+ Caption = 'save settings'
+ OnClick = btnSaveSettingsClick
+ TabOrder = 1
+ end
+ object Label14: TLabel
+ Left = 0
+ Height = 15
+ Top = 48
+ Width = 129
+ Caption = 'Yes, that''s all for now. :-)'
+ end
+ end
+ object tsGroff: TTabSheet
+ Caption = 'groff version'
+ ClientHeight = 631
+ ClientWidth = 833
+ object GroupBox2: TGroupBox
+ Left = 20
+ Height = 57
+ Top = 566
+ Width = 793
+ Align = alBottom
+ BorderSpacing.Left = 20
+ BorderSpacing.Right = 20
+ BorderSpacing.Bottom = 8
+ Caption = 'groff for Windows'
+ ClientHeight = 37
+ ClientWidth = 789
+ TabOrder = 0
+ object Label6: TLabel
+ Left = 8
+ Height = 15
+ Top = 8
+ Width = 108
+ Caption = 'latest version online:'
+ end
+ object edtOnlineGroffVersionWindows: TEdit
+ Left = 136
+ Height = 15
+ Top = 8
+ Width = 556
+ Anchors = [akTop, akLeft, akRight]
+ BorderStyle = bsNone
+ Enabled = False
+ TabOrder = 0
+ Text = 'fetching ...'
+ end
+ object btnDownloadGroffWindows: TButton
+ Left = 700
+ Height = 25
+ Top = 5
+ Width = 80
+ Anchors = [akTop, akRight]
+ Caption = 'download it'
+ OnClick = btnDownloadGroffWindowsClick
+ TabOrder = 1
+ end
+ end
+ object Label7: TLabel
+ Left = 8
+ Height = 30
+ Top = 8
+ Width = 821
+ 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
+ WordWrap = True
+ end
+ object Label9: TLabel
+ Left = 8
+ Height = 15
+ Top = 56
+ Width = 70
+ Caption = 'groff version:'
+ end
+ object edtGroffInstalledVersion: TEdit
+ Left = 144
+ Height = 15
+ Top = 56
+ Width = 685
+ Anchors = [akTop, akLeft, akRight]
+ BorderStyle = bsNone
+ Enabled = False
+ TabOrder = 1
+ end
+ object lblTroffCommandNotFound: TLabel
+ Left = 8
+ Height = 45
+ Top = 112
+ Width = 820
+ 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
+ ParentFont = False
+ Visible = False
+ WordWrap = True
+ end
+ object edtGroffstudioInstalledVersion: TEdit
+ Left = 144
+ Height = 15
+ Top = 77
+ Width = 685
+ Anchors = [akTop, akLeft, akRight]
+ BorderStyle = bsNone
+ Enabled = False
+ TabOrder = 2
+ end
+ object Label10: TLabel
+ Left = 8
+ Height = 15
+ Top = 77
+ Width = 103
+ Caption = 'groffstudio version:'
+ end
+ end
+ object tsAbout: TTabSheet
+ Caption = 'about groffstudio'
+ ClientHeight = 631
+ ClientWidth = 833
+ object lblAboutProductName: TLabel
+ Left = 0
+ Height = 61
+ Top = 16
+ Width = 315
+ Caption = 'groffstudio x.y.z'
+ Font.Color = clBlue
+ Font.Height = -45
+ ParentFont = False
+ end
+ object Label8: TLabel
+ Left = 20
+ Height = 15
+ Top = 80
+ Width = 217
+ Caption = 'brought to you by tux0r and contributors'
+ end
+ object Label11: TLabel
+ Left = 0
+ Height = 15
+ Top = 128
+ Width = 45
+ Caption = 'Website:'
+ Font.Style = [fsItalic]
+ ParentFont = False
+ end
+ object Label12: TLabel
+ Left = 0
+ Height = 15
+ Top = 152
+ Width = 57
+ Caption = 'Repository:'
+ Font.Style = [fsItalic]
+ ParentFont = False
+ end
+ object Label13: TLabel
+ Left = 0
+ Height = 15
+ Top = 176
+ Width = 99
+ Caption = 'Repository (mirror):'
+ Font.Style = [fsItalic]
+ ParentFont = False
+ end
+ object mLicense: TMemo
+ Left = 0
+ Height = 418
+ Top = 216
+ Width = 840
+ Anchors = [akTop, akLeft, akRight]
+ ScrollBars = ssAutoBoth
+ TabOrder = 0
+ end
+ object lblWebsite: TLabel
+ Cursor = crHandPoint
+ Left = 120
+ Height = 15
+ Top = 128
+ Width = 99
+ Caption = 'groff.tuxproject.de'
+ Font.Color = clBlue
+ Font.Style = [fsUnderline]
+ ParentFont = False
+ OnClick = lblWebsiteClick
+ end
+ object lblFossilRepo: TLabel
+ Cursor = crHandPoint
+ Left = 120
+ Height = 15
+ Top = 152
+ Width = 121
+ Caption = 'code.rosaelefanten.org'
+ Font.Color = clBlue
+ Font.Style = [fsUnderline]
+ ParentFont = False
+ OnClick = lblFossilRepoClick
+ end
+ object lblGithubRepo: TLabel
+ Cursor = crHandPoint
+ Left = 120
+ Height = 15
+ Top = 176
+ Width = 62
+ Caption = 'github.com'
+ Font.Color = clBlue
+ Font.Style = [fsUnderline]
+ ParentFont = False
+ OnClick = lblGithubRepoClick
+ end
+ end
+ end
+ object odOpenGroffFile: TOpenDialog
+ Title = 'open a groff document'
+ Left = 688
+ Top = 8
+ end
+ object sdSaveGroffFile: TSaveDialog
+ Title = 'save a groff document'
+ Left = 736
+ Top = 8
+ end
+ object iniStorage: TIniPropStorage
+ StoredValues = <>
+ IniFileName = 'groffstudio.ini'
+ Left = 584
+ Top = 8
+ end
+end
ADDED src/unit1.pas
Index: src/unit1.pas
==================================================================
--- /dev/null
+++ src/unit1.pas
@@ -0,0 +1,399 @@
+unit Unit1;
+
+{
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.1 only
+ (the "License"). You may not use this file except in compliance
+ with the License.
+
+ See the file LICENSE in this distribution for details.
+ A copy of the CDDL is also available via the Internet at
+ https://spdx.org/licenses/CDDL-1.1.html
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the contents of the LICENSE file from this
+ distribution.
+}
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls,
+ ExtCtrls, Buttons, ExtendedNotebook, SynEdit, fphttpclient, opensslsockets,
+ RegExpr, LCLIntf, LCLType, IniPropStorage, Process, Helpers, fileinfo,
+ {$IF DEFINED(WINDOWS)}
+ winpeimagereader,
+ {$ELSEIF DEFINED(MACOS)}
+ machoreader,
+ {$ELSEIF DEFINED(LINUX)}
+ elfreader,
+ {$ENDIF}
+ BuildOutputWindow;
+
+type
+
+ { TMainForm }
+
+ TMainForm = class(TForm)
+ btnSaveGroff: TButton;
+ btnLoadGroff: TButton;
+ btnBuild: TButton;
+ btnDownloadGroffWindows: TButton;
+ btnSaveSettings: TButton;
+ chkAutoSaveBuildSettings: TCheckBox;
+ chkPdfMark: TCheckBox;
+ chkRefer: TCheckBox;
+ chkChem: TCheckBox;
+ chkGrn: TCheckBox;
+ chkTbl: TCheckBox;
+ chkPic: TCheckBox;
+ chkEqn: TCheckBox;
+ cmbMacro: TComboBox;
+ edtGroffInstalledVersion: TEdit;
+ edtGroffstudioInstalledVersion: TEdit;
+ edtOnlineGroffVersionWindows: TEdit;
+ ExtendedNotebook1: TExtendedNotebook;
+ GroupBox1: TGroupBox;
+ GroupBox2: TGroupBox;
+ iniStorage: TIniPropStorage;
+ Label1: TLabel;
+ Label10: TLabel;
+ Label11: TLabel;
+ Label12: TLabel;
+ Label13: TLabel;
+ Label14: TLabel;
+ lblGithubRepo: TLabel;
+ lblFossilRepo: TLabel;
+ lblWebsite: TLabel;
+ Label2: TLabel;
+ Label3: TLabel;
+ Label4: TLabel;
+ Label5: TLabel;
+ Label6: TLabel;
+ Label7: TLabel;
+ Label8: TLabel;
+ lblAboutProductName: TLabel;
+ lblTroffCommandNotFound: TLabel;
+ Label9: TLabel;
+ MainStatusBar: TStatusBar;
+ mLicense: TMemo;
+ odOpenGroffFile: TOpenDialog;
+ rdPdf: TRadioButton;
+ rdPs: TRadioButton;
+ sdSaveGroffFile: TSaveDialog;
+ SynEdit1: TSynEdit;
+ tsEdit: TTabSheet;
+ tsAbout: TTabSheet;
+ tsGroff: TTabSheet;
+ tsSettings: TTabSheet;
+ procedure btnBuildClick(Sender: TObject);
+ procedure btnDownloadGroffWindowsClick(Sender: TObject);
+ procedure btnLoadGroffClick(Sender: TObject);
+ procedure btnSaveGroffClick(Sender: TObject);
+ procedure btnSaveSettingsClick(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);
+ procedure rdPdfChange(Sender: TObject);
+ procedure rdPsChange(Sender: TObject);
+ procedure SynEdit1Change(Sender: TObject);
+ private
+ var currentGroffFilePath: String;
+ var currentGroffFileName: String;
+ var hasGroff: Boolean;
+ var unsavedChanges: Boolean;
+ var latestGroffWindowsUrl: String;
+
+ var storeBuildSettings: Boolean;
+ public
+
+ end;
+
+var
+ MainForm: TMainForm;
+ BuildWindow: TBuildStatusWindow;
+
+implementation
+
+{$R *.lfm}
+
+{ TMainForm }
+
+procedure TMainForm.FormCreate(Sender: TObject);
+var
+ GroffOutputVersion: String;
+ OnlineVersionsFile: String;
+ reGroffVersion, reGroffStudioVersion: TRegExpr;
+ FileVerInfo: TFileVersionInfo;
+ HasVersionUpdate: Integer;
+ GroffHelpers: TGroffHelpers;
+ ResStream: TResourceStream;
+begin
+ // What's the current running groff version?
+ if RunCommand('troff', ['--version'], GroffOutputVersion) then
+ begin
+ edtGroffInstalledVersion.Text := GroffOutputVersion;
+ hasGroff := True;
+ end else begin
+ edtGroffInstalledVersion.Text := 'n/a';
+ hasGroff := False;
+ lblTroffCommandNotFound.Visible := True;
+ end;
+
+ // Default file name
+ currentGroffFilePath := '[unsaved file]';
+
+ // Embed the license
+ ResStream:= TResourceStream.Create(HInstance, 'LICENSE', RT_RCDATA);
+ try
+ mLicense.Lines.LoadFromStream(ResStream);
+ finally
+ ResStream.Free;
+ end;
+
+ // Restore the settings
+ iniStorage.Restore;
+ storeBuildSettings := iniStorage.ReadBoolean('AutoSaveBuildSettings', False);
+ chkAutoSaveBuildSettings.Checked := storeBuildSettings;
+
+ if storeBuildSettings then
+ begin
+ cmbMacro.Text := iniStorage.ReadString('BuildChosenMacro', '[ select ]');
+ chkChem.Checked := iniStorage.ReadBoolean('BuildUseChem', False);
+ chkEqn.Checked := iniStorage.ReadBoolean('BuildUseEqn', False);
+ chkGrn.Checked := iniStorage.ReadBoolean('BuildUseGrn', False);
+ chkPic.Checked := iniStorage.ReadBoolean('BuildUsePic', False);
+ chkRefer.Checked := iniStorage.ReadBoolean('BuildUseRefer', False);
+ chkTbl.Checked := iniStorage.ReadBoolean('BuildUseTbl', False);
+ chkPdfMark.Checked := iniStorage.ReadBoolean('BuildUsePdfMark', False);
+ rdPs.Checked := iniStorage.ReadBoolean('BuildToPostscript', False);
+ rdPdf.Checked := iniStorage.ReadBoolean('BuildToPDF', False);
+ end;
+
+ {$IFDEF WINDOWS}
+ // What's the latest available version?
+ FileVerInfo := TFileVersionInfo.Create(nil);
+
+ try
+ FileVerInfo.ReadFileInfo;
+ edtGroffStudioInstalledVersion.Text := FileVerInfo.VersionStrings.Values['FileVersion'];
+ lblAboutProductName.Caption := FileVerInfo.VersionStrings.Values['ProductName'] + ' ' + FileVerInfo.VersionStrings.Values['FileVersion'];
+
+ OnlineVersionsFile := TFPCustomHTTPClient.SimpleGet('https://groff.tuxproject.de/updates/versions.txt');
+ reGroffVersion := TRegExpr.Create('groff-win ([\d\.]+) (.*)$');
+ reGroffVersion.ModifierM := True;
+ if reGroffVersion.Exec(OnlineVersionsFile) then
+ begin
+ edtOnlineGroffVersionWindows.Text := reGroffVersion.Match[1];
+ latestGroffWindowsUrl := reGroffVersion.Match[2];
+ end else begin
+ edtOnlineGroffVersionWindows.Text := 'error';
+ btnDownloadGroffWindows.Enabled := False;
+ end;
+
+ // Note that there is no version check (nor precompiled downloads :-))
+ // for non-Windows versions right now. Contributors welcome.
+ reGroffStudioVersion := TRegExpr.Create('studio-win ([\d\.]+) (.*)$');
+ reGroffStudioVersion.ModifierM := True;
+ if reGroffStudioVersion.Exec(OnlineVersionsFile) then
+ begin
+ // Compare the two versions - ours and the online one:
+ GroffHelpers.VerStrCompare(reGroffStudioVersion.Match[1], FileVerInfo.VersionStrings.Values['FileVersion'], HasVersionUpdate);
+ if HasVersionUpdate > 0 then
+ MainStatusBar.Panels[2].Text := 'update ' + reGroffStudioVersion.Match[1] + ' available'
+ else
+ MainStatusBar.Panels[2].Text := IntToStr(HasVersionUpdate);
+ end else MainStatusBar.Panels[2].Text := '';
+ finally
+ FileVerInfo.Free;
+ end;
+ {$ELSE}
+ // Non-Windows platforms won't need all that.
+ edtOnlineGroffVersionWindows.Text := 'n/a';
+ btnDownloadGroffWindows.Enabled := False;
+ MainStatusBar.Panels[2].Text := '';
+ {$ENDIF}
+
+ // Loaded file display
+ MainStatusBar.Panels[0].Text := '';
+
+ // Groff build status
+ MainStatusBar.Panels[1].Text := '';
+end;
+
+procedure TMainForm.lblFossilRepoClick(Sender: TObject);
+begin
+ OpenURL('https://code.rosaelefanten.org/groffstudio');
+end;
+
+procedure TMainForm.lblGithubRepoClick(Sender: TObject);
+begin
+ OpenURL('https://github.com/dertuxmalwieder/groffstudio');
+end;
+
+procedure TMainForm.lblWebsiteClick(Sender: TObject);
+begin
+ OpenURL('https://groff.tuxproject.de');
+end;
+
+procedure TMainForm.rdPdfChange(Sender: TObject);
+begin
+ chkPdfMark.Enabled := True;
+end;
+
+procedure TMainForm.rdPsChange(Sender: TObject);
+begin
+ chkPdfMark.Enabled := False;
+end;
+
+procedure TMainForm.SynEdit1Change(Sender: TObject);
+begin
+ // Set the "Changed" mark:
+ MainStatusBar.Panels[0].Text := '* ' + currentGroffFileName;
+ unsavedChanges := True;
+end;
+
+procedure TMainForm.btnDownloadGroffWindowsClick(Sender: TObject);
+begin
+ {$IFDEF WINDOWS}
+ OpenURL(latestGroffWindowsUrl);
+ {$ENDIF}
+end;
+
+procedure TMainForm.btnBuildClick(Sender: TObject);
+var
+ buildSuccess: Boolean;
+ buildOpts: String;
+ outputFileName: String;
+begin
+ // Reset status display:
+ MainStatusBar.Panels[1].Text := '';
+
+ BuildWindow := TBuildStatusWindow.Create(Application);
+ BuildWindow.ShowModal;
+
+ // Build the parameters:
+ buildOpts := 'groff';
+
+ // - Macro:
+ buildOpts := buildOpts + ' -' + cmbMacro.SelText;
+
+ // - Enforce UTF-8:
+ buildOpts := buildOpts + ' -Kutf8';
+
+ // - Preprocessors:
+ if chkChem.Checked then buildOpts := buildOpts + ' -chem';
+ if chkEqn.Checked then buildOpts := buildOpts + ' -eqn';
+ if chkGrn.Checked then buildOpts := buildOpts + ' -grn';
+ if chkPic.Checked then buildOpts := buildOpts + ' -pic';
+ if chkRefer.Checked then buildOpts := buildOpts + ' -refer';
+ if chkTbl.Checked then buildOpts := buildOpts + ' -tbl';
+
+ // - PDF-specifics:
+ if rdPdf.Checked then begin
+ buildOpts := buildOpts + ' -Tpdf';
+ if chkPdfMark.Checked then buildOpts := buildOpts + ' -mpdfmark';
+ outputFileName := currentGroffFilePath + '.pdf';
+ end
+ else outputFileName := currentGroffFilePath + '.ps';
+
+ // - Input file:
+ buildOpts := buildOpts + ' ' + currentGroffFilePath;
+ buildOpts := buildOpts + ' > ' + outputFileName;
+
+ // Build:
+ buildSuccess := BuildWindow.BuildDocument(buildOpts);
+ if buildSuccess then
+ MainStatusBar.Panels[1].Text := 'build successful'
+ else
+ MainStatusBar.Panels[1].Text := 'build problem';
+
+ FreeAndNil(BuildWindow);
+end;
+
+procedure TMainForm.btnLoadGroffClick(Sender: TObject);
+var
+ Reply, BoxStyle: Integer;
+begin
+ // If the current file has unsaved changes, ask first.
+ if unsavedChanges then with Application do begin
+ BoxStyle := MB_ICONQUESTION + MB_YESNO;
+ Reply := MessageBox('Do you want to save the document first?', 'UnsavedChanges', BoxStyle);
+ if Reply = IDYES then SynEdit1.Lines.SaveToFile(currentGroffFilePath);
+ unsavedChanges := False;
+ end;
+
+ if odOpenGroffFile.Execute then
+ begin
+ if FileExists(odOpenGroffFile.FileName) then
+ begin
+ currentGroffFilePath := odOpenGroffFile.FileName;
+ currentGroffFileName := ExtractFileName(odOpenGroffFile.FileName);
+ SynEdit1.Lines.LoadFromFile(odOpenGroffFile.FileName);
+
+ if hasGroff then btnBuild.Enabled := True;
+
+ // Display the current file:
+ MainStatusBar.Panels[0].Text := currentGroffFileName;
+ end;
+ end;
+end;
+
+procedure TMainForm.btnSaveGroffClick(Sender: TObject);
+begin
+ if FileExists(currentGroffFilePath) then
+ // We don't need to open the Save As box every time.
+ SynEdit1.Lines.SaveToFile(currentGroffFilePath)
+ else if sdSaveGroffFile.Execute then
+ begin
+ currentGroffFilePath := sdSaveGroffFile.FileName;
+ currentGroffFileName := ExtractFileName(currentGroffFilePath);
+ SynEdit1.Lines.SaveToFile(sdSaveGroffFile.FileName);
+
+ if hasGroff then btnBuild.Enabled := True;
+ end;
+
+ // Remove the "Changed" mark:
+ MainStatusBar.Panels[0].Text := currentGroffFileName;
+ unsavedChanges := False;
+end;
+
+procedure TMainForm.btnSaveSettingsClick(Sender: TObject);
+begin
+ // Store the build settings:
+ iniStorage.WriteString('BuildChosenMacro', cmbMacro.Text);
+ iniStorage.WriteBoolean('BuildUseChem', chkChem.Checked);
+ iniStorage.WriteBoolean('BuildUseEqn', chkEqn.Checked);
+ iniStorage.WriteBoolean('BuildUseGrn', chkGrn.Checked);
+ iniStorage.WriteBoolean('BuildUsePic', chkPic.Checked);
+ iniStorage.WriteBoolean('BuildUseRefer', chkRefer.Checked);
+ iniStorage.WriteBoolean('BuildUseTbl', chkTbl.Checked);
+ iniStorage.WriteBoolean('BuildUsePdfMark', chkPdfMark.Checked);
+ iniStorage.WriteBoolean('BuildToPostscript', rdPs.Checked);
+ iniStorage.WriteBoolean('BuildToPDF', rdPDF.Checked);
+
+ // Store the IDE settings:
+ iniStorage.WriteBoolean('AutoSaveBuildSettings', chkAutoSaveBuildSettings.Checked);
+
+ iniStorage.Save;
+end;
+
+procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+var
+ Reply, BoxStyle: Integer;
+begin
+ // If the current file has unsaved changes, ask first.
+ if unsavedChanges then
+ with Application do begin
+ BoxStyle := MB_ICONQUESTION + MB_YESNO;
+ Reply := MessageBox('Do you want to save the document first?', 'UnsavedChanges', BoxStyle);
+ if Reply = IDYES then SynEdit1.Lines.SaveToFile(currentGroffFilePath);
+ end;
+end;
+
+end.
+