ADDED CHANGES.txt Index: CHANGES.txt ================================================================== --- CHANGES.txt +++ 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 ================================================================== --- CODE_OF_CONDUCT.md +++ 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 ================================================================== --- LICENSE +++ 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 ================================================================== --- README.md +++ 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 ================================================================== --- src/buildoutputwindow.lfm +++ 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 ================================================================== --- src/buildoutputwindow.pas +++ 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 ================================================================== --- src/groffstudio.ico +++ src/groffstudio.ico cannot compute difference between binary files ADDED src/groffstudio.lpi Index: src/groffstudio.lpi ================================================================== --- src/groffstudio.lpi +++ src/groffstudio.lpi @@ -0,0 +1,126 @@ + + + + + + + + + <Scaled Value="True"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + <TextName Value="rosaelefanten.groffstudio"/> + <TextDesc Value="an ide for groff."/> + </XPManifest> + <Icon Value="0"/> + <Resources Count="1"> + <Resource_0 FileName="..\LICENSE" Type="RCDATA" ResourceName="LICENSE"/> + </Resources> + </General> + <VersionInfo> + <UseVersionInfo Value="True"/> + <AutoIncrementBuild Value="True"/> + <MinorVersionNr Value="9"/> + <RevisionNr Value="9"/> + <Attributes pvaPreRelease="True"/> + <StringTable ProductName="groffstudio"/> + </VersionInfo> + <BuildModes> + <Item Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages> + <Item> + <PackageName Value="RunTimeTypeInfoControls"/> + </Item> + <Item> + <PackageName Value="SynEdit"/> + </Item> + <Item> + <PackageName Value="LazControls"/> + </Item> + <Item> + <PackageName Value="LCL"/> + </Item> + </RequiredPackages> + <Units> + <Unit> + <Filename Value="groffstudio.lpr"/> + <IsPartOfProject Value="True"/> + </Unit> + <Unit> + <Filename Value="unit1.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="MainForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="Unit1"/> + </Unit> + <Unit> + <Filename Value="helpers.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Helpers"/> + </Unit> + <Unit> + <Filename Value="buildoutputwindow.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="BuildStatusWindow"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="BuildOutputWindow"/> + </Unit> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="groffstudio"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <Optimizations> + <OptimizationLevel Value="4"/> + </Optimizations> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + <DebugInfoType Value="dsDwarf3"/> + <StripSymbols Value="True"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <WriteFPCLogo Value="False"/> + </Other> + </CompilerOptions> + <Debugging> + <Exceptions> + <Item> + <Name Value="EAbort"/> + </Item> + <Item> + <Name Value="ECodetoolError"/> + </Item> + <Item> + <Name Value="EFOpenError"/> + </Item> + </Exceptions> + </Debugging> +</CONFIG> ADDED src/groffstudio.lpr Index: src/groffstudio.lpr ================================================================== --- src/groffstudio.lpr +++ 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 ================================================================== --- src/groffstudio.lps +++ src/groffstudio.lps @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectSession> + <PathDelim Value="\"/> + <Version Value="12"/> + <BuildModes Active="Default"/> + <Units> + <Unit> + <Filename Value="groffstudio.lpr"/> + <IsPartOfProject Value="True"/> + <EditorIndex Value="1"/> + <CursorPos X="47" Y="22"/> + <UsageCount Value="42"/> + <Loaded Value="True"/> + </Unit> + <Unit> + <Filename Value="unit1.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="MainForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="Unit1"/> + <TopLine Value="302"/> + <CursorPos X="39" Y="309"/> + <UsageCount Value="42"/> + <Loaded Value="True"/> + <LoadedDesigner Value="True"/> + </Unit> + <Unit> + <Filename Value="helpers.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Helpers"/> + <EditorIndex Value="3"/> + <TopLine Value="10"/> + <CursorPos X="40" Y="42"/> + <UsageCount Value="35"/> + <Loaded Value="True"/> + </Unit> + <Unit> + <Filename Value="buildoutputwindow.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="BuildStatusWindow"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="BuildOutputWindow"/> + <IsVisibleTab Value="True"/> + <EditorIndex Value="2"/> + <TopLine Value="53"/> + <CursorPos X="22" Y="80"/> + <UsageCount Value="24"/> + <Loaded Value="True"/> + <LoadedDesigner Value="True"/> + </Unit> + <Unit> + <Filename Value="C:\lazarus\lcl\stdctrls.pp"/> + <UnitName Value="StdCtrls"/> + <EditorIndex Value="-1"/> + <TopLine Value="1355"/> + <CursorPos X="3" Y="1370"/> + <UsageCount Value="9"/> + </Unit> + </Units> + <JumpHistory HistoryIndex="29"> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="146" Column="71" TopLine="130"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="161" Column="32" TopLine="144"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="313" Column="7" TopLine="281"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="289" Column="23" TopLine="255"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="290" Column="23" TopLine="259"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="291" Column="23" TopLine="260"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="292" Column="23" TopLine="261"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="293" Column="23" TopLine="262"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="125" Column="32" TopLine="98"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="156" Column="16" TopLine="127"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="315" Column="26" TopLine="298"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="322" Column="26" TopLine="305"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="223" Column="42" TopLine="221"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="224" Column="42" TopLine="222"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="227" Column="27" TopLine="210"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="226" Column="27" TopLine="209"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="220" Column="28" TopLine="209"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="227" Column="28" TopLine="211"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="225" Column="54" TopLine="211"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="227" Column="54" TopLine="213"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="223" Column="48" TopLine="214"/> + </Position> + <Position> + <Filename Value="buildoutputwindow.pas"/> + <Caret Column="23"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="272" Column="49" TopLine="249"/> + </Position> + <Position> + <Filename Value="unit1.pas"/> + <Caret Line="34" Column="31" TopLine="15"/> + </Position> + <Position> + <Filename Value="buildoutputwindow.pas"/> + <Caret Line="53" Column="21" TopLine="23"/> + </Position> + <Position> + <Filename Value="buildoutputwindow.pas"/> + <Caret Line="50" Column="28" TopLine="23"/> + </Position> + <Position> + <Filename Value="buildoutputwindow.pas"/> + <Caret Line="51" Column="20" TopLine="23"/> + </Position> + <Position> + <Filename Value="buildoutputwindow.pas"/> + <Caret Line="53" Column="24" TopLine="22"/> + </Position> + <Position> + <Filename Value="buildoutputwindow.pas"/> + <Caret Line="55" Column="8" TopLine="39"/> + </Position> + <Position> + <Filename Value="buildoutputwindow.pas"/> + <Caret Line="44" Column="7" TopLine="36"/> + </Position> + </JumpHistory> + <RunParams> + <FormatVersion Value="2"/> + <Modes ActiveMode=""/> + </RunParams> + </ProjectSession> +</CONFIG> ADDED src/helpers.pas Index: src/helpers.pas ================================================================== --- src/helpers.pas +++ 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 ================================================================== --- src/unit1.lfm +++ 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 ================================================================== --- src/unit1.pas +++ 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. +