├── resource.bat ├── wizard2.png ├── ProjectRTF.pas ├── ProjectRes.zip ├── SynProject.ico ├── SynProject.res ├── ProjectEdit.res ├── ProjectEditor.pas ├── ProjectParser.pas ├── ProjectTypes.pas ├── ProjectCommons.pas ├── ProjectDiffUnit.pas ├── ProjectGraphEdit.pas ├── ProjectSpellCheck.pas ├── ProjectMemoExSyntax.pas ├── PasDocLight ├── PasDoc_Hashes.pas ├── PasDoc_Types.pas ├── PasDoc_HierarchyTree.pas ├── PasDoc_ObjectVector.pas ├── PasDoc_StringVector.pas ├── PasDoc_SortSettings.pas ├── pasdoc_defines.inc ├── PasDoc_StringPairVector.pas └── PasDoc_Serialize.pas ├── ProjectRes.rc ├── .gitattributes ├── ProjectFormViewOne.dfm ├── ProjectFormViewTwo.dfm ├── ProjectVersionCompare.dfm ├── ProjectFrameViewer.dfm ├── ProjectEditMain.dfm ├── ProjectFormSelection.dfm ├── .gitignore ├── ProjectFrameRisk.dfm ├── ProjectSpellCheck.dfm ├── ProjectVersionBackup.pas ├── ProjectFrameRisk.pas ├── ProjectEditorCommit.pas ├── README.md ├── ProjectEditorCommit.dfm ├── ProjectEditorProgram.dfm ├── SynProject.dpr ├── ProjectVersionBackup.dfm ├── ProjectGraphEdit.dfm ├── ProjectFormSelection.pas ├── ProjectVersionSCR.pas ├── ProjectVersionSCR.dfm ├── ProjectEditorRelease.dfm ├── ProjectVersionCommit.pas ├── ProjectEditorRelease.pas ├── ProjectDiagrams.pas ├── ProjectVersionCommit.dfm ├── ProjectVersionMain.dfm ├── ProjectVersionPages.dfm ├── ProjectVersionCompare.pas ├── ProjectTrackerLogin.dfm ├── ProjectFormViewOne.pas ├── ProjectFormDocWizard.dfm ├── synproject.css ├── ProjectFormViewTwo.pas ├── ProjectFrameViewer.pas ├── ProjectTrackerLogin.pas ├── ProjectEditMain.pas └── ProjectEditor.dfm /resource.bat: -------------------------------------------------------------------------------- 1 | brcc32 ProjectRes.rc 2 | pause -------------------------------------------------------------------------------- /wizard2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/wizard2.png -------------------------------------------------------------------------------- /ProjectRTF.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectRTF.pas -------------------------------------------------------------------------------- /ProjectRes.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectRes.zip -------------------------------------------------------------------------------- /SynProject.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/SynProject.ico -------------------------------------------------------------------------------- /SynProject.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/SynProject.res -------------------------------------------------------------------------------- /ProjectEdit.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectEdit.res -------------------------------------------------------------------------------- /ProjectEditor.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectEditor.pas -------------------------------------------------------------------------------- /ProjectParser.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectParser.pas -------------------------------------------------------------------------------- /ProjectTypes.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectTypes.pas -------------------------------------------------------------------------------- /ProjectCommons.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectCommons.pas -------------------------------------------------------------------------------- /ProjectDiffUnit.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectDiffUnit.pas -------------------------------------------------------------------------------- /ProjectGraphEdit.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectGraphEdit.pas -------------------------------------------------------------------------------- /ProjectSpellCheck.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectSpellCheck.pas -------------------------------------------------------------------------------- /ProjectMemoExSyntax.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/ProjectMemoExSyntax.pas -------------------------------------------------------------------------------- /PasDocLight/PasDoc_Hashes.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/PasDocLight/PasDoc_Hashes.pas -------------------------------------------------------------------------------- /PasDocLight/PasDoc_Types.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/PasDocLight/PasDoc_Types.pas -------------------------------------------------------------------------------- /PasDocLight/PasDoc_HierarchyTree.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/PasDocLight/PasDoc_HierarchyTree.pas -------------------------------------------------------------------------------- /PasDocLight/PasDoc_ObjectVector.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/PasDocLight/PasDoc_ObjectVector.pas -------------------------------------------------------------------------------- /PasDocLight/PasDoc_StringVector.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synopse/SynProject/HEAD/PasDocLight/PasDoc_StringVector.pas -------------------------------------------------------------------------------- /ProjectRes.rc: -------------------------------------------------------------------------------- 1 | Default TXT "Default.ini" 2 | Zip ZIP "ProjectRes.zip" 3 | wizard2 10 "wizard2.png" 4 | css TXT "synproject.css" 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /ProjectFormViewOne.dfm: -------------------------------------------------------------------------------- 1 | object FormViewOne: TFormViewOne 2 | Left = 667 3 | Top = 194 4 | Width = 445 5 | Height = 562 6 | Color = clBtnFace 7 | Font.Charset = DEFAULT_CHARSET 8 | Font.Color = clWindowText 9 | Font.Height = -11 10 | Font.Name = 'MS Sans Serif' 11 | Font.Style = [] 12 | FormStyle = fsStayOnTop 13 | OldCreateOrder = False 14 | PixelsPerInch = 96 15 | TextHeight = 13 16 | object Image: TImage 17 | Left = 0 18 | Top = 0 19 | Width = 437 20 | Height = 528 21 | Align = alClient 22 | Visible = False 23 | end 24 | object PopupMenu: TPopupMenu 25 | Left = 64 26 | Top = 80 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /ProjectFormViewTwo.dfm: -------------------------------------------------------------------------------- 1 | object FormViewTwo: TFormViewTwo 2 | Left = 257 3 | Top = 137 4 | Width = 522 5 | Height = 455 6 | Color = clBtnFace 7 | Font.Charset = DEFAULT_CHARSET 8 | Font.Color = clWindowText 9 | Font.Height = -11 10 | Font.Name = 'Tahoma' 11 | Font.Style = [] 12 | FormStyle = fsStayOnTop 13 | OldCreateOrder = False 14 | OnResize = FormResize 15 | PixelsPerInch = 96 16 | TextHeight = 13 17 | object Splitter1: TSplitter 18 | Left = 265 19 | Top = 0 20 | Height = 421 21 | end 22 | object PanelLeft: TPanel 23 | Left = 0 24 | Top = 0 25 | Width = 265 26 | Height = 421 27 | Align = alLeft 28 | BevelOuter = bvNone 29 | TabOrder = 0 30 | end 31 | object PanelRight: TPanel 32 | Left = 268 33 | Top = 0 34 | Width = 246 35 | Height = 421 36 | Align = alClient 37 | BevelOuter = bvNone 38 | TabOrder = 1 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /ProjectVersionCompare.dfm: -------------------------------------------------------------------------------- 1 | object ProjectVersionCompareForm: TProjectVersionCompareForm 2 | Left = 162 3 | Top = 354 4 | Width = 547 5 | Height = 393 6 | Color = clBtnFace 7 | Font.Charset = DEFAULT_CHARSET 8 | Font.Color = clWindowText 9 | Font.Height = -11 10 | Font.Name = 'MS Sans Serif' 11 | Font.Style = [] 12 | OldCreateOrder = False 13 | OnResize = FormResize 14 | OnShow = FormShow 15 | PixelsPerInch = 96 16 | TextHeight = 13 17 | object PanelLeft: TPanel 18 | Left = 225 19 | Top = 0 20 | Width = 148 21 | Height = 342 22 | Align = alLeft 23 | BevelOuter = bvNone 24 | TabOrder = 0 25 | end 26 | object PanelRight: TPanel 27 | Left = 373 28 | Top = 0 29 | Width = 203 30 | Height = 342 31 | Align = alRight 32 | BevelOuter = bvNone 33 | TabOrder = 1 34 | end 35 | object ListFilesCommit: TListView 36 | Left = 0 37 | Top = 0 38 | Width = 225 39 | Height = 342 40 | Align = alLeft 41 | Columns = <> 42 | MultiSelect = True 43 | TabOrder = 2 44 | OnSelectItem = ListFilesCommitSelectItem 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /ProjectFrameViewer.dfm: -------------------------------------------------------------------------------- 1 | object FrameViewer: TFrameViewer 2 | Left = 0 3 | Top = 0 4 | Width = 318 5 | Height = 238 6 | TabOrder = 0 7 | object MemoEx: TMemoEx 8 | Left = 0 9 | Top = 0 10 | Width = 318 11 | Height = 238 12 | Cursor = crIBeam 13 | TabOrder = 0 14 | GutterWidth = 0 15 | RightMarginColor = clSilver 16 | ReadOnly = True 17 | Completion.Separator = '=' 18 | Completion.ItemHeight = 13 19 | Completion.Interval = 800 20 | Completion.ListBoxStyle = lbStandard 21 | Completion.CaretChar = '|' 22 | Completion.CRLF = '/n' 23 | TabStops = '8' 24 | SelForeColor = clHighlightText 25 | SelBackColor = clHighlight 26 | OnKeyDown = MemoExKeyDown 27 | Align = alClient 28 | Ctl3D = True 29 | Font.Charset = DEFAULT_CHARSET 30 | Font.Color = clWindowText 31 | Font.Height = -13 32 | Font.Name = 'Courier New' 33 | Font.Pitch = fpFixed 34 | Font.Style = [] 35 | ParentColor = False 36 | TabStop = True 37 | UseDockManager = False 38 | WordWrap = False 39 | end 40 | object FindDialog: TFindDialog 41 | Options = [frDown, frHideWholeWord, frHideUpDown] 42 | OnFind = FindDialogFind 43 | Left = 72 44 | Top = 72 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /ProjectEditMain.dfm: -------------------------------------------------------------------------------- 1 | object ProMainForm: TProMainForm 2 | Left = 250 3 | Top = 303 4 | Width = 668 5 | Height = 436 6 | Color = clBtnFace 7 | Font.Charset = DEFAULT_CHARSET 8 | Font.Color = clWindowText 9 | Font.Height = -11 10 | Font.Name = 'Tahoma' 11 | Font.Style = [] 12 | KeyPreview = True 13 | OldCreateOrder = False 14 | ShowHint = True 15 | WindowState = wsMaximized 16 | OnCloseQuery = FormCloseQuery 17 | OnCreate = FormCreate 18 | OnDestroy = FormDestroy 19 | OnShow = FormShow 20 | PixelsPerInch = 96 21 | TextHeight = 13 22 | object Splitter2: TSplitter 23 | Left = 121 24 | Top = 0 25 | Height = 379 26 | end 27 | object Splitter1: TSplitter 28 | Left = 649 29 | Top = 0 30 | Height = 379 31 | Align = alRight 32 | end 33 | object Sections: TListBox 34 | Left = 0 35 | Top = 0 36 | Width = 121 37 | Height = 379 38 | Align = alLeft 39 | ItemHeight = 13 40 | TabOrder = 0 41 | OnClick = SectionsClick 42 | OnMouseDown = SectionsMouseDown 43 | end 44 | object StatusBar: TStatusBar 45 | Left = 0 46 | Top = 379 47 | Width = 652 48 | Height = 19 49 | AutoHint = True 50 | Panels = < 51 | item 52 | Width = 500 53 | end 54 | item 55 | Width = 50 56 | end> 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /ProjectFormSelection.dfm: -------------------------------------------------------------------------------- 1 | object SelectionForm: TSelectionForm 2 | Left = 352 3 | Top = 156 4 | Width = 571 5 | Height = 665 6 | Color = clBtnFace 7 | Font.Charset = DEFAULT_CHARSET 8 | Font.Color = clWindowText 9 | Font.Height = -13 10 | Font.Name = 'Tahoma' 11 | Font.Style = [] 12 | KeyPreview = True 13 | OldCreateOrder = False 14 | Position = poScreenCenter 15 | OnCreate = FormCreate 16 | OnDestroy = FormDestroy 17 | OnKeyDown = FormKeyDown 18 | OnShow = FormShow 19 | PixelsPerInch = 96 20 | TextHeight = 16 21 | object List: TListBox 22 | Left = 0 23 | Top = 25 24 | Width = 555 25 | Height = 602 26 | Style = lbVirtualOwnerDraw 27 | Align = alClient 28 | ItemHeight = 18 29 | TabOrder = 1 30 | OnDblClick = ListDblClick 31 | OnDrawItem = ListDrawItem 32 | end 33 | object pnlTop: TPanel 34 | Left = 0 35 | Top = 0 36 | Width = 555 37 | Height = 25 38 | Align = alTop 39 | TabOrder = 0 40 | DesignSize = ( 41 | 555 42 | 25) 43 | object edtFind: TEdit 44 | Left = 0 45 | Top = 0 46 | Width = 530 47 | Height = 25 48 | Anchors = [akLeft, akTop, akRight] 49 | AutoSize = False 50 | TabOrder = 0 51 | OnChange = edtFindChange 52 | end 53 | object btnNext: TButton 54 | Left = 528 55 | Top = 0 56 | Width = 25 57 | Height = 25 58 | Hint = 'Next (F3)' 59 | Anchors = [akTop, akRight] 60 | Caption = '>' 61 | Font.Charset = DEFAULT_CHARSET 62 | Font.Color = clWindowText 63 | Font.Height = -13 64 | Font.Name = 'Tahoma' 65 | Font.Style = [fsBold] 66 | ParentFont = False 67 | ParentShowHint = False 68 | ShowHint = True 69 | TabOrder = 1 70 | TabStop = False 71 | OnClick = edtFindChange 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /PasDocLight/PasDoc_SortSettings.pas: -------------------------------------------------------------------------------- 1 | unit PasDoc_SortSettings; 2 | 3 | interface 4 | 5 | uses SysUtils; 6 | 7 | type 8 | EInvalidSortSetting = class(Exception); 9 | 10 | TSortSetting = ( 11 | { At unit (TPasUnit) level : } { } 12 | ssCIOs, ssConstants, ssFuncsProcs, ssTypes, ssVariables, ssUsesClauses, 13 | { At CIO (TPasCio) level : } { } 14 | ssRecordFields, ssNonRecordFields, ssMethods, ssProperties); 15 | TSortSettings = set of TSortSetting; 16 | 17 | const 18 | AllSortSettings: TSortSettings = [Low(TSortSetting) .. High(TSortSetting)]; 19 | 20 | { Must be lowercase. 21 | Used in @link(SortSettingsToName), @link(SortSettingFromName). } 22 | SortSettingNames: array[TSortSetting] of string = ( 23 | 'structures', 'constants', 'functions', 'types', 'variables', 'uses-clauses', 24 | 'record-fields', 'non-record-fields', 'methods', 'properties' ); 25 | 26 | { @raises(EInvalidSortSetting if ASortSettingName does not match 27 | (case ignored) to any SortSettingNames.) } 28 | function SortSettingFromName(const SortSettingName: string): TSortSetting; 29 | 30 | { Comma-separated list } 31 | function SortSettingsToName(const SortSettings: TSortSettings): string; 32 | 33 | 34 | implementation 35 | 36 | function SortSettingFromName(const SortSettingName: string): TSortSetting; 37 | var S: string; 38 | begin 39 | S := LowerCase(SortSettingName); 40 | for Result := Low(Result) to High(Result) do 41 | if S = SortSettingNames[Result] then 42 | Exit; 43 | raise EInvalidSortSetting.CreateFmt('Invalid sort specifier "%s"', 44 | [SortSettingName]); 45 | end; 46 | 47 | function SortSettingsToName(const SortSettings: TSortSettings): string; 48 | var SS: TSortSetting; 49 | begin 50 | Result := ''; 51 | for SS := Low(SS) to High(SS) do 52 | if SS in SortSettings then 53 | begin 54 | if Result <> '' then Result := Result + ','; 55 | Result := Result + SortSettingNames[SS]; 56 | end; 57 | end; 58 | 59 | end. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | *.ddp 15 | *.dof 16 | # 17 | # Visual LiveBindings file. Added in Delphi XE2. 18 | # Uncomment this if you are not using LiveBindings Designer. 19 | #*.vlb 20 | # 21 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 22 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 23 | #*.deployproj 24 | # 25 | # C++ object files produced when C/C++ Output file generation is configured. 26 | # Uncomment this if you are not using external objects (zlib library for example). 27 | #*.obj 28 | # 29 | 30 | # Delphi compiler-generated binaries (safe to delete) 31 | *.exe 32 | *.dll 33 | *.bpl 34 | *.bpi 35 | *.dcp 36 | *.so 37 | *.apk 38 | *.drc 39 | *.map 40 | *.dres 41 | *.rsm 42 | *.tds 43 | *.dcu 44 | *.lib 45 | *.a 46 | *.o 47 | *.ocx 48 | 49 | # FreePascal compiler 50 | *.com 51 | *.class 52 | *.ppu 53 | *.compiled 54 | *.rsj 55 | *.or 56 | *.lps 57 | *.db 58 | fpc/ 59 | 60 | # Delphi autogenerated files (duplicated info) 61 | *.cfg 62 | *.hpp 63 | *Resource.rc 64 | 65 | # Delphi local files (user-specific info) 66 | *.local 67 | *.identcache 68 | *.projdata 69 | *.tvsconfig 70 | *.dsk 71 | 72 | # Delphi history and backups 73 | __history/ 74 | __recovery/ 75 | *.~* 76 | *.bak 77 | 78 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 79 | *.stat 80 | 81 | #other VCS 82 | _FOSSIL_ 83 | .svn/ 84 | # SourceCodeRep artifact 85 | *.txt 86 | 87 | backup/ 88 | .idea/ 89 | -------------------------------------------------------------------------------- /ProjectFrameRisk.dfm: -------------------------------------------------------------------------------- 1 | object FrameRisk: TFrameRisk 2 | Left = 0 3 | Top = 0 4 | Width = 353 5 | Height = 171 6 | TabOrder = 0 7 | object GroupBoxRisk: TGroupBox 8 | Left = 0 9 | Top = 0 10 | Width = 353 11 | Height = 169 12 | Caption = ' Risk Assessment ' 13 | TabOrder = 0 14 | DesignSize = ( 15 | 353 16 | 169) 17 | object Label1: TLabel 18 | Left = 80 19 | Top = 32 20 | Width = 3 21 | Height = 13 22 | Alignment = taRightJustify 23 | end 24 | object Label2: TLabel 25 | Left = 80 26 | Top = 56 27 | Width = 3 28 | Height = 13 29 | Alignment = taRightJustify 30 | end 31 | object Label3: TLabel 32 | Left = 80 33 | Top = 80 34 | Width = 3 35 | Height = 13 36 | Alignment = taRightJustify 37 | end 38 | object ComboBox1: TComboBox 39 | Left = 88 40 | Top = 28 41 | Width = 245 42 | Height = 21 43 | Style = csDropDownList 44 | Anchors = [akLeft, akTop, akRight] 45 | ItemHeight = 13 46 | TabOrder = 0 47 | end 48 | object ComboBox2: TComboBox 49 | Left = 88 50 | Top = 52 51 | Width = 245 52 | Height = 21 53 | Style = csDropDownList 54 | Anchors = [akLeft, akTop, akRight] 55 | ItemHeight = 13 56 | TabOrder = 1 57 | end 58 | object ComboBox3: TComboBox 59 | Left = 88 60 | Top = 76 61 | Width = 245 62 | Height = 21 63 | Style = csDropDownList 64 | Anchors = [akLeft, akTop, akRight] 65 | ItemHeight = 13 66 | TabOrder = 2 67 | end 68 | object LabeledEditEvaluatedBy: TLabeledEdit 69 | Left = 88 70 | Top = 104 71 | Width = 245 72 | Height = 21 73 | Hint = 'Put the SW risk evaluation team names, separated with +' 74 | Anchors = [akLeft, akTop, akRight] 75 | EditLabel.Width = 62 76 | EditLabel.Height = 13 77 | EditLabel.Caption = 'Evaluated by' 78 | LabelPosition = lpLeft 79 | ParentShowHint = False 80 | ShowHint = True 81 | TabOrder = 3 82 | OnKeyPress = LabeledEditEvaluatedByKeyPress 83 | end 84 | object LabeledEditJustif: TLabeledEdit 85 | Left = 88 86 | Top = 130 87 | Width = 245 88 | Height = 21 89 | Anchors = [akLeft, akTop, akRight] 90 | EditLabel.Width = 55 91 | EditLabel.Height = 13 92 | EditLabel.Caption = 'Justification' 93 | LabelPosition = lpLeft 94 | TabOrder = 4 95 | end 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /ProjectSpellCheck.dfm: -------------------------------------------------------------------------------- 1 | object SpellCheckForm: TSpellCheckForm 2 | Left = 453 3 | Top = 413 4 | BorderStyle = bsSingle 5 | Caption = 'Spell Check' 6 | ClientHeight = 219 7 | ClientWidth = 452 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -11 12 | Font.Name = 'Tahoma' 13 | Font.Style = [] 14 | KeyPreview = True 15 | OldCreateOrder = False 16 | OnCreate = FormCreate 17 | OnDestroy = FormDestroy 18 | OnKeyUp = FormKeyUp 19 | PixelsPerInch = 96 20 | TextHeight = 13 21 | object Label1: TLabel 22 | Left = 19 23 | Top = 15 24 | Width = 78 25 | Height = 13 26 | Alignment = taRightJustify 27 | Caption = '&Not in dictionary' 28 | FocusControl = Edit 29 | end 30 | object Label2: TLabel 31 | Left = 56 32 | Top = 46 33 | Width = 39 34 | Height = 13 35 | Alignment = taRightJustify 36 | Caption = 'Suggest' 37 | end 38 | object Edit: TEdit 39 | Left = 104 40 | Top = 13 41 | Width = 151 42 | Height = 21 43 | TabOrder = 0 44 | end 45 | object btnSkip: TButton 46 | Left = 280 47 | Top = 8 48 | Width = 73 49 | Height = 33 50 | Caption = '&Skip' 51 | TabOrder = 1 52 | OnClick = btnClick 53 | end 54 | object btnSkipAll: TButton 55 | Left = 360 56 | Top = 8 57 | Width = 73 58 | Height = 33 59 | Caption = 'Skip &All' 60 | TabOrder = 2 61 | OnClick = btnClick 62 | end 63 | object ListBox: TListBox 64 | Left = 104 65 | Top = 40 66 | Width = 153 67 | Height = 161 68 | ItemHeight = 13 69 | TabOrder = 3 70 | OnClick = ListBoxClick 71 | end 72 | object btnAddDictionary: TButton 73 | Left = 280 74 | Top = 56 75 | Width = 105 76 | Height = 33 77 | Caption = 'Add to &Dictionary' 78 | TabOrder = 4 79 | OnClick = btnClick 80 | end 81 | object btnReplace: TButton 82 | Left = 280 83 | Top = 104 84 | Width = 73 85 | Height = 33 86 | Caption = '&Replace' 87 | TabOrder = 5 88 | OnClick = btnClick 89 | end 90 | object btnReplaceAll: TButton 91 | Left = 360 92 | Top = 104 93 | Width = 73 94 | Height = 33 95 | Caption = 'Replace A&ll' 96 | TabOrder = 6 97 | OnClick = btnClick 98 | end 99 | object btnClose: TButton 100 | Left = 280 101 | Top = 168 102 | Width = 73 103 | Height = 33 104 | Caption = '&Close' 105 | Default = True 106 | TabOrder = 7 107 | OnClick = btnClick 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /ProjectVersionBackup.pas: -------------------------------------------------------------------------------- 1 | /// File Versioning Backup form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectVersionBackup; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 30 | Dialogs, StdCtrls, Buttons, CheckLst, ProjectCommons; 31 | 32 | type 33 | TProjectVersionBackupForm = class(TForm) 34 | CheckListBox: TCheckListBox; 35 | Label1: TLabel; 36 | BtnSelected: TBitBtn; 37 | BtnAll: TBitBtn; 38 | BtnCancel: TBitBtn; 39 | procedure FormKeyDown(Sender: TObject; var Key: Word; 40 | Shift: TShiftState); 41 | procedure BtnAllClick(Sender: TObject); 42 | procedure BtnSelectedClick(Sender: TObject); 43 | procedure FormShow(Sender: TObject); 44 | private 45 | { Private declarations } 46 | public 47 | Selected: TIntegerDynArray; 48 | end; 49 | 50 | var 51 | ProjectVersionBackupForm: TProjectVersionBackupForm; 52 | 53 | implementation 54 | 55 | {$R *.dfm} 56 | 57 | procedure TProjectVersionBackupForm.FormKeyDown(Sender: TObject; 58 | var Key: Word; Shift: TShiftState); 59 | begin 60 | if byte(Shift)=0 then 61 | case Key of 62 | vk_F3: BtnSelected.Click; 63 | vk_F4: BtnAll.Click; 64 | end; 65 | end; 66 | 67 | procedure TProjectVersionBackupForm.BtnAllClick(Sender: TObject); 68 | var i: integer; 69 | begin 70 | SetLength(Selected,CheckListBox.Count); 71 | with CheckListBox.Items do 72 | for i := 0 to Count-1 do 73 | Selected[i] := integer(Objects[i]); 74 | end; 75 | 76 | procedure TProjectVersionBackupForm.BtnSelectedClick(Sender: TObject); 77 | var n,i: integer; 78 | begin 79 | SetLength(Selected,CheckListBox.Count); 80 | n := 0; 81 | with CheckListBox.Items do 82 | for i := 0 to Count-1 do 83 | if CheckListBox.Checked[i] then begin 84 | Selected[n] := integer(Objects[i]); 85 | inc(n); 86 | end; 87 | Setlength(Selected,n); 88 | end; 89 | 90 | procedure TProjectVersionBackupForm.FormShow(Sender: TObject); 91 | begin 92 | BtnSelected.SetFocus; 93 | end; 94 | 95 | end. 96 | -------------------------------------------------------------------------------- /ProjectFrameRisk.pas: -------------------------------------------------------------------------------- 1 | /// Risk assessment setting visual frame 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectFrameRisk; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 30 | Dialogs, StdCtrls, ExtCtrls; 31 | 32 | type 33 | TFrameRisk = class(TFrame) 34 | GroupBoxRisk: TGroupBox; 35 | Label1: TLabel; 36 | Label2: TLabel; 37 | Label3: TLabel; 38 | ComboBox1: TComboBox; 39 | ComboBox2: TComboBox; 40 | ComboBox3: TComboBox; 41 | LabeledEditEvaluatedBy: TLabeledEdit; 42 | LabeledEditJustif: TLabeledEdit; 43 | procedure LabeledEditEvaluatedByKeyPress(Sender: TObject; var Key: Char); 44 | public 45 | constructor Create(AOwner: TComponent); override; 46 | procedure Init(const RiskValue: string); 47 | function Risk: string; 48 | end; 49 | 50 | implementation 51 | 52 | {$R *.dfm} 53 | 54 | uses 55 | ProjectTypes; // for RISKDEFS_ENGLISH[] 56 | 57 | { TFrameRisk } 58 | 59 | constructor TFrameRisk.Create(AOwner: TComponent); 60 | procedure One(const Risk: TRiskOneDef; L: TLabel; C: TComboBox); 61 | begin 62 | with Risk do begin 63 | L.Caption := Name; 64 | C.Hint := Name+': '+Description; 65 | with C.Items do begin 66 | Clear; 67 | Add('0 - Not evaluated'); 68 | Add('1 - '+Level[1]); 69 | Add('2 - '+Level[2]); 70 | Add('3 - '+Level[3]); 71 | end; 72 | end; 73 | C.ShowHint := true; 74 | C.ItemIndex := 0; 75 | end; 76 | begin 77 | inherited; 78 | One(RISKDEFS[0],Label1,ComboBox1); 79 | One(RISKDEFS[1],Label2,ComboBox2); 80 | One(RISKDEFS[2],Label3,ComboBox3); 81 | end; 82 | 83 | procedure TFrameRisk.Init(const RiskValue: string); 84 | var R: TRisk; 85 | begin 86 | fillchar(R,sizeof(R),0); 87 | R.FromString(RiskValue); 88 | LabeledEditEvaluatedBy.Text := R.EvaluatedBy; 89 | LabeledEditJustif.Text := R.Comment; 90 | ComboBox1.ItemIndex := R.Risk[0]; 91 | ComboBox2.ItemIndex := R.Risk[1]; 92 | ComboBox3.ItemIndex := R.Risk[2]; 93 | end; 94 | 95 | function TFrameRisk.Risk: string; 96 | begin 97 | result := format('%s,%s,%s,%s,%s',[ 98 | ComboBox1.Text[1],ComboBox2.Text[1],ComboBox3.Text[1], 99 | trim(LabeledEditEvaluatedBy.Text),trim(LabeledEditJustif.Text)]); 100 | if result='0,0,0,,' then 101 | result := ''; 102 | end; 103 | 104 | procedure TFrameRisk.LabeledEditEvaluatedByKeyPress(Sender: TObject; var Key: Char); 105 | begin 106 | if Key=',' then 107 | Key := '+'; 108 | end; 109 | 110 | end. 111 | 112 | -------------------------------------------------------------------------------- /ProjectEditorCommit.pas: -------------------------------------------------------------------------------- 1 | /// Commit parameters setting form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectEditorCommit; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 30 | Dialogs, StdCtrls, Buttons, ExtCtrls; 31 | 32 | type 33 | /// Commit parameters setting form 34 | TProjectEditorCommitForm = class(TForm) 35 | DisplayName: TLabeledEdit; 36 | Path: TLabeledEdit; 37 | BtnOK: TBitBtn; 38 | BtnCancel: TBitBtn; 39 | FilterDefault: TCheckBox; 40 | Filters: TLabeledEdit; 41 | BtnPath: TButton; 42 | procedure BtnPathClick(Sender: TObject); 43 | private 44 | FDefPath: string; 45 | public 46 | end; 47 | 48 | function EditorCommitForm(const Title, DefPath, FilterDefault: string; var Value: string): boolean; 49 | 50 | 51 | implementation 52 | 53 | uses 54 | ProjectCommons, ProjectRTF, ProjectFormDocWizard, ProjectVersioning; 55 | 56 | {$R *.dfm} 57 | 58 | 59 | function EditorCommitForm(const Title, DefPath, FilterDefault: string; var Value: string): boolean; 60 | // Value = 'Display Name;Path;Filter,Filter,..' 61 | var F: TProjectEditorCommitForm; 62 | P: PAnsiChar; 63 | v: string; 64 | begin 65 | F := TProjectEditorCommitForm.Create(Application); 66 | try 67 | F.FDefPath := IncludeTrailingPathDelimiter(SysUtils.UpperCase(trim(DefPath))); 68 | F.Caption := ' '+Title; 69 | P := pointer(Value); 70 | F.DisplayName.Text := GetNextItem(P,';'); 71 | F.Path.Text := GetNextItem(P,';'); 72 | F.FilterDefault.Caption := sCommitFilterDefault; 73 | F.FilterDefault.Hint := FilterDefault; 74 | v := P; 75 | F.FilterDefault.Checked := CSVDelete(v,'FilterDefault'); 76 | F.Filters.Text := v; 77 | result := F.ShowModal=mrOk; 78 | if not result then 79 | exit; 80 | Value := trim(F.DisplayName.Text)+';'+trim(F.Path.Text)+';'; 81 | v := trim(F.Filters.Text); 82 | if F.FilterDefault.Checked then 83 | if v='' then 84 | v := 'FilterDefault' else 85 | v := 'FilterDefault,'+v; 86 | Value := Value+v; 87 | finally 88 | F.Free; 89 | end; 90 | end; 91 | 92 | procedure TProjectEditorCommitForm.BtnPathClick(Sender: TObject); 93 | var Dir: string; 94 | begin 95 | Dir := Path.Text; 96 | if not DirectoryExists(Dir) and DirectoryExists(FDefPath+Dir) then 97 | Dir := FDefPath+Dir; 98 | if SelectDirectory(Handle,Path.EditLabel.Caption,Dir) then begin 99 | if IdemPChar(pointer(Dir),pointer(FDefPath)) then 100 | Delete(Dir,1,length(FDefPath)); 101 | Path.Text := Dir; 102 | end; 103 | end; 104 | 105 | end. 106 | -------------------------------------------------------------------------------- /PasDocLight/pasdoc_defines.inc: -------------------------------------------------------------------------------- 1 | {$define DONTUSEASPELL} 2 | {$define USEZIPCACHE} 3 | {$define DONTUSETAGS} 4 | // above directives are PasDocLight default 5 | 6 | {$IFDEF WIN32} 7 | 8 | {$IFDEF VER180} 9 | {$DEFINE DELPHI_10} 10 | {$DEFINE DELPHI_10_UP} 11 | {$DEFINE DELPHI_9_UP} 12 | {$DEFINE DELPHI_7_UP} 13 | {$DEFINE DELPHI_6_UP} 14 | {$DEFINE DELPHI_5_UP} 15 | {$DEFINE DELPHI_4_UP} 16 | {$DEFINE DELPHI_3_UP} 17 | {$DEFINE DELPHI_2_UP} 18 | {$DEFINE DELPHI_1_UP} 19 | 20 | {$DEFINE COMPILER_10} 21 | {$DEFINE COMPILER_10_UP} 22 | {$DEFINE COMPILER_9_UP} 23 | {$DEFINE COMPILER_7_UP} 24 | {$DEFINE COMPILER_6_UP} 25 | {$DEFINE COMPILER_5_UP} 26 | {$DEFINE COMPILER_4_UP} 27 | {$DEFINE COMPILER_3_UP} 28 | {$DEFINE COMPILER_2_UP} 29 | {$DEFINE COMPILER_1_UP} 30 | {$ENDIF} 31 | 32 | {$IFDEF VER170} 33 | {$DEFINE DELPHI_9} 34 | {$DEFINE DELPHI_9_UP} 35 | {$DEFINE DELPHI_7_UP} 36 | {$DEFINE DELPHI_6_UP} 37 | {$DEFINE DELPHI_5_UP} 38 | {$DEFINE DELPHI_4_UP} 39 | {$DEFINE DELPHI_3_UP} 40 | {$DEFINE DELPHI_2_UP} 41 | {$DEFINE DELPHI_1_UP} 42 | 43 | {$DEFINE COMPILER_9} 44 | {$DEFINE COMPILER_9_UP} 45 | {$DEFINE COMPILER_7_UP} 46 | {$DEFINE COMPILER_6_UP} 47 | {$DEFINE COMPILER_5_UP} 48 | {$DEFINE COMPILER_4_UP} 49 | {$DEFINE COMPILER_3_UP} 50 | {$DEFINE COMPILER_2_UP} 51 | {$DEFINE COMPILER_1_UP} 52 | {$ENDIF} 53 | 54 | {$IFDEF VER150} 55 | {$DEFINE DELPHI_7} 56 | {$DEFINE DELPHI_7_UP} 57 | {$DEFINE DELPHI_6_UP} 58 | {$DEFINE DELPHI_5_UP} 59 | {$DEFINE DELPHI_4_UP} 60 | {$DEFINE DELPHI_3_UP} 61 | {$DEFINE DELPHI_2_UP} 62 | {$DEFINE DELPHI_1_UP} 63 | 64 | {$DEFINE COMPILER_7} 65 | {$DEFINE COMPILER_7_UP} 66 | {$DEFINE COMPILER_6_UP} 67 | {$DEFINE COMPILER_5_UP} 68 | {$DEFINE COMPILER_4_UP} 69 | {$DEFINE COMPILER_3_UP} 70 | {$DEFINE COMPILER_2_UP} 71 | {$DEFINE COMPILER_1_UP} 72 | {$ENDIF} 73 | 74 | {$IFDEF VER140} 75 | {$DEFINE DELPHI_6} 76 | {$DEFINE DELPHI_6_UP} 77 | {$DEFINE DELPHI_5_UP} 78 | {$DEFINE DELPHI_4_UP} 79 | {$DEFINE DELPHI_3_UP} 80 | {$DEFINE DELPHI_2_UP} 81 | {$DEFINE DELPHI_1_UP} 82 | 83 | {$DEFINE COMPILER_6} 84 | {$DEFINE COMPILER_6_UP} 85 | {$DEFINE COMPILER_5_UP} 86 | {$DEFINE COMPILER_4_UP} 87 | {$DEFINE COMPILER_3_UP} 88 | {$DEFINE COMPILER_2_UP} 89 | {$DEFINE COMPILER_1_UP} 90 | {$ENDIF} 91 | 92 | {$IFDEF VER130} 93 | {$DEFINE DELPHI_5} 94 | {$DEFINE DELPHI_5_UP} 95 | {$DEFINE DELPHI_4_UP} 96 | {$DEFINE DELPHI_3_UP} 97 | {$DEFINE DELPHI_2_UP} 98 | {$DEFINE DELPHI_1_UP} 99 | 100 | {$DEFINE COMPILER_5} 101 | {$DEFINE COMPILER_5_UP} 102 | {$DEFINE COMPILER_4_UP} 103 | {$DEFINE COMPILER_3_UP} 104 | {$DEFINE COMPILER_2_UP} 105 | {$DEFINE COMPILER_1_UP} 106 | {$ENDIF} 107 | 108 | {$IFDEF VER120} 109 | {$DEFINE DELPHI_4} 110 | {$DEFINE DELPHI_4_UP} 111 | {$DEFINE DELPHI_3_UP} 112 | {$DEFINE DELPHI_2_UP} 113 | {$DEFINE DELPHI_1_UP} 114 | 115 | {$DEFINE COMPILER_4} 116 | {$DEFINE COMPILER_4_UP} 117 | {$DEFINE COMPILER_3_UP} 118 | {$DEFINE COMPILER_2_UP} 119 | {$DEFINE COMPILER_1_UP} 120 | {$ENDIF} 121 | 122 | {$IFDEF VER100} 123 | {$DEFINE DELPHI_3} 124 | {$DEFINE DELPHI_3_UP} 125 | {$DEFINE DELPHI_2_UP} 126 | {$DEFINE DELPHI_1_UP} 127 | 128 | {$DEFINE COMPILER_3} 129 | {$DEFINE COMPILER_3_UP} 130 | {$DEFINE COMPILER_2_UP} 131 | {$DEFINE COMPILER_1_UP} 132 | {$ENDIF} 133 | 134 | {$IFDEF VER90} 135 | {$DEFINE DELPHI_2} 136 | {$DEFINE DELPHI_2_UP} 137 | {$DEFINE DELPHI_1_UP} 138 | 139 | {$DEFINE COMPILER_2} 140 | {$DEFINE COMPILER_2_UP} 141 | {$DEFINE COMPILER_1_UP} 142 | {$ENDIF} 143 | 144 | {$IFDEF VER80} 145 | {$DEFINE DELPHI_1} 146 | {$DEFINE DELPHI_1_UP} 147 | 148 | {$DEFINE COMPILER_1} 149 | {$DEFINE COMPILER_1_UP} 150 | {$ENDIF} 151 | 152 | {$IFNDEF MSWINDOWS} 153 | {$DEFINE MSWINDOWS} 154 | {$ENDIF} 155 | 156 | {$ENDIF} // WIN32 157 | 158 | {$IFNDEF FPC} 159 | {$IFDEF LINUX} 160 | {$I pasdoc_kylixversions.inc} 161 | {$ENDIF} 162 | {$ELSE} 163 | {$ENDIF} 164 | 165 | {$IFDEF DELPHI_7_UP} 166 | {$WARN UNSAFE_CAST OFF} 167 | {$WARN UNSAFE_CODE OFF} 168 | {$WARN UNSAFE_TYPE OFF} 169 | {$ENDIF} 170 | (* Disables .NET warnings for Delphi 7 and later. *) 171 | 172 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SynProject 2 | ========== 3 | 4 | *Synopse SynProject* is an open source application for code source versioning and automated documentation of Delphi projects. 5 | 6 | Licensed under a GPL license. 7 | 8 | [Take a look at the SynProject official web site](http://synopse.info/fossil/wiki?name=SynProject) 9 | 10 | 11 | 12 | Features 13 | ======== 14 | 15 | Its main features are: 16 | 17 | 1. Local source code versioning; 18 | 2. Automated documentation. 19 | 20 | 21 | Source code versioning 22 | ---------------------- 23 | 24 | * handle multiple projects or libraries with the same program; 25 | * allow source code versioning with detailed commits; 26 | * can access to a PVCS tracker (more trackers are coming) and link the commits to the tickets; 27 | * allow automated source code backup (without any commit to document: it's like a daily snapshot of your files); 28 | * backups can be local (on your hard drive) or remote (on a distant drive); 29 | * you can make a visual "diff" and compare source code versions side by side in the graphical user interface; 30 | * you can see pictures (png jpeg bitmap icon) within the main user interface; 31 | * diff storage between version is very optimized, and use little disk space; 32 | * storage is based on .zip files and plain text files, so it's easy to work with. 33 | 34 | Automated Documentation 35 | ----------------------- 36 | 37 | * follow a typical Design Inputs -> Risk Assessment -> Software Architecture -> Detailed Design -> Tests protocols -> Traceability matrix -> Release Notes workflow; 38 | * initial (marketing-level) Design Input can be refined into more precise Software Requirement Specifications; 39 | * Design Inputs can evolve during the project life: all documentation stay synchronized and you will have to maintain the DI and their description only at one place; 40 | * therefore, the process is meant to be compliant with the most precise documentation protocols (like IEC 62304); 41 | only one text file, formated like a wiki, contains the whole documentation; 42 | * it's very easy to add pictures, or formated source code (pascal, C, C++, C#, plain text) into the documentation; 43 | * word files (and then pdf) are created from this content, with full table of contents, picture or source code reference tables, unified page layout, customizable templates; 44 | * it's easy to add tables to your document, or link to other part or external resources * you can even put pure RTF content into your documentation; 45 | * pictures are centralized and captioned, people involved in the documentation are maintained once for the whole documentation; 46 | * document version numbering and cross-referencing is handled easily; 47 | * for pascal projects, the source code is parsed and all interface architecture is generated from the source; 48 | it's easy to browse classes, variables and functions from the documentation, and add reference to them to your document; 49 | the source code description can also be located in an external .sae file, therefore your original source code tree won't necessary be changed by the adding of comments; 50 | * all references are cross-linked: Software Architecture Document is created from the source code, and also is able to highlight the classes or methods - involved in implementing every Design Input, from the Software Design Document; 51 | * integrated GraphViz component, in order to create easily diagrams from plain text embedded into your documentation; * integrated fully featured text editor, with word wrapping, wiki-syntax buttons and keyboard shortcuts, and spell checking; 52 | * a step by step Wizard is available to create a new project, from supplied template files; 53 | another Wizard is already available, to browse your documentation workflow, and check its consistency or set up its parameters; 54 | * the documentation is integrated to the Versioning system above. 55 | 56 | Of course, it's a full Open Source - GPL licensed - project. Source code (for Delphi 6/7) is available and maintained, since it is used by our internal projects (including our little [mORMot](http://mormot.net)). -------------------------------------------------------------------------------- /ProjectEditorCommit.dfm: -------------------------------------------------------------------------------- 1 | object ProjectEditorCommitForm: TProjectEditorCommitForm 2 | Left = 434 3 | Top = 388 4 | BorderStyle = bsDialog 5 | ClientHeight = 300 6 | ClientWidth = 459 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | PixelsPerInch = 96 15 | TextHeight = 13 16 | object DisplayName: TLabeledEdit 17 | Left = 56 18 | Top = 40 19 | Width = 353 20 | Height = 21 21 | EditLabel.Width = 68 22 | EditLabel.Height = 13 23 | EditLabel.Caption = 'Display Name:' 24 | TabOrder = 0 25 | end 26 | object Path: TLabeledEdit 27 | Left = 56 28 | Top = 88 29 | Width = 321 30 | Height = 21 31 | EditLabel.Width = 85 32 | EditLabel.Height = 13 33 | EditLabel.Caption = 'Path to search in:' 34 | TabOrder = 1 35 | end 36 | object BtnOK: TBitBtn 37 | Left = 152 38 | Top = 232 39 | Width = 105 40 | Height = 33 41 | Caption = 'OK' 42 | Default = True 43 | ModalResult = 1 44 | TabOrder = 5 45 | Glyph.Data = { 46 | 96010000424D9601000000000000760000002800000018000000180000000100 47 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 48 | 10001EB6340041CE67001C9830002FC54F0059E3890017AC270034B24C00FC02 49 | FC00178F24004FD977002CB2470024AA3A0038BE580024A23400999999999999 50 | 9999999999999999999999999999999999999999999999999999999999999999 51 | 9999999999999999999999999999099999999999999999999990F09999999999 52 | 99999999990D7C09999999999999999990D277D099999999999999990452277D 53 | 09999999999999904355D0C7D09999999999990ABB3C09027D09999999999906 54 | 6BE09990A7D09999999999086E099999907D0999999999903099999999077099 55 | 9999999909999999999017099999999999999999999990A09999999999999999 56 | 9999990109999999999999999999999900999999999999999999999999099999 57 | 9999999999999999999999999999999999999999999999999999999999999999 58 | 9999999999999999999999999999999999999999999999999999} 59 | end 60 | object BtnCancel: TBitBtn 61 | Left = 304 62 | Top = 232 63 | Width = 105 64 | Height = 33 65 | Cancel = True 66 | Caption = 'Cancel' 67 | ModalResult = 2 68 | TabOrder = 6 69 | Glyph.Data = { 70 | 96010000424D9601000000000000760000002800000018000000180000000100 71 | 04000000000020010000130B0000130B0000100000000000000004029C00FC02 72 | FC001343FA003461F900204FFB000424EA001C42ED000733F7002C4FE4004172 73 | FC00143AEC00052CF7001E48F7002D59F7003967FA002457FC00111111111111 74 | 1111111111111111111111111111111111111111111111111111111111111111 75 | 1001111111111001111111110270111111110BB011111110C22B01111110577B 76 | 011111102C227011110B7B7501111111064C270110B77750111111111064CCA0 77 | 0BBB75011111111111064CCA77B750111111111111106422A77B011111111111 78 | 11110C2222701111111111111111044C22A01111111111111110DF44444A0111 79 | 11111111110D3DDCCF44601111111111103E3E400CF44601111111110E9EE801 80 | 106F446011111110999980111106D44C011111109998011111106DFC01111111 81 | 09D0111111110C40111111111001111111111001111111111111111111111111 82 | 1111111111111111111111111111111111111111111111111111} 83 | end 84 | object FilterDefault: TCheckBox 85 | Left = 56 86 | Top = 120 87 | Width = 353 88 | Height = 17 89 | ParentShowHint = False 90 | ShowHint = True 91 | TabOrder = 3 92 | WordWrap = True 93 | end 94 | object Filters: TLabeledEdit 95 | Left = 56 96 | Top = 168 97 | Width = 353 98 | Height = 21 99 | EditLabel.Width = 275 100 | EditLabel.Height = 13 101 | EditLabel.Caption = 'Additionnal Filters separated by "," ("*.doc,*.rtf,*.emf"):' 102 | TabOrder = 4 103 | end 104 | object BtnPath: TButton 105 | Left = 384 106 | Top = 88 107 | Width = 25 108 | Height = 21 109 | Caption = '...' 110 | TabOrder = 2 111 | OnClick = BtnPathClick 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /ProjectEditorProgram.dfm: -------------------------------------------------------------------------------- 1 | object ProjectEditorProgramForm: TProjectEditorProgramForm 2 | Left = 47 3 | Top = 204 4 | Width = 903 5 | Height = 450 6 | Caption = ' SynProject - Integrated Reference Class Browser' 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | Position = poScreenCenter 15 | PixelsPerInch = 96 16 | TextHeight = 13 17 | object Panel1: TPanel 18 | Left = 0 19 | Top = 0 20 | Width = 895 21 | Height = 41 22 | Align = alTop 23 | TabOrder = 0 24 | DesignSize = ( 25 | 895 26 | 41) 27 | object lUnitName: TLabel 28 | Left = 230 29 | Top = 13 30 | Width = 53 31 | Height = 13 32 | Alignment = taRightJustify 33 | Caption = 'Unit Name:' 34 | end 35 | object lSADSection: TLabel 36 | Left = 29 37 | Top = 13 38 | Width = 62 39 | Height = 13 40 | Alignment = taRightJustify 41 | Caption = 'SAD Section:' 42 | end 43 | object cbUnitName: TComboBox 44 | Left = 287 45 | Top = 10 46 | Width = 170 47 | Height = 21 48 | Style = csDropDownList 49 | DropDownCount = 32 50 | ItemHeight = 13 51 | TabOrder = 0 52 | OnChange = cbUnitNameChange 53 | end 54 | object btnOk: TButton 55 | Left = 713 56 | Top = 8 57 | Width = 74 58 | Height = 25 59 | Anchors = [akTop, akRight] 60 | Caption = 'Save' 61 | ModalResult = 1 62 | TabOrder = 1 63 | end 64 | object btnCancel: TButton 65 | Left = 809 66 | Top = 8 67 | Width = 74 68 | Height = 25 69 | Anchors = [akTop, akRight] 70 | Cancel = True 71 | Caption = 'Cancel' 72 | ModalResult = 2 73 | TabOrder = 2 74 | end 75 | object cbSADSection: TComboBox 76 | Left = 96 77 | Top = 10 78 | Width = 113 79 | Height = 21 80 | Style = csDropDownList 81 | ItemHeight = 13 82 | TabOrder = 3 83 | OnChange = cbSADSectionChange 84 | end 85 | object leUnitDescription: TLabeledEdit 86 | Left = 552 87 | Top = 10 88 | Width = 148 89 | Height = 21 90 | Anchors = [akLeft, akTop, akRight] 91 | EditLabel.Width = 79 92 | EditLabel.Height = 13 93 | EditLabel.Caption = 'Unit Description:' 94 | LabelPosition = lpLeft 95 | LabelSpacing = 3 96 | TabOrder = 4 97 | OnExit = leUnitDescriptionExit 98 | end 99 | end 100 | object pagTypes: TPageControl 101 | Left = 0 102 | Top = 41 103 | Width = 710 104 | Height = 375 105 | Align = alClient 106 | TabOrder = 1 107 | end 108 | object PanelRight: TPanel 109 | Left = 710 110 | Top = 41 111 | Width = 185 112 | Height = 375 113 | Align = alRight 114 | TabOrder = 2 115 | DesignSize = ( 116 | 185 117 | 375) 118 | object l1: TLabel 119 | Left = 8 120 | Top = 328 121 | Width = 166 122 | Height = 13 123 | Anchors = [akLeft, akBottom] 124 | Caption = 'Double-click any left item to add it.' 125 | end 126 | object lstValues: TListBox 127 | Left = 1 128 | Top = 1 129 | Width = 183 130 | Height = 320 131 | Align = alTop 132 | Anchors = [akLeft, akTop, akRight, akBottom] 133 | ItemHeight = 13 134 | TabOrder = 0 135 | OnClick = lstValuesClick 136 | end 137 | object btnDeleteItem: TButton 138 | Left = 8 139 | Top = 344 140 | Width = 75 141 | Height = 25 142 | Anchors = [akLeft, akBottom] 143 | Caption = 'Delete item' 144 | TabOrder = 1 145 | OnClick = btnDeleteItemClick 146 | end 147 | object btnClearList: TButton 148 | Left = 88 149 | Top = 344 150 | Width = 75 151 | Height = 25 152 | Anchors = [akLeft, akBottom] 153 | Caption = 'Clear list' 154 | TabOrder = 2 155 | OnClick = btnClearListClick 156 | end 157 | end 158 | end 159 | -------------------------------------------------------------------------------- /SynProject.dpr: -------------------------------------------------------------------------------- 1 | /// main SynProject program file 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.13 3 | program SynProject; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2016 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | 25 | Compilation hint: 26 | - tested under Delphi 6/7 ONLY - should work with Delphi 2007, but would 27 | NOT work with Delphi 2009/2010/XE (this source code is not Unicode-Ready) 28 | - you should have entered .\PasDocLight in your Project/Options/Directories 29 | SearchPath field 30 | - you should have added the TMemoEx component (from SynMemoEx.pas) to the IDE 31 | - and of course, the synopse Lib directory must be in your Tools/Environment 32 | Options/Libray/Library Path 33 | 34 | *) 35 | 36 | uses 37 | FastMM4, 38 | Forms, 39 | ProjectVersionMain in 'ProjectVersionMain.pas' {MainForm}, 40 | ProjectVersioning in 'ProjectVersioning.pas', 41 | ProjectSections in 'ProjectSections.pas', 42 | ProjectVersionPages in 'ProjectVersionPages.pas' {FramePages: TFrame}, 43 | ProjectFrameViewer in 'ProjectFrameViewer.pas' {FrameViewer: TFrame}, 44 | ProjectMemoExSyntax in 'ProjectMemoExSyntax.pas', 45 | ProjectFormViewOne in 'ProjectFormViewOne.pas' {FormViewOne}, 46 | ProjectFormViewTwo in 'ProjectFormViewTwo.pas' {FormViewTwo}, 47 | ProjectEditor in 'ProjectEditor.pas' {FrameEditor: TFrame}, 48 | ProjectVersionSCR in 'ProjectVersionSCR.pas' {ProjectVersionSCRForm}, 49 | ProjectVersionBackup in 'ProjectVersionBackup.pas' {ProjectVersionBackupForm}, 50 | ProjectFrameRisk in 'ProjectFrameRisk.pas' {FrameRisk: TFrame}, 51 | ProjectVersionCommit in 'ProjectVersionCommit.pas' {ProjectVersionCommitForm}, 52 | ProjectEditMain in 'ProjectEditMain.pas' {ProMainForm}, 53 | ProjectVersionCompare in 'ProjectVersionCompare.pas' {ProjectVersionCompareForm}, 54 | ProjectFormDocWizard in 'ProjectFormDocWizard.pas' {ProjectDocWizard}, 55 | ProjectEditorRelease in 'ProjectEditorRelease.pas' {ProjectEditorReleaseForm}, 56 | ProjectTypes in 'ProjectTypes.pas', 57 | ProjectTrackerLogin in 'ProjectTrackerLogin.pas' {ProjectTrackerLoginForm}, 58 | ProjectEditorCommit in 'ProjectEditorCommit.pas' {ProjectEditorCommitForm}, 59 | ProjectGraphEdit in 'ProjectGraphEdit.pas' {GraphEditForm}, 60 | ProjectSpellCheck in 'ProjectSpellCheck.pas' {SpellCheckForm}, 61 | ProjectEditorProgram in 'ProjectEditorProgram.pas' {ProjectEditorProgramForm}, 62 | ProjectCommons in 'ProjectCommons.pas', 63 | ProjectDiff in 'ProjectDiff.pas', 64 | ProjectDiffUnit in 'ProjectDiffUnit.pas', 65 | ProjectParser in 'ProjectParser.pas', 66 | ProjectRTF in 'ProjectRTF.pas', 67 | ProjectTrkTool in 'ProjectTrkTool.pas', 68 | ProjectFormSelection in 'ProjectFormSelection.pas' {SelectionForm}, 69 | ProjectDiagrams in 'ProjectDiagrams.pas'; 70 | 71 | {$R *.res} 72 | {$R Vista.res} 73 | 74 | begin 75 | Application.Initialize; 76 | Application.CreateForm(TMainForm, MainForm); 77 | Application.CreateForm(TFormViewOne, FormViewOne); 78 | Application.CreateForm(TFormViewTwo, FormViewTwo); 79 | Application.CreateForm(TProjectVersionSCRForm, ProjectVersionSCRForm); 80 | Application.CreateForm(TProjectVersionBackupForm, ProjectVersionBackupForm); 81 | Application.CreateForm(TProjectVersionCommitForm, ProjectVersionCommitForm); 82 | Application.CreateForm(TProMainForm, ProMainForm); 83 | Application.CreateForm(TProjectVersionCompareForm, ProjectVersionCompareForm); 84 | Application.CreateForm(TProjectDocWizard, ProjectDocWizard); 85 | Application.CreateForm(TProjectTrackerLoginForm, ProjectTrackerLoginForm); 86 | Application.Run; 87 | end. 88 | -------------------------------------------------------------------------------- /PasDocLight/PasDoc_StringPairVector.pas: -------------------------------------------------------------------------------- 1 | unit PasDoc_StringPairVector; 2 | 3 | interface 4 | 5 | uses 6 | Classes, 7 | PasDoc_ObjectVector; 8 | 9 | type 10 | TStringPair = class 11 | Name: string; 12 | Value: string; 13 | Data: Pointer; 14 | 15 | { Init Name and Value by @link(ExtractFirstWord) from S. } 16 | constructor CreateExtractFirstWord(const S: string); 17 | 18 | constructor Create(const AName, AValue: string; AData: Pointer = nil); 19 | end; 20 | 21 | { This is a list of string pairs. 22 | This class contains only non-nil objects of class TStringPair. 23 | 24 | Using this class instead of TStringList (with it's Name and Value 25 | properties) is often better, because this allows both Name and Value 26 | of each pair to safely contain any special characters (including '=' 27 | and newline markers). It's also faster, since it doesn't try to 28 | encode Name and Value into one string. } 29 | TStringPairVector = class(TObjectVector) 30 | private 31 | function GetItems(i: Integer): TStringPair; 32 | procedure SetItems(i: Integer; Item: TStringPair); 33 | public 34 | property Items[i: Integer]: TStringPair read GetItems write SetItems; default; 35 | 36 | { Returns all items Names and Values glued together. 37 | For every item, string Name + NameValueSepapator + Value is 38 | constructed. Then all such strings for every items all 39 | concatenated with ItemSeparator. 40 | 41 | Remember that the very idea of @link(TStringPair) and 42 | @link(TStringPairVector) is that Name and Value strings 43 | may contain any special characters, including things you 44 | give here as NameValueSepapator and ItemSeparator. 45 | So it's practically impossible to later convert such Text 46 | back to items and Names/Value pairs. } 47 | function Text(const NameValueSepapator, ItemSeparator: string): string; 48 | 49 | { Finds a string pair with given Name. 50 | Returns -1 if not found. } 51 | function FindName(const Name: string; IgnoreCase: boolean = true): Integer; 52 | 53 | { Removes first string pair with given Name. 54 | Returns if some pair was removed. } 55 | function DeleteName(const Name: string; IgnoreCase: boolean = true): boolean; 56 | end; 57 | 58 | implementation 59 | 60 | uses 61 | SysUtils, 62 | PasDoc_Utils; 63 | 64 | { TStringPair ---------------------------------------------------------------- } 65 | 66 | constructor TStringPair.CreateExtractFirstWord(const S: string); 67 | var 68 | FirstWord, Rest: string; 69 | begin 70 | ExtractFirstWord(S, FirstWord, Rest); 71 | Create(FirstWord, Rest); 72 | end; 73 | 74 | constructor TStringPair.Create(const AName, AValue: string; AData: Pointer); 75 | begin 76 | inherited Create; 77 | Name := AName; 78 | Value := AValue; 79 | Data := AData; 80 | end; 81 | 82 | { TStringPairVector ---------------------------------------------------------- } 83 | 84 | function TStringPairVector.GetItems(i: Integer): TStringPair; 85 | begin 86 | Result := TStringPair(inherited Items[i]); 87 | end; 88 | 89 | procedure TStringPairVector.SetItems(i: Integer; Item: TStringPair); 90 | begin 91 | inherited Items[i] := Item; 92 | end; 93 | 94 | function TStringPairVector.Text( 95 | const NameValueSepapator, ItemSeparator: string): string; 96 | var 97 | i: Integer; 98 | begin 99 | if Count > 0 then 100 | begin 101 | Result := Items[0].Name + NameValueSepapator + Items[0].Value; 102 | for i := 1 to Count - 1 do 103 | Result := Result + ItemSeparator + 104 | Items[i].Name + NameValueSepapator + Items[i].Value; 105 | end; 106 | end; 107 | 108 | function TStringPairVector.FindName(const Name: string; IgnoreCase: boolean): Integer; 109 | begin 110 | if IgnoreCase then 111 | begin 112 | for Result := 0 to Count - 1 do 113 | if SameText(Items[Result].Name, Name) then 114 | Exit; 115 | Result := -1; 116 | end else 117 | begin 118 | for Result := 0 to Count - 1 do 119 | if Items[Result].Name = Name then 120 | Exit; 121 | Result := -1; 122 | end; 123 | end; 124 | 125 | function TStringPairVector.DeleteName(const Name: string; 126 | IgnoreCase: boolean): boolean; 127 | var 128 | i: Integer; 129 | begin 130 | i := FindName(Name, IgnoreCase); 131 | Result := i <> -1; 132 | if Result then 133 | Delete(i); 134 | end; 135 | 136 | end. 137 | -------------------------------------------------------------------------------- /ProjectVersionBackup.dfm: -------------------------------------------------------------------------------- 1 | object ProjectVersionBackupForm: TProjectVersionBackupForm 2 | Left = 639 3 | Top = 349 4 | BorderStyle = bsDialog 5 | ClientHeight = 314 6 | ClientWidth = 434 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | KeyPreview = True 14 | OldCreateOrder = False 15 | Position = poScreenCenter 16 | OnKeyDown = FormKeyDown 17 | OnShow = FormShow 18 | PixelsPerInch = 96 19 | TextHeight = 13 20 | object Label1: TLabel 21 | Left = 56 22 | Top = 24 23 | Width = 175 24 | Height = 13 25 | Caption = 'Select the backups to be performed:' 26 | end 27 | object CheckListBox: TCheckListBox 28 | Left = 48 29 | Top = 40 30 | Width = 329 31 | Height = 153 32 | ItemHeight = 13 33 | TabOrder = 0 34 | end 35 | object BtnSelected: TBitBtn 36 | Left = 56 37 | Top = 208 38 | Width = 161 39 | Height = 33 40 | Caption = 'Backup selected (Enter)' 41 | Default = True 42 | ModalResult = 1 43 | TabOrder = 1 44 | OnClick = BtnSelectedClick 45 | Glyph.Data = { 46 | 96010000424D9601000000000000760000002800000018000000180000000100 47 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 48 | 10001EB6340041CE67001C9830002FC54F0059E3890017AC270034B24C00FC02 49 | FC00178F24004FD977002CB2470024AA3A0038BE580024A23400999999999999 50 | 9999999999999999999999999999999999999999999999999999999999999999 51 | 9999999999999999999999999999099999999999999999999990F09999999999 52 | 99999999990D7C09999999999999999990D277D099999999999999990452277D 53 | 09999999999999904355D0C7D09999999999990ABB3C09027D09999999999906 54 | 6BE09990A7D09999999999086E099999907D0999999999903099999999077099 55 | 9999999909999999999017099999999999999999999990A09999999999999999 56 | 9999990109999999999999999999999900999999999999999999999999099999 57 | 9999999999999999999999999999999999999999999999999999999999999999 58 | 9999999999999999999999999999999999999999999999999999} 59 | end 60 | object BtnAll: TBitBtn 61 | Left = 56 62 | Top = 248 63 | Width = 161 64 | Height = 33 65 | Caption = 'Backup all (F4)' 66 | ModalResult = 8 67 | TabOrder = 2 68 | OnClick = BtnAllClick 69 | Glyph.Data = { 70 | 96010000424D9601000000000000760000002800000018000000180000000100 71 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 72 | 1000D67F7F0024B43C0048D36F00FC02FC001F9B3100B53F3D00CC676800DD99 73 | 99002FC54F0059E3890037BA5400178F24001CAC2F00C4545400555555555555 74 | 5555555555555555555555555555555555555555555550555555555555555555 75 | 5555060555555555555555555550EE305555555555555555550E3EE305555555 76 | 55555555506A33EE3055555555555555064AAE03E305555555555550D4443050 77 | EE30555555555550BBBC07550DEE055555555550CBC08875550EE05555555557 78 | 040888875550EE055555557820287888755501E0555557F9922757888755550D 79 | 055557999275557F887555501055572927555555788755555005557975555555 80 | 578875555550555755555555557F8755555555555555555555557F7555555555 81 | 5555555555555777555555555555555555555557755555555555555555555555 82 | 5755555555555555555555555555555555555555555555555555} 83 | end 84 | object BtnCancel: TBitBtn 85 | Left = 240 86 | Top = 248 87 | Width = 129 88 | Height = 33 89 | Cancel = True 90 | Caption = 'Cancel' 91 | ModalResult = 2 92 | TabOrder = 3 93 | Glyph.Data = { 94 | 96010000424D9601000000000000760000002800000018000000180000000100 95 | 04000000000020010000130B0000130B0000100000000000000004029C00FC02 96 | FC001343FA003461F900204FFB000424EA001C42ED000733F7002C4FE4004172 97 | FC00143AEC00052CF7001E48F7002D59F7003967FA002457FC00111111111111 98 | 1111111111111111111111111111111111111111111111111111111111111111 99 | 1001111111111001111111110270111111110BB011111110C22B01111110577B 100 | 011111102C227011110B7B7501111111064C270110B77750111111111064CCA0 101 | 0BBB75011111111111064CCA77B750111111111111106422A77B011111111111 102 | 11110C2222701111111111111111044C22A01111111111111110DF44444A0111 103 | 11111111110D3DDCCF44601111111111103E3E400CF44601111111110E9EE801 104 | 106F446011111110999980111106D44C011111109998011111106DFC01111111 105 | 09D0111111110C40111111111001111111111001111111111111111111111111 106 | 1111111111111111111111111111111111111111111111111111} 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /ProjectGraphEdit.dfm: -------------------------------------------------------------------------------- 1 | object GraphEditForm: TGraphEditForm 2 | Left = 278 3 | Top = 260 4 | BorderStyle = bsSingle 5 | ClientHeight = 490 6 | ClientWidth = 781 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | KeyPreview = True 14 | OldCreateOrder = False 15 | OnCloseQuery = FormCloseQuery 16 | OnDestroy = FormDestroy 17 | OnKeyUp = FormKeyUp 18 | OnShow = FormShow 19 | PixelsPerInch = 96 20 | TextHeight = 13 21 | object Image: TImage 22 | Left = 323 23 | Top = 0 24 | Width = 458 25 | Height = 490 26 | Align = alClient 27 | Proportional = True 28 | end 29 | object Splitter1: TSplitter 30 | Left = 321 31 | Top = 0 32 | Width = 2 33 | Height = 490 34 | end 35 | object Panel1: TPanel 36 | Left = 0 37 | Top = 0 38 | Width = 321 39 | Height = 490 40 | Align = alLeft 41 | TabOrder = 0 42 | DesignSize = ( 43 | 321 44 | 490) 45 | object Label1: TLabel 46 | Left = 24 47 | Top = 42 48 | Width = 20 49 | Height = 13 50 | Alignment = taRightJustify 51 | Caption = 'Title' 52 | end 53 | object Label2: TLabel 54 | Left = 19 55 | Top = 12 56 | Width = 27 57 | Height = 13 58 | Alignment = taRightJustify 59 | Caption = 'Name' 60 | end 61 | object Label3: TLabel 62 | Left = 8 63 | Top = 392 64 | Width = 297 65 | Height = 54 66 | Anchors = [akLeft, akBottom] 67 | AutoSize = False 68 | Font.Charset = DEFAULT_CHARSET 69 | Font.Color = clWindowText 70 | Font.Height = -11 71 | Font.Name = 'Tahoma' 72 | Font.Style = [] 73 | ParentFont = False 74 | WordWrap = True 75 | end 76 | object Tree: TTreeView 77 | Left = 8 78 | Top = 72 79 | Width = 305 80 | Height = 313 81 | Anchors = [akLeft, akTop, akRight, akBottom] 82 | Indent = 19 83 | MultiSelect = True 84 | MultiSelectStyle = [msControlSelect, msShiftSelect] 85 | ReadOnly = True 86 | TabOrder = 7 87 | Visible = False 88 | OnClick = TreeClick 89 | end 90 | object EditName: TEdit 91 | Left = 48 92 | Top = 8 93 | Width = 201 94 | Height = 21 95 | Anchors = [akLeft, akTop, akRight] 96 | TabOrder = 0 97 | end 98 | object EditTitle: TEdit 99 | Left = 48 100 | Top = 40 101 | Width = 265 102 | Height = 21 103 | Anchors = [akLeft, akTop, akRight] 104 | TabOrder = 1 105 | end 106 | object Source: TMemo 107 | Left = 8 108 | Top = 72 109 | Width = 305 110 | Height = 313 111 | Anchors = [akLeft, akTop, akRight, akBottom] 112 | ScrollBars = ssBoth 113 | TabOrder = 2 114 | WordWrap = False 115 | end 116 | object btnSave: TButton 117 | Left = 16 118 | Top = 453 119 | Width = 97 120 | Height = 25 121 | Anchors = [akLeft, akBottom] 122 | Caption = 'Save' 123 | Font.Charset = DEFAULT_CHARSET 124 | Font.Color = clWindowText 125 | Font.Height = -12 126 | Font.Name = 'Tahoma' 127 | Font.Style = [fsBold] 128 | ModalResult = 1 129 | ParentFont = False 130 | TabOrder = 3 131 | end 132 | object btnClose: TButton 133 | Left = 128 134 | Top = 453 135 | Width = 89 136 | Height = 25 137 | Anchors = [akLeft, akBottom] 138 | Caption = 'Close' 139 | ModalResult = 2 140 | TabOrder = 4 141 | end 142 | object btnRefresh: TButton 143 | Left = 232 144 | Top = 453 145 | Width = 73 146 | Height = 25 147 | Anchors = [akLeft, akBottom] 148 | Caption = 'Refresh F9' 149 | TabOrder = 5 150 | OnClick = btnRefreshClick 151 | end 152 | object btnFromCode: TButton 153 | Left = 256 154 | Top = 6 155 | Width = 59 156 | Height = 25 157 | Anchors = [akTop, akRight] 158 | Caption = 'From code' 159 | TabOrder = 6 160 | OnClick = btnFromCodeClick 161 | end 162 | end 163 | object PopupMenuFromCode: TPopupMenu 164 | TrackButton = tbLeftButton 165 | Left = 272 166 | Top = 32 167 | object FromCodeObjectHierarchyHide: TMenuItem 168 | Caption = 'Hide' 169 | OnClick = FromCodeClick 170 | end 171 | object N1: TMenuItem 172 | Caption = '-' 173 | end 174 | object FromCodeObjecthierarchy: TMenuItem 175 | Caption = 'Object hierarchy' 176 | end 177 | object FromCodeSQLRecord: TMenuItem 178 | Caption = 'TSQLRecord' 179 | end 180 | end 181 | end 182 | -------------------------------------------------------------------------------- /ProjectFormSelection.pas: -------------------------------------------------------------------------------- 1 | unit ProjectFormSelection; 2 | 3 | interface 4 | 5 | uses 6 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 7 | Dialogs, StdCtrls, ExtCtrls; 8 | 9 | type 10 | TSelectionForm = class(TForm) 11 | List: TListBox; 12 | pnlTop: TPanel; 13 | edtFind: TEdit; 14 | btnNext: TButton; 15 | procedure ListDblClick(Sender: TObject); 16 | procedure FormCreate(Sender: TObject); 17 | procedure FormDestroy(Sender: TObject); 18 | procedure FormShow(Sender: TObject); 19 | procedure FormKeyDown(Sender: TObject; var Key: Word; 20 | Shift: TShiftState); 21 | procedure edtFindChange(Sender: TObject); 22 | procedure ListDrawItem(Control: TWinControl; Index: Integer; 23 | Rect: TRect; State: TOwnerDrawState); 24 | public 25 | Lines: TStringList; 26 | OnlyNumberedTitles: boolean; 27 | Selected: integer; 28 | function TitleToNumber(index: integer): integer; 29 | end; 30 | 31 | var 32 | SelectionForm: TSelectionForm; 33 | 34 | 35 | implementation 36 | 37 | {$R *.dfm} 38 | 39 | function TSelectionForm.TitleToNumber(index: integer): integer; 40 | var j: integer; 41 | s: string; 42 | begin 43 | result := 0; 44 | if cardinal(index)>=cardinal(Lines.Count) then 45 | exit; 46 | s := Lines[index]; 47 | if (s='') or (s[1]='[') then 48 | exit; 49 | j := 0; 50 | while s[j+1] in ['0'..'9'] do inc(j); 51 | if j>0 then 52 | result := StrToInt(copy(s,1,j)); 53 | end; 54 | 55 | procedure TSelectionForm.ListDblClick(Sender: TObject); 56 | begin 57 | Selected := List.ItemIndex; 58 | Close; 59 | end; 60 | 61 | procedure TSelectionForm.FormCreate(Sender: TObject); 62 | begin 63 | Lines := TStringList.Create; 64 | end; 65 | 66 | procedure TSelectionForm.FormDestroy(Sender: TObject); 67 | begin 68 | Lines.Free; 69 | end; 70 | 71 | procedure TSelectionForm.FormShow(Sender: TObject); 72 | var i,n,max: integer; 73 | begin 74 | max := 0; 75 | for i := Lines.Count-1 downto 0 do begin 76 | n := TitleToNumber(i); 77 | if n>0 then begin 78 | if n>max then 79 | max := n; 80 | continue; 81 | end; 82 | if not OnlyNumberedTitles then 83 | continue; 84 | Lines.Delete(i); 85 | if Selected>=i then 86 | if Selected=i then 87 | Selected := -1 else 88 | dec(Selected); 89 | end; 90 | if max>0 then 91 | Caption := format('%s - Maximum title # is %d',[Caption,max]); 92 | List.Count := Lines.Count; 93 | if cardinal(Selected)0 then begin 125 | found := i; 126 | break; 127 | end; 128 | if found<0 then 129 | for i := 0 to List.ItemIndex-1 do 130 | if Pos(Search,UpperCase(Lines[i]))>0 then begin 131 | found := i; 132 | break; 133 | end; 134 | if found>=0 then begin 135 | List.TopIndex := found-10; 136 | List.ItemIndex := found; 137 | end; 138 | end; 139 | 140 | procedure TSelectionForm.ListDrawItem(Control: TWinControl; Index: Integer; 141 | Rect: TRect; State: TOwnerDrawState); 142 | var List: TCustomListBox absolute Control; 143 | Data,Number: string; 144 | i,sp: integer; 145 | begin 146 | with List.Canvas do begin 147 | FillRect(Rect); 148 | if cardinal(Index)'' then begin 151 | if Data[1]<>'[' then begin 152 | sp := 0; 153 | while Data[sp+1] in ['0'..'9'] do inc(sp); 154 | Number := copy(Data,1,sp); 155 | delete(Data,1,sp); 156 | sp := 3; 157 | for i := 1 to length(Data) do 158 | if Data[i]=' ' then 159 | inc(sp) else 160 | break; 161 | end else 162 | sp := 1; 163 | TextOut(Rect.Left+sp*8,Rect.Top,Data); 164 | TextOut(Rect.Right-TextWidth(Number)-12,Rect.Top,Number); 165 | end; 166 | end; 167 | end; 168 | end; 169 | 170 | end. 171 | 172 | -------------------------------------------------------------------------------- /ProjectVersionSCR.pas: -------------------------------------------------------------------------------- 1 | /// File Versioning SCR Editor form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectVersionSCR; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, SynMemoEx, 30 | Dialogs, StdCtrls, ExtCtrls, Buttons, ProjectFrameRisk; 31 | 32 | type 33 | TProjectVersionSCRForm = class(TForm) 34 | Description: TLabeledEdit; 35 | ShortName: TLabeledEdit; 36 | Request: TLabeledEdit; 37 | BtnOK: TBitBtn; 38 | BtnCancel: TBitBtn; 39 | Ident: TLabeledEdit; 40 | BtnTrackerImport: TBitBtn; 41 | procedure BtnOKClick(Sender: TObject); 42 | procedure FormShow(Sender: TObject); 43 | procedure FormCreate(Sender: TObject); 44 | procedure BtnTrackerImportClick(Sender: TObject); 45 | private 46 | { Private declarations } 47 | public 48 | { Public declarations } 49 | FrameRisk: TFrameRisk; 50 | TrackNumber: integer; 51 | Risk, 52 | Body: string; 53 | procedure Init(const Title: string); 54 | end; 55 | 56 | var 57 | ProjectVersionSCRForm: TProjectVersionSCRForm; 58 | 59 | function NotVoid(Field: TComponent): boolean; 60 | 61 | resourcestring 62 | SErrorFieldEmpty = 'This field must not be empty'; 63 | 64 | 65 | implementation 66 | 67 | uses ProjectTrackerLogin; 68 | 69 | {$R *.dfm} 70 | 71 | procedure TProjectVersionSCRForm.Init(const Title: string); 72 | begin 73 | Caption := ' '+Title; 74 | Description.Text := ''; 75 | ShortName.Text := ''; 76 | Request.Text := ''; 77 | Ident.Text := ''; 78 | TrackNumber := -1; 79 | Body := ''; 80 | FrameRisk.Init(''); 81 | end; 82 | 83 | function NotVoid(Field: TComponent): boolean; 84 | begin 85 | if Field<>nil then 86 | if Field.InheritsFrom(TLabeledEdit) then begin 87 | result := TLabeledEdit(Field).Text<>''; 88 | if result then exit; 89 | MessageDlg(TLabeledEdit(Field).EditLabel.Caption+#13#13+ 90 | SErrorFieldEmpty,mtError,[mbOk],0); 91 | TLabeledEdit(Field).SetFocus; 92 | exit; 93 | end else 94 | if Field.InheritsFrom(TMemoEx) then begin 95 | result := TMemoEx(Field).Lines.HasText; 96 | if result then exit; 97 | MessageDlg(SErrorFieldEmpty,mtError,[mbOk],0); 98 | TMemoEx(Field).SetFocus; 99 | exit; 100 | end; 101 | result := true; 102 | end; 103 | 104 | procedure TProjectVersionSCRForm.BtnOKClick(Sender: TObject); 105 | begin 106 | if not TryStrToInt(Ident.Text,TrackNumber) then begin 107 | TrackNumber := -1; 108 | MessageDlg(Ident.EditLabel.Caption+' '+Ident.Hint,mtError,[mbOk],0); 109 | Ident.SetFocus; 110 | end else 111 | if (TrackNumber>=0) and notVoid(Description) and notVoid(Request) then begin 112 | Risk := FrameRisk.Risk; 113 | exit; 114 | end; 115 | ModalResult := mrNone; 116 | end; 117 | 118 | 119 | procedure TProjectVersionSCRForm.FormShow(Sender: TObject); 120 | begin 121 | if TrackNumber<0 then 122 | Ident.SetFocus; 123 | end; 124 | 125 | procedure TProjectVersionSCRForm.FormCreate(Sender: TObject); 126 | begin 127 | FrameRisk := TFrameRisk.Create(self); 128 | FrameRisk.Parent := self; 129 | FrameRisk.Left := Ident.Left; 130 | FrameRisk.Top := 216; 131 | end; 132 | 133 | procedure TProjectVersionSCRForm.BtnTrackerImportClick(Sender: TObject); 134 | var F: TProjectTrackerLoginForm; 135 | aDescription, aRequest: string; 136 | begin 137 | F := TrackerLogin(false); 138 | if F<>nil then 139 | try 140 | F.ShowSCRList; 141 | if (F.ShowModal=mrOk) and (F.SelectedID>0) then 142 | try 143 | Screen.Cursor := crHourGlass; 144 | SCRImportOne(F.Tracker,F.SelectedID,aDescription,aRequest,@Body); 145 | Ident.Text := IntToStr(F.SelectedID); 146 | Description.Text := aDescription; 147 | Request.Text := aRequest; 148 | finally 149 | Screen.Cursor := crDefault; 150 | end; 151 | finally 152 | DeleteTempForm(F); 153 | end; 154 | end; 155 | 156 | end. 157 | -------------------------------------------------------------------------------- /ProjectVersionSCR.dfm: -------------------------------------------------------------------------------- 1 | object ProjectVersionSCRForm: TProjectVersionSCRForm 2 | Left = 287 3 | Top = 319 4 | BorderStyle = bsDialog 5 | ClientHeight = 466 6 | ClientWidth = 450 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | Position = poScreenCenter 15 | OnCreate = FormCreate 16 | OnShow = FormShow 17 | PixelsPerInch = 96 18 | TextHeight = 13 19 | object Description: TLabeledEdit 20 | Left = 56 21 | Top = 88 22 | Width = 353 23 | Height = 21 24 | EditLabel.Width = 57 25 | EditLabel.Height = 13 26 | EditLabel.Caption = 'Description:' 27 | TabOrder = 1 28 | end 29 | object ShortName: TLabeledEdit 30 | Left = 56 31 | Top = 136 32 | Width = 353 33 | Height = 21 34 | EditLabel.Width = 85 35 | EditLabel.Height = 13 36 | EditLabel.Caption = 'Short description:' 37 | TabOrder = 2 38 | end 39 | object Request: TLabeledEdit 40 | Left = 56 41 | Top = 184 42 | Width = 353 43 | Height = 21 44 | EditLabel.Width = 121 45 | EditLabel.Height = 13 46 | EditLabel.Caption = 'Request (SCR #55 e.g.):' 47 | TabOrder = 3 48 | end 49 | object BtnOK: TBitBtn 50 | Left = 152 51 | Top = 416 52 | Width = 105 53 | Height = 33 54 | Caption = 'OK' 55 | Default = True 56 | ModalResult = 1 57 | TabOrder = 4 58 | OnClick = BtnOKClick 59 | Glyph.Data = { 60 | 96010000424D9601000000000000760000002800000018000000180000000100 61 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 62 | 10001EB6340041CE67001C9830002FC54F0059E3890017AC270034B24C00FC02 63 | FC00178F24004FD977002CB2470024AA3A0038BE580024A23400999999999999 64 | 9999999999999999999999999999999999999999999999999999999999999999 65 | 9999999999999999999999999999099999999999999999999990F09999999999 66 | 99999999990D7C09999999999999999990D277D099999999999999990452277D 67 | 09999999999999904355D0C7D09999999999990ABB3C09027D09999999999906 68 | 6BE09990A7D09999999999086E099999907D0999999999903099999999077099 69 | 9999999909999999999017099999999999999999999990A09999999999999999 70 | 9999990109999999999999999999999900999999999999999999999999099999 71 | 9999999999999999999999999999999999999999999999999999999999999999 72 | 9999999999999999999999999999999999999999999999999999} 73 | end 74 | object BtnCancel: TBitBtn 75 | Left = 304 76 | Top = 416 77 | Width = 105 78 | Height = 33 79 | Cancel = True 80 | Caption = 'Cancel' 81 | ModalResult = 2 82 | TabOrder = 5 83 | Glyph.Data = { 84 | 96010000424D9601000000000000760000002800000018000000180000000100 85 | 04000000000020010000130B0000130B0000100000000000000004029C00FC02 86 | FC001343FA003461F900204FFB000424EA001C42ED000733F7002C4FE4004172 87 | FC00143AEC00052CF7001E48F7002D59F7003967FA002457FC00111111111111 88 | 1111111111111111111111111111111111111111111111111111111111111111 89 | 1001111111111001111111110270111111110BB011111110C22B01111110577B 90 | 011111102C227011110B7B7501111111064C270110B77750111111111064CCA0 91 | 0BBB75011111111111064CCA77B750111111111111106422A77B011111111111 92 | 11110C2222701111111111111111044C22A01111111111111110DF44444A0111 93 | 11111111110D3DDCCF44601111111111103E3E400CF44601111111110E9EE801 94 | 106F446011111110999980111106D44C011111109998011111106DFC01111111 95 | 09D0111111110C40111111111001111111111001111111111111111111111111 96 | 1111111111111111111111111111111111111111111111111111} 97 | end 98 | object Ident: TLabeledEdit 99 | Left = 56 100 | Top = 40 101 | Width = 225 102 | Height = 21 103 | Hint = 'This field must have a valid numeric value' 104 | EditLabel.Width = 69 105 | EditLabel.Height = 13 106 | EditLabel.Caption = 'Track number:' 107 | ParentShowHint = False 108 | ShowHint = True 109 | TabOrder = 0 110 | end 111 | object BtnTrackerImport: TBitBtn 112 | Left = 296 113 | Top = 38 114 | Width = 113 115 | Height = 25 116 | Caption = 'Tracker Import' 117 | TabOrder = 6 118 | OnClick = BtnTrackerImportClick 119 | Glyph.Data = { 120 | F6000000424DF600000000000000760000002800000010000000100000000100 121 | 0400000000008000000000000000000000001000000000000000040204000482 122 | 0400848204008402040004FE0400FCFEFC00FC02040004FEFC00000040000000 123 | 00000000000000000000DFFBC100DA67AB00410080007E007C00000555500000 124 | 0000002222500000000000222253633300000022225136363600002222541413 125 | 3330002222514141363603222257143413630622225147414413552222555474 126 | 7143222222225747471422222222577474732222222266774743006666676664 127 | 7460006466777666436000067464666366000000024744660000} 128 | end 129 | end 130 | -------------------------------------------------------------------------------- /ProjectEditorRelease.dfm: -------------------------------------------------------------------------------- 1 | object ProjectEditorReleaseForm: TProjectEditorReleaseForm 2 | Left = 399 3 | Top = 191 4 | BorderStyle = bsDialog 5 | ClientHeight = 276 6 | ClientWidth = 458 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | Position = poScreenCenter 15 | OnShow = FormShow 16 | PixelsPerInch = 96 17 | TextHeight = 13 18 | object Description: TLabeledEdit 19 | Left = 56 20 | Top = 88 21 | Width = 353 22 | Height = 21 23 | EditLabel.Width = 57 24 | EditLabel.Height = 13 25 | EditLabel.Caption = 'Description:' 26 | TabOrder = 1 27 | end 28 | object BtnCurrent: TBitBtn 29 | Left = 112 30 | Top = 184 31 | Width = 145 32 | Height = 33 33 | Caption = 'Change Current' 34 | Default = True 35 | ModalResult = 1 36 | TabOrder = 4 37 | OnClick = BtnCurrentClick 38 | Glyph.Data = { 39 | 96010000424D9601000000000000760000002800000018000000180000000100 40 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 41 | 10001EB6340041CE67001C9830002FC54F0059E3890017AC270034B24C00FC02 42 | FC00178F24004FD977002CB2470024AA3A0038BE580024A23400999999999999 43 | 9999999999999999999999999999999999999999999999999999999999999999 44 | 9999999999999999999999999999099999999999999999999990F09999999999 45 | 99999999990D7C09999999999999999990D277D099999999999999990452277D 46 | 09999999999999904355D0C7D09999999999990ABB3C09027D09999999999906 47 | 6BE09990A7D09999999999086E099999907D0999999999903099999999077099 48 | 9999999909999999999017099999999999999999999990A09999999999999999 49 | 9999990109999999999999999999999900999999999999999999999999099999 50 | 9999999999999999999999999999999999999999999999999999999999999999 51 | 9999999999999999999999999999999999999999999999999999} 52 | end 53 | object BtnCancel: TBitBtn 54 | Left = 304 55 | Top = 184 56 | Width = 105 57 | Height = 33 58 | Cancel = True 59 | Caption = 'Cancel' 60 | ModalResult = 2 61 | TabOrder = 6 62 | Glyph.Data = { 63 | 96010000424D9601000000000000760000002800000018000000180000000100 64 | 04000000000020010000130B0000130B0000100000000000000004029C00FC02 65 | FC001343FA003461F900204FFB000424EA001C42ED000733F7002C4FE4004172 66 | FC00143AEC00052CF7001E48F7002D59F7003967FA002457FC00111111111111 67 | 1111111111111111111111111111111111111111111111111111111111111111 68 | 1001111111111001111111110270111111110BB011111110C22B01111110577B 69 | 011111102C227011110B7B7501111111064C270110B77750111111111064CCA0 70 | 0BBB75011111111111064CCA77B750111111111111106422A77B011111111111 71 | 11110C2222701111111111111111044C22A01111111111111110DF44444A0111 72 | 11111111110D3DDCCF44601111111111103E3E400CF44601111111110E9EE801 73 | 106F446011111110999980111106D44C011111109998011111106DFC01111111 74 | 09D0111111110C40111111111001111111111001111111111111111111111111 75 | 1111111111111111111111111111111111111111111111111111} 76 | end 77 | object Version: TLabeledEdit 78 | Left = 56 79 | Top = 40 80 | Width = 353 81 | Height = 21 82 | EditLabel.Width = 172 83 | EditLabel.Height = 13 84 | EditLabel.Caption = 'Version release number (1.01 e.g.):' 85 | ParentShowHint = False 86 | ShowHint = True 87 | TabOrder = 0 88 | end 89 | object Date: TLabeledEdit 90 | Left = 56 91 | Top = 136 92 | Width = 297 93 | Height = 21 94 | EditLabel.Width = 65 95 | EditLabel.Height = 13 96 | EditLabel.Caption = 'Version Date:' 97 | TabOrder = 2 98 | end 99 | object BtnToday: TButton 100 | Left = 368 101 | Top = 136 102 | Width = 45 103 | Height = 25 104 | Caption = 'Today' 105 | TabOrder = 3 106 | OnClick = BtnTodayClick 107 | end 108 | object BtnNew: TBitBtn 109 | Left = 112 110 | Top = 224 111 | Width = 145 112 | Height = 33 113 | Caption = 'Create new version' 114 | ModalResult = 1 115 | TabOrder = 5 116 | OnClick = BtnCurrentClick 117 | Glyph.Data = { 118 | 96010000424D9601000000000000760000002800000018000000180000000100 119 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 120 | 1000D67F7F0024B43C0048D36F00FC02FC001F9B3100B53F3D00CC676800DD99 121 | 99002FC54F0059E3890037BA5400178F24001CAC2F00C4545400555555555555 122 | 5555555555555555555555555555555555555555555550555555555555555555 123 | 5555060555555555555555555550EE305555555555555555550E3EE305555555 124 | 55555555506A33EE3055555555555555064AAE03E305555555555550D4443050 125 | EE30555555555550BBBC07550DEE055555555550CBC08875550EE05555555557 126 | 040888875550EE055555557820287888755501E0555557F9922757888755550D 127 | 055557999275557F887555501055572927555555788755555005557975555555 128 | 578875555550555755555555557F8755555555555555555555557F7555555555 129 | 5555555555555777555555555555555555555557755555555555555555555555 130 | 5755555555555555555555555555555555555555555555555555} 131 | end 132 | end 133 | -------------------------------------------------------------------------------- /ProjectVersionCommit.pas: -------------------------------------------------------------------------------- 1 | /// File Versioning Commit form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectVersionCommit; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 30 | Dialogs, StdCtrls, Buttons, CheckLst, ProjectCommons, ExtCtrls, ProjectVersioning; 31 | 32 | type 33 | TProjectVersionCommitForm = class(TForm) 34 | CheckListBox: TCheckListBox; 35 | Label1: TLabel; 36 | BtnSelected: TBitBtn; 37 | BtnAll: TBitBtn; 38 | BtnCancel: TBitBtn; 39 | Description: TLabeledEdit; 40 | Label2: TLabel; 41 | Comments: TMemo; 42 | Label3: TLabel; 43 | SCR: TComboBox; 44 | PVCS: TCheckBox; 45 | procedure FormKeyDown(Sender: TObject; var Key: Word; 46 | Shift: TShiftState); 47 | procedure BtnAllClick(Sender: TObject); 48 | procedure BtnSelectedClick(Sender: TObject); 49 | procedure FormShow(Sender: TObject); 50 | procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 51 | private 52 | { Private declarations } 53 | public 54 | Selected: TIntegerDynArray; 55 | procedure Init(const Title: string; Versions: TVersions); 56 | end; 57 | 58 | var 59 | ProjectVersionCommitForm: TProjectVersionCommitForm; 60 | 61 | implementation 62 | 63 | uses 64 | ProjectVersionSCR, // for notVoid() 65 | ProjectSections; 66 | 67 | 68 | {$R *.dfm} 69 | 70 | procedure TProjectVersionCommitForm.FormKeyDown(Sender: TObject; 71 | var Key: Word; Shift: TShiftState); 72 | begin 73 | if byte(Shift)=0 then 74 | case Key of 75 | vk_F3: BtnSelected.Click; 76 | vk_F4: BtnAll.Click; 77 | end; 78 | end; 79 | 80 | procedure TProjectVersionCommitForm.BtnAllClick(Sender: TObject); 81 | var i: integer; 82 | begin 83 | SetLength(Selected,CheckListBox.Count); 84 | with CheckListBox.Items do 85 | for i := 0 to Count-1 do 86 | Selected[i] := integer(Objects[i]); 87 | end; 88 | 89 | procedure TProjectVersionCommitForm.BtnSelectedClick(Sender: TObject); 90 | var n,i: integer; 91 | begin 92 | SetLength(Selected,CheckListBox.Count); 93 | n := 0; 94 | with CheckListBox.Items do 95 | for i := 0 to Count-1 do 96 | if CheckListBox.Checked[i] then begin 97 | Selected[n] := integer(Objects[i]); 98 | inc(n); 99 | end; 100 | Setlength(Selected,n); 101 | end; 102 | 103 | procedure TProjectVersionCommitForm.FormShow(Sender: TObject); 104 | begin 105 | Description.SetFocus; 106 | end; 107 | 108 | procedure TProjectVersionCommitForm.FormCloseQuery(Sender: TObject; 109 | var CanClose: Boolean); 110 | begin 111 | if not (ModalResult in [mrOK,mrAll]) then exit; 112 | if NotVoid(Description) then exit; 113 | CanClose := false; 114 | end; 115 | 116 | procedure TProjectVersionCommitForm.Init(const Title: string; Versions: TVersions); 117 | var i, s, Value,Code: integer; 118 | sel, u, last: string; 119 | aSCR: TSectionsStorage; 120 | Sec: TSection; 121 | begin 122 | Caption := ' '+Title; 123 | Description.Text := ''; 124 | Comments.Clear; 125 | PVCS.Checked := isTrue(Versions.Params['CommitToPVCS']); 126 | sel := Versions.Params['LastUpdate']; // LastUpdate=012 127 | with CheckListBox.Items do begin 128 | Clear; // Update4=IFA Software;Synopse\IFA2;FilterDefault,*.sld,*.ias 129 | for i := 0 to 9 do begin 130 | u := Versions.Params['Update'+IntToStr(i)]; 131 | if u='' then continue; 132 | AddObject(format('%s - %s',[ValAt(u,0,';'),ValAt(u,1,';')]),pointer(i)); 133 | if pos(chr(i+48),sel)>0 then 134 | CheckListBox.Checked[Count-1] := true; 135 | end; 136 | end; 137 | with SCR.Items do begin 138 | Clear; 139 | aSCR := Versions.SCR; 140 | if aSCR<>nil then begin 141 | s := 0; 142 | last := Versions.Commits[Versions.Params['LastCommit']]['SCR']; 143 | AddObject('-=- None -=-',pointer(-1)); 144 | for i := 0 to aSCR.Sections.Count-1 do begin 145 | Sec := aSCR.Sections[i]; 146 | Val(Sec.SectionName,Value,Code); 147 | if Code<>0 then continue; // [section] must be numeric 148 | AddObject(format('%s - %s',[Sec.SectionName,Sec.ShortDescription('')]), 149 | pointer(Value)); 150 | if Sec.SectionName=last then 151 | s := Count-1; 152 | end; 153 | SCR.ItemIndex := s; 154 | end; 155 | end; 156 | end; 157 | 158 | end. 159 | -------------------------------------------------------------------------------- /ProjectEditorRelease.pas: -------------------------------------------------------------------------------- 1 | /// Documentation editor Version number wizard form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectEditorRelease; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 30 | Dialogs, StdCtrls, ExtCtrls, Buttons, 31 | ProjectSections; 32 | 33 | type 34 | TProjectEditorReleaseForm = class(TForm) 35 | Description: TLabeledEdit; 36 | BtnCurrent: TBitBtn; 37 | BtnCancel: TBitBtn; 38 | Version: TLabeledEdit; 39 | Date: TLabeledEdit; 40 | BtnToday: TButton; 41 | BtnNew: TBitBtn; 42 | procedure BtnCurrentClick(Sender: TObject); 43 | procedure FormShow(Sender: TObject); 44 | procedure BtnTodayClick(Sender: TObject); 45 | private 46 | Doc: TSection; 47 | public 48 | procedure Init(aDoc: TSection); 49 | end; 50 | 51 | 52 | resourcestring 53 | sNewReleaseForDocumentN = 'New Release for the "%s" document'; 54 | sDocumentVersionNumberN = '"%s" document version number (1.01 e.g.):'; 55 | sErrorRevisionNotInUserN = 'The revision %s is not in use - please enter an existing one'; 56 | sErrorRevisionUsedN = 'The revision %s is already used - please enter a new value'; 57 | 58 | 59 | implementation 60 | 61 | uses 62 | ProjectCommons, 63 | ProjectFormDocWizard, 64 | ProjectVersionSCR; 65 | 66 | { 67 | Revision=0.1 68 | RevisionDescription=Initial Version 69 | RevisionDate=October 1, 2008 70 | } 71 | 72 | {$R *.dfm} 73 | 74 | procedure TProjectEditorReleaseForm.Init(aDoc: TSection); 75 | var Title: string; 76 | begin 77 | if self=nil then exit; 78 | Doc := aDoc; 79 | Title := Doc.DisplayName(nil); 80 | Caption := ' '+format(sNewReleaseForDocumentN,[Title]); 81 | Version.EditLabel.Caption := format(sDocumentVersionNumberN,[Title]); 82 | Version.Text := aDoc['Revision']; 83 | Description.Text := aDoc['RevisionDescription']; 84 | Date.Text := aDoc['RevisionDate']; 85 | end; 86 | 87 | procedure TProjectEditorReleaseForm.BtnCurrentClick(Sender: TObject); 88 | var i, num, first: integer; 89 | s,up: string; 90 | oldDate: boolean; 91 | begin 92 | ModalResult := mrNone; 93 | if not notVoid(Version) or not notVoid(Description) then exit; 94 | up := uppercase(trim(Version.Text)); 95 | if Sender=BtnCurrent then begin 96 | if not SameText(Doc['Revision'],up) then begin // check is current 97 | MessageErrFmt(sErrorRevisionNotInUserN,up); 98 | Version.SetFocus; 99 | exit; 100 | end; 101 | Doc['RevisionDescription'] := Description.Text; 102 | Doc['RevisionDate'] := Date.Text; 103 | end else 104 | if Sender=BtnNew then begin 105 | first := -1; 106 | num := -1; 107 | for i := 0 to Doc.Lines.Count-1 do begin 108 | s := Doc.Lines[i]; 109 | if (s='') or (s[1]=':') then break; 110 | if IdemPChar(pointer(s),'REVISION=') then begin 111 | if first<0 then 112 | first := i; 113 | if IdemPChar(@s[length('REVISION=')+1],pointer(up)) then begin 114 | num := i; 115 | break; 116 | end; 117 | end; 118 | end; 119 | if num>=0 then begin // check if unique 120 | MessageErrFmt(sErrorRevisionUsedN,up); 121 | Version.SetFocus; 122 | exit; 123 | end; 124 | if Doc['RevisionDate']='' then begin 125 | Doc['RevisionDate'] := trim(Date.Text); // update old version date 126 | oldDate := true; 127 | end else 128 | oldDate := false; 129 | if first<0 then begin // no Revision= yet -> just add new 130 | Doc['Revision'] := up; 131 | Doc['RevisionDescription'] := trim(Description.Text); 132 | // RevisionDate was '' -> already set 133 | end else begin // add before any existing Revision= 134 | if oldDate then 135 | Doc.Lines.Insert(first,'RevisionDate=') else 136 | Doc.Lines.Insert(first,'RevisionDate='+trim(Date.Text)); 137 | Doc.Lines.Insert(first,'RevisionDescription='+trim(Description.Text)); 138 | Doc.Lines.Insert(first,'Revision='+up); 139 | end; 140 | end; 141 | ModalResult := mrOk; 142 | end; 143 | 144 | 145 | procedure TProjectEditorReleaseForm.FormShow(Sender: TObject); 146 | begin 147 | if Version.Text='' then 148 | Version.SetFocus; 149 | end; 150 | 151 | procedure TProjectEditorReleaseForm.BtnTodayClick(Sender: TObject); 152 | var s: string; 153 | begin 154 | DateTimeToString(s,'mmmm d, yyyy',now); 155 | Date.Text := s; 156 | end; 157 | 158 | end. 159 | -------------------------------------------------------------------------------- /PasDocLight/PasDoc_Serialize.pas: -------------------------------------------------------------------------------- 1 | unit PasDoc_Serialize; 2 | 3 | interface 4 | uses 5 | Classes, 6 | SysUtils; 7 | 8 | type 9 | TSerializable = class; 10 | TSerializableClass = class of TSerializable; 11 | 12 | TSerializable = class 13 | private 14 | FWasDeserialized: boolean; 15 | protected 16 | procedure Serialize(const ADestination: TStream); virtual; 17 | procedure Deserialize(const ASource: TStream); virtual; 18 | public 19 | class function LoadStringFromStream(const ASource: TStream): string; 20 | class procedure SaveStringToStream(const AValue: string; const ADestination: TStream); 21 | class function LoadDoubleFromStream(const ASource: TStream): double; 22 | class procedure SaveDoubleToStream(const AValue: double; const ADestination: TStream); 23 | class function LoadIntegerFromStream(const ASource: TStream): Integer; 24 | class procedure SaveIntegerToStream(const AValue: Integer; const ADestination: TStream); 25 | 26 | constructor Create; virtual; 27 | class procedure SerializeObject(const AObject: TSerializable; const ADestination: TStream); 28 | class function DeserializeObject(const ASource: TStream): TSerializable; 29 | class procedure Register(const AClass: TSerializableClass); 30 | procedure SerializeToFile(const AFileName: string); 31 | class function DeserializeFromFile(const AFileName: string): TSerializable; 32 | class function DeserializeFromStream(AStream: TStream): TSerializable; 33 | property WasDeserialized: boolean read FWasDeserialized; 34 | end; 35 | 36 | ESerializedException = class(Exception); 37 | 38 | implementation 39 | 40 | uses 41 | PasDoc_Utils; 42 | 43 | var 44 | GClassNames: TStringList; 45 | 46 | { TSerializable } 47 | 48 | constructor TSerializable.Create; 49 | begin 50 | inherited; 51 | end; 52 | 53 | procedure TSerializable.Serialize(const ADestination: TStream); 54 | begin 55 | end; 56 | 57 | procedure TSerializable.Deserialize(const ASource: TStream); 58 | begin 59 | FWasDeserialized := True; 60 | end; 61 | 62 | class function TSerializable.DeserializeFromFile( 63 | const AFileName: string): TSerializable; 64 | var LF: THeapMemoryStream; 65 | begin 66 | LF := THeapMemoryStream.Create; 67 | LF.LoadFromFile(AFileName); 68 | try 69 | Result := DeserializeObject(LF); 70 | finally 71 | LF.Free; 72 | end; 73 | end; 74 | 75 | class function TSerializable.DeserializeFromStream(AStream: TStream): TSerializable; 76 | begin 77 | Result := DeserializeObject(AStream); 78 | end; 79 | 80 | class function TSerializable.DeserializeObject( 81 | const ASource: TStream): TSerializable; 82 | var S: string; 83 | L: integer; 84 | LClass: TSerializableClass; 85 | Idx: Integer; 86 | begin 87 | L := 0; 88 | ASource.Read(L, 1); 89 | Setlength(S,L); 90 | ASource.Read(S[1], L); 91 | Idx := GClassNames.IndexOf(S); 92 | if Idx<0 then begin 93 | raise ESerializedException.CreateFmt('Tried loading unknown class %s', [S]); 94 | end else begin 95 | LClass := TSerializableClass(GClassNames.Objects[Idx]); 96 | Result := LClass.Create; 97 | Result.Deserialize(ASource); 98 | end; 99 | end; 100 | 101 | class function TSerializable.LoadIntegerFromStream( 102 | const ASource: TStream): Integer; 103 | begin 104 | ASource.Read(Result, SizeOf(Result)); 105 | end; 106 | 107 | class function TSerializable.LoadDoubleFromStream( 108 | const ASource: TStream): double; 109 | begin 110 | ASource.Read(Result, SizeOf(Result)); 111 | end; 112 | 113 | class function TSerializable.LoadStringFromStream( 114 | const ASource: TStream): string; 115 | var L: Integer; 116 | begin 117 | ASource.Read(L, SizeOf(L)); 118 | SetLength(Result, L); 119 | ASource.Read(Pointer(Result)^, L); 120 | end; 121 | 122 | class procedure TSerializable.Register(const AClass: TSerializableClass); 123 | begin 124 | GClassNames.AddObject(AClass.ClassName, TObject(AClass)); 125 | end; 126 | 127 | class procedure TSerializable.SaveIntegerToStream( 128 | const AValue: Integer; const ADestination: TStream); 129 | begin 130 | ADestination.Write(AValue, SizeOf(AValue)); 131 | end; 132 | 133 | class procedure TSerializable.SaveDoubleToStream(const AValue: double; 134 | const ADestination: TStream); 135 | begin 136 | ADestination.Write(AValue, SizeOf(AValue)); 137 | end; 138 | 139 | class procedure TSerializable.SaveStringToStream(const AValue: string; 140 | const ADestination: TStream); 141 | var L: Integer; 142 | begin 143 | L := Length(AValue); 144 | ADestination.Write(L, SizeOf(L)); 145 | ADestination.Write(Pointer(AValue)^, L); 146 | end; 147 | 148 | class procedure TSerializable.SerializeObject(const AObject: TSerializable; 149 | const ADestination: TStream); 150 | var 151 | S: shortstring; 152 | begin 153 | S := AObject.ClassName; 154 | if GClassNames.IndexOf(S)<0 then 155 | raise ESerializedException.CreateFmt('Tried saving unregistered class %s', [S]); 156 | ADestination.Write(S[0], Byte(S[0])+1); 157 | AObject.Serialize(ADestination); 158 | end; 159 | 160 | procedure TSerializable.SerializeToFile(const AFileName: string); 161 | var 162 | LF: THeapMemoryStream; 163 | begin 164 | LF := THeapMemoryStream.Create; 165 | try 166 | SerializeObject(Self, LF); 167 | LF.SaveToFile(AFileName); 168 | finally 169 | LF.Free; 170 | end; 171 | end; 172 | 173 | 174 | 175 | initialization 176 | GClassNames := TStringList.Create; 177 | GClassNames.Sorted := true; // faster IndexOf() 178 | finalization 179 | GClassNames.Free; 180 | end. 181 | -------------------------------------------------------------------------------- /ProjectDiagrams.pas: -------------------------------------------------------------------------------- 1 | /// UML diagrams rendering 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.18 3 | unit ProjectDiagrams; 4 | 5 | interface 6 | 7 | uses 8 | Graphics, 9 | SysUtils, 10 | Classes; 11 | 12 | /// convert a text sequence into an UML-like vectorial diagram 13 | // - returns nil if the supplied content is incorrect 14 | // - text syntax is pretty easy: 15 | // $A=Alice // optional participant naming and ordering 16 | // $B=Bob 17 | // $A->B:synchronous call 18 | // $A->>A:asynchronous arrow 19 | // $B-->A:dotted open arrow 20 | // $A->:Authentication Request 21 | // $alt:successful case // alternative group 22 | // $ B->A:Authentication Accepted // internal lines shall be indented 23 | // $:on failure // same level group will be 24 | // $ B->A:authentication Failure 25 | // $ opt: // nested group 26 | // $ loop:10000 times 27 | // $ A->B:DNS attack 28 | // $:on timeout 29 | // $ B->A:please retry 30 | // $A->+Service:DoQuery() // + - notifies lifeline activation 31 | // $+Service->Domain:PrepareQuery() 32 | // $Domain-->TQuery:Prepare() 33 | // $-Domain-->Service 34 | // $+Service->Domain:CommitQuery() 35 | // $*TQuery // * destroy a participant 36 | function UMLSequenceToMetaFile(const Content: string): TMetafile; 37 | 38 | 39 | { 40 | C=Customer 41 | O=Order 42 | M=Menu Manager 43 | ?>>C:hunger 44 | >>O:< 45 | loop:until complete 46 | >:Add item 47 | >M:Check Available 48 | <:a Callback 49 | =:a self message 50 | >:return 51 | ref:complete Order And Pay 52 | M>?:Stock update 53 | 54 | 55 | W=Website 56 | H=Warehouse 57 | B=Banck 58 | ? "Customer Order" W 59 | alt:deliver to home 60 | W processPayment H <> 61 | H "validate card" B <> 62 | W mailToHome H <> 63 | :collect from store 64 | W mailToStore H <> 65 | 66 | C=Customer 67 | O=Order 68 | M=Menu Manager 69 | ? hunger C 70 | C <> O 71 | loop:until complete 72 | C "Add item" O 73 | O "Check Available" M <> 74 | M "a Callback" O "<>" 75 | O "a self message" O 76 | ref:Complete Order and Pay 77 | M "Stock update" ? 78 | 79 | } 80 | implementation 81 | 82 | type 83 | TUMLSequenceLineStyle = (slsSynchCall, slsAsynchCall, slsSynchReturn); 84 | TUMLSequence = class 85 | protected 86 | function ParticipantIndex(const aName, aIdent: string; 87 | CreateIfNotExisting: boolean=true): integer; 88 | public 89 | Participant: array of record 90 | Name: string; 91 | Ident: string; 92 | end; 93 | Items: array of record 94 | Style: TUMLSequenceLineStyle; 95 | FromParticipant: integer; 96 | ToParticipant: integer; 97 | end; 98 | procedure ParseLine(Line: string); 99 | function RenderContent: TMetaFile; 100 | end; 101 | 102 | 103 | function UMLSequenceToMetaFile(const Content: string): TMetafile; 104 | var Lines: TStringList; 105 | i: integer; 106 | begin 107 | with TUMLSequence.Create do 108 | try 109 | Lines := TStringList.Create; 110 | try 111 | Lines.Text := Content; 112 | for i := 0 to Lines.Count-1 do 113 | ParseLine(Lines[i]); 114 | finally 115 | Lines.Free; 116 | end; 117 | result := RenderContent; 118 | finally 119 | Free; 120 | end; 121 | end; 122 | 123 | 124 | { TUMLSequence } 125 | 126 | procedure TUMLSequence.ParseLine(Line: string); 127 | var i,j: integer; 128 | activation: (aNone, aActivate, aDisactivate, aDestroy); 129 | fromPart, toPart: string; 130 | style: TUMLSequenceLineStyle; 131 | begin 132 | if (Line='') or (Line[1]=';') then 133 | exit; 134 | // A=Alice or Alice= 135 | for i := 1 to length(Line) do 136 | if Line[i]='=' then begin 137 | ParticipantIndex(Copy(Line,1,i-1),copy(Line,i+1,1000)); 138 | exit; 139 | end else 140 | if not (Line[i] in ['A'..'Z','a'..'z','0'..'9','_']) then 141 | break; 142 | case Line[1] of 143 | '+': activation := aActivate; 144 | '-': activation := aDisactivate; 145 | '*': activation := aDestroy; 146 | else activation := aNone; 147 | end; 148 | if activation<>aNone then 149 | delete(Line,1,1); 150 | // A->B or Alice-->Bob 151 | for i := 1 to length(Line) do 152 | if Line[i]=':' then break else 153 | if Line[i]='-' then begin 154 | fromPart := copy(line,1,i-1); 155 | j := i+1; 156 | if j>=length(Line) then 157 | break; 158 | if line[j]='>' then 159 | if line[j+1]='>' then begin 160 | style := slsAsynchCall; 161 | inc(j,2); 162 | end else begin 163 | style := slsSynchCall; 164 | inc(j); 165 | end else 166 | if (line[j]='-') and (line[j+1]='>') then begin 167 | style := slsSynchReturn; 168 | inc(j,2); 169 | end else 170 | break; 171 | // TO BE DONE 172 | exit; 173 | end; 174 | 175 | end; 176 | 177 | function TUMLSequence.ParticipantIndex(const aName, aIdent: string; 178 | CreateIfNotExisting: boolean): integer; 179 | begin 180 | for result := 0 to high(Participant) do 181 | if Participant[result].Name=aName then 182 | exit; 183 | if CreateIfNotExisting then begin 184 | result := Length(Participant); 185 | SetLength(Participant,result+1); 186 | Participant[result].Name := aName; 187 | if aIdent='' then 188 | Participant[result].Ident := aName else 189 | Participant[result].Ident := aIdent; 190 | end else 191 | result := -1; 192 | end; 193 | 194 | function TUMLSequence.RenderContent: TMetaFile; 195 | begin 196 | 197 | end; 198 | 199 | end. 200 | -------------------------------------------------------------------------------- /ProjectVersionCommit.dfm: -------------------------------------------------------------------------------- 1 | object ProjectVersionCommitForm: TProjectVersionCommitForm 2 | Left = 401 3 | Top = 201 4 | BorderStyle = bsDialog 5 | ClientHeight = 513 6 | ClientWidth = 434 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | KeyPreview = True 14 | OldCreateOrder = False 15 | Position = poScreenCenter 16 | OnCloseQuery = FormCloseQuery 17 | OnKeyDown = FormKeyDown 18 | OnShow = FormShow 19 | PixelsPerInch = 96 20 | TextHeight = 13 21 | object Label1: TLabel 22 | Left = 48 23 | Top = 264 24 | Width = 165 25 | Height = 13 26 | Caption = 'Precise the extend of this Commit:' 27 | end 28 | object Label2: TLabel 29 | Left = 48 30 | Top = 112 31 | Width = 54 32 | Height = 13 33 | Caption = 'Comments:' 34 | end 35 | object Label3: TLabel 36 | Left = 48 37 | Top = 64 38 | Width = 129 39 | Height = 13 40 | Caption = 'Associated SCR in Tracker:' 41 | end 42 | object CheckListBox: TCheckListBox 43 | Left = 48 44 | Top = 280 45 | Width = 329 46 | Height = 121 47 | ItemHeight = 13 48 | TabOrder = 3 49 | end 50 | object BtnSelected: TBitBtn 51 | Left = 56 52 | Top = 416 53 | Width = 161 54 | Height = 33 55 | Caption = 'Commit selected (F3)' 56 | Default = True 57 | ModalResult = 1 58 | TabOrder = 4 59 | OnClick = BtnSelectedClick 60 | Glyph.Data = { 61 | 96010000424D9601000000000000760000002800000018000000180000000100 62 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 63 | 10001EB6340041CE67001C9830002FC54F0059E3890017AC270034B24C00FC02 64 | FC00178F24004FD977002CB2470024AA3A0038BE580024A23400999999999999 65 | 9999999999999999999999999999999999999999999999999999999999999999 66 | 9999999999999999999999999999099999999999999999999990F09999999999 67 | 99999999990D7C09999999999999999990D277D099999999999999990452277D 68 | 09999999999999904355D0C7D09999999999990ABB3C09027D09999999999906 69 | 6BE09990A7D09999999999086E099999907D0999999999903099999999077099 70 | 9999999909999999999017099999999999999999999990A09999999999999999 71 | 9999990109999999999999999999999900999999999999999999999999099999 72 | 9999999999999999999999999999999999999999999999999999999999999999 73 | 9999999999999999999999999999999999999999999999999999} 74 | end 75 | object BtnAll: TBitBtn 76 | Left = 56 77 | Top = 456 78 | Width = 161 79 | Height = 33 80 | Caption = 'Commit all (F4)' 81 | ModalResult = 8 82 | TabOrder = 5 83 | OnClick = BtnAllClick 84 | Glyph.Data = { 85 | 96010000424D9601000000000000760000002800000018000000180000000100 86 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 87 | 1000D67F7F0024B43C0048D36F00FC02FC001F9B3100B53F3D00CC676800DD99 88 | 99002FC54F0059E3890037BA5400178F24001CAC2F00C4545400555555555555 89 | 5555555555555555555555555555555555555555555550555555555555555555 90 | 5555060555555555555555555550EE305555555555555555550E3EE305555555 91 | 55555555506A33EE3055555555555555064AAE03E305555555555550D4443050 92 | EE30555555555550BBBC07550DEE055555555550CBC08875550EE05555555557 93 | 040888875550EE055555557820287888755501E0555557F9922757888755550D 94 | 055557999275557F887555501055572927555555788755555005557975555555 95 | 578875555550555755555555557F8755555555555555555555557F7555555555 96 | 5555555555555777555555555555555555555557755555555555555555555555 97 | 5755555555555555555555555555555555555555555555555555} 98 | end 99 | object BtnCancel: TBitBtn 100 | Left = 240 101 | Top = 456 102 | Width = 129 103 | Height = 33 104 | Cancel = True 105 | Caption = 'Cancel' 106 | ModalResult = 2 107 | TabOrder = 6 108 | Glyph.Data = { 109 | 96010000424D9601000000000000760000002800000018000000180000000100 110 | 04000000000020010000130B0000130B0000100000000000000004029C00FC02 111 | FC001343FA003461F900204FFB000424EA001C42ED000733F7002C4FE4004172 112 | FC00143AEC00052CF7001E48F7002D59F7003967FA002457FC00111111111111 113 | 1111111111111111111111111111111111111111111111111111111111111111 114 | 1001111111111001111111110270111111110BB011111110C22B01111110577B 115 | 011111102C227011110B7B7501111111064C270110B77750111111111064CCA0 116 | 0BBB75011111111111064CCA77B750111111111111106422A77B011111111111 117 | 11110C2222701111111111111111044C22A01111111111111110DF44444A0111 118 | 11111111110D3DDCCF44601111111111103E3E400CF44601111111110E9EE801 119 | 106F446011111110999980111106D44C011111109998011111106DFC01111111 120 | 09D0111111110C40111111111001111111111001111111111111111111111111 121 | 1111111111111111111111111111111111111111111111111111} 122 | end 123 | object Description: TLabeledEdit 124 | Left = 48 125 | Top = 32 126 | Width = 329 127 | Height = 21 128 | AutoSize = False 129 | EditLabel.Width = 57 130 | EditLabel.Height = 13 131 | EditLabel.Caption = 'Description:' 132 | TabOrder = 0 133 | end 134 | object Comments: TMemo 135 | Left = 48 136 | Top = 128 137 | Width = 329 138 | Height = 121 139 | ScrollBars = ssVertical 140 | TabOrder = 2 141 | end 142 | object SCR: TComboBox 143 | Left = 48 144 | Top = 80 145 | Width = 329 146 | Height = 21 147 | Style = csDropDownList 148 | DropDownCount = 16 149 | ItemHeight = 13 150 | TabOrder = 1 151 | end 152 | object PVCS: TCheckBox 153 | Left = 240 154 | Top = 62 155 | Width = 145 156 | Height = 17 157 | Caption = 'Add to PVCS as modules' 158 | TabOrder = 7 159 | end 160 | end 161 | -------------------------------------------------------------------------------- /ProjectVersionMain.dfm: -------------------------------------------------------------------------------- 1 | object MainForm: TMainForm 2 | Left = 244 3 | Top = 158 4 | Width = 694 5 | Height = 376 6 | Color = clBtnFace 7 | Font.Charset = DEFAULT_CHARSET 8 | Font.Color = clWindowText 9 | Font.Height = -11 10 | Font.Name = 'Tahoma' 11 | Font.Style = [] 12 | KeyPreview = True 13 | OldCreateOrder = False 14 | OnClose = FormClose 15 | OnCreate = FormCreate 16 | OnDestroy = FormDestroy 17 | OnKeyDown = FormKeyDown 18 | OnResize = FormResize 19 | OnShow = FormShow 20 | PixelsPerInch = 96 21 | TextHeight = 13 22 | object SplitterPanel: TSplitter 23 | Left = 305 24 | Top = 42 25 | Height = 296 26 | end 27 | object ToolBar: TToolBar 28 | Left = 0 29 | Top = 0 30 | Width = 678 31 | Height = 42 32 | AutoSize = True 33 | ButtonHeight = 36 34 | ButtonWidth = 46 35 | EdgeBorders = [ebLeft, ebTop, ebRight, ebBottom] 36 | Images = ImageList 37 | ShowCaptions = True 38 | TabOrder = 0 39 | object BtnReleaseOpen: TToolButton 40 | Left = 0 41 | Top = 2 42 | Hint = 'Open another Release .dvs file' 43 | Caption = 'Open' 44 | DropdownMenu = PopupMenuOpen 45 | ImageIndex = 7 46 | ParentShowHint = False 47 | ShowHint = True 48 | OnClick = BtnReleaseOpenClick 49 | end 50 | object BtnReleaseNew: TToolButton 51 | Left = 46 52 | Top = 2 53 | Hint = 'Create a new Release (.dvs and associated directories and files)' 54 | Caption = 'New' 55 | ImageIndex = 8 56 | ParentShowHint = False 57 | ShowHint = True 58 | OnClick = BtnReleaseNewClick 59 | end 60 | object BtnReleaseSettings: TToolButton 61 | Left = 92 62 | Top = 2 63 | Hint = 'Release Settings (F9)' 64 | Caption = 'Settings' 65 | ImageIndex = 0 66 | ParentShowHint = False 67 | ShowHint = True 68 | OnClick = BtnReleaseSettingsClick 69 | end 70 | object ToolButton1: TToolButton 71 | Left = 138 72 | Top = 2 73 | Width = 8 74 | ImageIndex = 2 75 | Style = tbsSeparator 76 | end 77 | object BtnSCR: TToolButton 78 | Left = 146 79 | Top = 2 80 | Hint = 'SCR Editor (F1)' 81 | Caption = 'SCR' 82 | ImageIndex = 2 83 | ParentShowHint = False 84 | ShowHint = True 85 | OnClick = BtnSCRClick 86 | end 87 | object BtnSCRAdd: TToolButton 88 | Left = 192 89 | Top = 2 90 | Hint = 'Add a new Tracker entry to the SCR file' 91 | Caption = 'Entry' 92 | ImageIndex = 6 93 | ParentShowHint = False 94 | ShowHint = True 95 | OnClick = BtnSCRAddClick 96 | end 97 | object ToolButton5: TToolButton 98 | Left = 238 99 | Top = 2 100 | Width = 8 101 | ImageIndex = 1 102 | Style = tbsSeparator 103 | end 104 | object BtnManual: TToolButton 105 | Left = 246 106 | Top = 2 107 | Hint = 'Software Manual Editor' 108 | Caption = 'Manual' 109 | ImageIndex = 10 110 | ParentShowHint = False 111 | ShowHint = True 112 | OnClick = BtnManualClick 113 | end 114 | object ToolButton3: TToolButton 115 | Left = 292 116 | Top = 2 117 | Width = 8 118 | ImageIndex = 5 119 | Style = tbsSeparator 120 | end 121 | object BtnPRO: TToolButton 122 | Left = 300 123 | Top = 2 124 | Hint = 'Release Documentation Editor (F2)' 125 | Caption = 'Docs' 126 | ImageIndex = 3 127 | ParentShowHint = False 128 | ShowHint = True 129 | OnClick = BtnPROClick 130 | end 131 | object BtnPROWizard: TToolButton 132 | Left = 346 133 | Top = 2 134 | Hint = 'Release Documentation Wizard' 135 | Caption = 'Wizard' 136 | ImageIndex = 5 137 | ParentShowHint = False 138 | ShowHint = True 139 | OnClick = BtnPROWizardClick 140 | end 141 | object ToolButton2: TToolButton 142 | Left = 392 143 | Top = 2 144 | Width = 8 145 | ImageIndex = 2 146 | Style = tbsSeparator 147 | end 148 | object BtnCommit: TToolButton 149 | Left = 400 150 | Top = 2 151 | Hint = 'Commit source modifications (F3)' 152 | Caption = 'Commit' 153 | ImageIndex = 4 154 | ParentShowHint = False 155 | ShowHint = True 156 | OnClick = BtnCommitClick 157 | end 158 | object BtnBackup: TToolButton 159 | Left = 446 160 | Top = 2 161 | Hint = 'Incremental Backup (F4)' 162 | Caption = 'Backup' 163 | ImageIndex = 1 164 | ParentShowHint = False 165 | ShowHint = True 166 | OnClick = BtnBackupClick 167 | end 168 | object BtnBackupOpen: TToolButton 169 | Left = 492 170 | Top = 2 171 | Hint = 'View a backup content' 172 | Caption = 'GetBack' 173 | DropdownMenu = PopupMenuBackup 174 | ImageIndex = 11 175 | ParentShowHint = False 176 | ShowHint = True 177 | OnClick = BtnBackupOpenClick 178 | end 179 | object ToolButton4: TToolButton 180 | Left = 538 181 | Top = 2 182 | Width = 8 183 | Caption = 'ToolButton4' 184 | ImageIndex = 12 185 | Style = tbsSeparator 186 | end 187 | object BtnAbout: TToolButton 188 | Left = 546 189 | Top = 2 190 | Caption = 'About' 191 | ImageIndex = 9 192 | OnClick = BtnAboutClick 193 | end 194 | end 195 | object PanelLeft: TPanel 196 | Left = 0 197 | Top = 42 198 | Width = 305 199 | Height = 296 200 | Align = alLeft 201 | TabOrder = 1 202 | end 203 | object PanelRight: TPanel 204 | Left = 308 205 | Top = 42 206 | Width = 370 207 | Height = 296 208 | Align = alClient 209 | TabOrder = 2 210 | end 211 | object ImageList: TImageList 212 | Left = 32 213 | Top = 181 214 | end 215 | object PopupMenuBackup: TPopupMenu 216 | Left = 500 217 | Top = 50 218 | end 219 | object PopupMenuOpen: TPopupMenu 220 | Left = 8 221 | Top = 50 222 | end 223 | end 224 | -------------------------------------------------------------------------------- /ProjectVersionPages.dfm: -------------------------------------------------------------------------------- 1 | object FramePages: TFramePages 2 | Left = 0 3 | Top = 0 4 | Width = 567 5 | Height = 315 6 | Font.Charset = DEFAULT_CHARSET 7 | Font.Color = clWindowText 8 | Font.Height = -11 9 | Font.Name = 'Tahoma' 10 | Font.Style = [] 11 | ParentFont = False 12 | TabOrder = 0 13 | object Pages: TPageControl 14 | Left = 0 15 | Top = 0 16 | Width = 567 17 | Height = 315 18 | ActivePage = PageFile 19 | Align = alClient 20 | TabOrder = 0 21 | OnChange = PagesChange 22 | object PageCommit: TTabSheet 23 | Caption = 'By Commit' 24 | object Splitter1: TSplitter 25 | Left = 201 26 | Top = 0 27 | Height = 287 28 | end 29 | object ListCommit: TListView 30 | Left = 0 31 | Top = 0 32 | Width = 201 33 | Height = 287 34 | Align = alLeft 35 | Columns = <> 36 | Items.Data = {1D0000000100000000000000FFFFFFFFFFFFFFFF000000000000000000} 37 | TabOrder = 0 38 | end 39 | object CommitRight: TPanel 40 | Left = 204 41 | Top = 0 42 | Width = 355 43 | Height = 287 44 | Align = alClient 45 | TabOrder = 1 46 | object ListCommitFiles: TListView 47 | Left = 1 48 | Top = 25 49 | Width = 353 50 | Height = 261 51 | Align = alClient 52 | Columns = <> 53 | TabOrder = 0 54 | OnMouseDown = ListCommitFilesMouseDown 55 | end 56 | object CommitRightTop: TPanel 57 | Left = 1 58 | Top = 1 59 | Width = 353 60 | Height = 24 61 | Align = alTop 62 | TabOrder = 1 63 | DesignSize = ( 64 | 353 65 | 24) 66 | object LabelCommitRightTop: TLabel 67 | Left = 110 68 | Top = 6 69 | Width = 239 70 | Height = 13 71 | Anchors = [akLeft, akTop, akRight] 72 | AutoSize = False 73 | Font.Charset = DEFAULT_CHARSET 74 | Font.Color = clWindowText 75 | Font.Height = -11 76 | Font.Name = 'Tahoma' 77 | Font.Style = [fsItalic] 78 | ParentFont = False 79 | end 80 | object BtnComitRightTop: TSpeedButton 81 | Left = 5 82 | Top = 4 83 | Width = 16 84 | Height = 16 85 | Hint = 'Show / Hide Commit column' 86 | Glyph.Data = { 87 | 36030000424D3603000000000000360000002800000010000000100000000100 88 | 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF 89 | FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 90 | FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF 91 | 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF 92 | FF00FFFF00FFFF00FF006600006600FF00FFFF00FFFF00FFFF00FFFF00FFFF00 93 | FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0066001EB2311FB13300 94 | 6600FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF 95 | FF00FF00660031C24F22B7381AB02D21B437006600FF00FFFF00FFFF00FFFF00 96 | FFFF00FFFF00FFFF00FFFF00FFFF00FF00660047D36D3BCB5E25A83B0066001B 97 | A92E1DB132006600FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF006600 98 | 4FD67953DE7F31B54D006600FF00FF006600179D271EAE31006600FF00FFFF00 99 | FFFF00FFFF00FFFF00FFFF00FFFF00FF00660041C563006600FF00FFFF00FFFF 100 | 00FFFF00FF00660019AA2B006600FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF 101 | FF00FF006600FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF006600149D210066 102 | 00FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF 103 | 00FFFF00FFFF00FFFF00FFFF00FF006600006600FF00FFFF00FFFF00FFFF00FF 104 | FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 105 | FF006600006600FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF 106 | 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF 107 | FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 108 | FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF 109 | 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF 110 | FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 111 | FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF 112 | 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} 113 | Layout = blGlyphBottom 114 | ParentShowHint = False 115 | ShowHint = True 116 | Spacing = 0 117 | OnClick = BtnComitRightTopClick 118 | end 119 | object CheckBoxOnlyModified: TCheckBox 120 | Left = 24 121 | Top = 5 122 | Width = 89 123 | Height = 17 124 | Caption = 'only modified' 125 | Checked = True 126 | State = cbChecked 127 | TabOrder = 0 128 | OnClick = CheckBoxOnlyModifiedClick 129 | end 130 | end 131 | end 132 | end 133 | object PageFile: TTabSheet 134 | Caption = 'By File' 135 | ImageIndex = 1 136 | object Splitter2: TSplitter 137 | Left = 329 138 | Top = 0 139 | Height = 287 140 | end 141 | object ListFiles: TListView 142 | Left = 0 143 | Top = 0 144 | Width = 329 145 | Height = 287 146 | Align = alLeft 147 | Columns = <> 148 | TabOrder = 0 149 | end 150 | object ListFilesCommit: TListView 151 | Left = 332 152 | Top = 0 153 | Width = 227 154 | Height = 287 155 | Align = alClient 156 | Columns = <> 157 | MultiSelect = True 158 | TabOrder = 1 159 | OnSelectItem = ListFilesCommitSelectItem 160 | end 161 | end 162 | end 163 | end 164 | -------------------------------------------------------------------------------- /ProjectVersionCompare.pas: -------------------------------------------------------------------------------- 1 | /// File Versioning comparison form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectVersionCompare; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 30 | Menus, ComCtrls, ExtCtrls, SynMemoEx, ProjectCommons, 31 | ProjectVersioning, 32 | ProjectEditor, ProjectFrameViewer, ProjectFormViewTwo; 33 | 34 | type 35 | TProjectVersionCompareForm = class(TForm) 36 | PanelLeft: TPanel; 37 | PanelRight: TPanel; 38 | ListFilesCommit: TListView; 39 | procedure FormResize(Sender: TObject); 40 | procedure FormShow(Sender: TObject); 41 | procedure ListFilesCommitSelectItem(Sender: TObject; Item: TListItem; 42 | Selected: Boolean); 43 | private 44 | procedure SynchronizeOnScroll(Sender: TObject); 45 | public 46 | Backup, 47 | Versions: TVersions; 48 | Editor: TFrameEditor; 49 | EditorText: string; 50 | Title, 51 | FileName: string; 52 | FileNameIndex: integer; // in Backup.FileNames[] 53 | View1, 54 | View2: TFrameViewer; 55 | procedure OnEditorBtnHistoryClick(Sender: TObject); 56 | procedure Init(aVersions: TVersions; aEditor: TFrameEditor; const aFileName: string); 57 | procedure CompareUsing(const aTitle: string; Back: TVersions); 58 | end; 59 | 60 | var 61 | ProjectVersionCompareForm: TProjectVersionCompareForm; 62 | 63 | implementation 64 | 65 | uses 66 | ProjectVersionMain; 67 | 68 | {$R *.dfm} 69 | 70 | { TProjectVersionCompareForm } 71 | 72 | procedure TProjectVersionCompareForm.CompareUsing(const aTitle: string; Back: TVersions); 73 | var i: integer; 74 | begin 75 | Backup := Back; 76 | FileNameIndex := Back.FileNames.FindIndex(FileName); 77 | if FileNameIndex<0 then exit; 78 | Title := StringReplaceAll(aTitle,'&',''); 79 | Caption := ' '+Title; 80 | WindowState := wsMaximized; 81 | View1.Free; 82 | View1 := TFrameViewer.Create(self,Back,nil,false); 83 | View1.FileName := FileName; 84 | View1.Parent := PanelLeft; 85 | View1.Align := alClient; 86 | View1.Name := 'View1'; 87 | View1.Diff := true; 88 | View1.MemoEx.OnScroll := SynchronizeOnScroll; 89 | // right = current Editor content 90 | View2.Free; 91 | View2 := TFrameViewer.Create(self,Back,nil,false); 92 | View2.FileName := FileName; 93 | View2.Parent := PanelRight; 94 | View2.Align := alClient; 95 | View2.Name := 'View2'; 96 | View2.Diff := true; 97 | View2.MemoEx.OnScroll := SynchronizeOnScroll; 98 | MainForm.PagesLeft.CommitInit(ListFilesCommit); 99 | for i := Back.Count-1 downto 0 do 100 | with Back.Values[i] do 101 | if FileName=FileNameIndex then 102 | MainForm.PagesLeft.CommitAdd(Back,Commit,true,ListFilesCommit); 103 | MainForm.PagesLeft.CommitEnd(ListFilesCommit); 104 | ListFilesCommit.OnResize := nil; // FormResize; 105 | ShowModal; 106 | end; 107 | 108 | procedure TProjectVersionCompareForm.OnEditorBtnHistoryClick(Sender: TObject); 109 | // just a TMenuItem with Tag = BakcupDir # 110 | var Menu: TMenuItem absolute Sender; 111 | b, path, FN: string; 112 | Back: TVersions; 113 | begin 114 | if not Sender.InheritsFrom(TMenuItem) then exit; 115 | if Menu.Tag=-1 then // Tag=-1 -> commits = Version 116 | Back := Versions else begin 117 | b := Versions.Params['BackupDir'+IntToStr(Menu.Tag)]; 118 | // BackupDir0=Local backup,012345,D:\-=- Backup -=-\Synopse\ 119 | FN := Versions.GetBackupFileName(b,path); 120 | if not FileExists(FN) then exit; 121 | Back := TVersions.Create(FN); 122 | end; 123 | try 124 | EditorText := Editor.Memo.Lines.Text; 125 | CompareUsing('Compare with '+Menu.Caption, Back); 126 | finally 127 | if Back<>Versions then 128 | Back.Free; 129 | end; 130 | end; 131 | 132 | procedure TProjectVersionCompareForm.FormResize(Sender: TObject); 133 | var W: integer; 134 | begin 135 | W := (ClientWidth-ListFilesCommit.Width)div 2; 136 | PanelLeft.Width := W; 137 | PanelRight.Width := W; 138 | end; 139 | 140 | procedure TProjectVersionCompareForm.SynchronizeOnScroll(Sender: TObject); 141 | var M: TMemoEx absolute Sender; 142 | begin 143 | if not (Sender.InheritsFrom(TMemoEx)) then exit; 144 | if M=View1.MemoEx then 145 | View2.MemoEx.SetLeftTop(0,M.TopRow) else 146 | if M=View2.MemoEx then 147 | View1.MemoEx.SetLeftTop(0,M.TopRow); 148 | end; 149 | 150 | procedure TProjectVersionCompareForm.Init(aVersions: TVersions; 151 | aEditor: TFrameEditor; const aFileName: string); 152 | begin 153 | Versions := aVersions; 154 | Editor := aEditor; 155 | FileName := aFileName; 156 | end; 157 | 158 | procedure TProjectVersionCompareForm.FormShow(Sender: TObject); 159 | begin 160 | if ListFilesCommit.Items.Count>0 then 161 | ListFilesCommit.ItemIndex := 0; 162 | View2.MemoEx.SetFocus; // must be after having been shown 163 | end; 164 | 165 | procedure TProjectVersionCompareForm.ListFilesCommitSelectItem( 166 | Sender: TObject; Item: TListItem; Selected: Boolean); 167 | var List: TListView absolute Sender; 168 | Diff: TDiffCalc; 169 | begin 170 | if csDestroying in ComponentState then exit; 171 | if not Sender.InheritsFrom(TListView) or not Assigned(Backup) then exit; 172 | if List.SelCount>1 then begin // maximum 1 selected item 173 | Item.Selected := false; 174 | exit; 175 | end; 176 | Diff.Execute(Backup.GetVersionData(FileNameIndex,integer(Item.Data)), EditorText, 177 | View1.MemoEx, View2.MemoEx, false); 178 | Caption := format(' %s - %s : %d add, %d mod, %d del',[ 179 | Title,FileName,Diff.linesAdd,Diff.linesMod,Diff.linesDel]); 180 | View2.GotoNextModif; 181 | end; 182 | 183 | end. 184 | -------------------------------------------------------------------------------- /ProjectTrackerLogin.dfm: -------------------------------------------------------------------------------- 1 | object ProjectTrackerLoginForm: TProjectTrackerLoginForm 2 | Left = 470 3 | Top = 204 4 | BorderStyle = bsDialog 5 | Caption = ' PVCS Tracker' 6 | ClientHeight = 345 7 | ClientWidth = 429 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -11 12 | Font.Name = 'Tahoma' 13 | Font.Style = [] 14 | OldCreateOrder = False 15 | Position = poScreenCenter 16 | OnDestroy = FormDestroy 17 | OnShow = FormShow 18 | PixelsPerInch = 96 19 | TextHeight = 13 20 | object BtnOk: TBitBtn 21 | Left = 136 22 | Top = 296 23 | Width = 105 24 | Height = 33 25 | Hint = 'OK,Connect' 26 | Caption = 'Connect' 27 | Default = True 28 | ModalResult = 1 29 | TabOrder = 0 30 | OnClick = BtnOkClick 31 | Glyph.Data = { 32 | F6000000424DF600000000000000760000002800000010000000100000000100 33 | 0400000000008000000000000000000000001000000000000000040204000482 34 | 0400848204008402040004FE0400FCFEFC00FC02040004FEFC00000040000000 35 | 00000000000000000000DFFBC100DA67AB00410080007E007C00000555500000 36 | 0000002222500000000000222253633300000022225136363600002222541413 37 | 3330002222514141363603222257143413630622225147414413552222555474 38 | 7143222222225747471422222222577474732222222266774743006666676664 39 | 7460006466777666436000067464666366000000024744660000} 40 | end 41 | object BtnCancel: TBitBtn 42 | Left = 288 43 | Top = 296 44 | Width = 105 45 | Height = 33 46 | Cancel = True 47 | Caption = 'Cancel' 48 | ModalResult = 2 49 | TabOrder = 1 50 | Glyph.Data = { 51 | 96010000424D9601000000000000760000002800000018000000180000000100 52 | 04000000000020010000130B0000130B0000100000000000000004029C00FC02 53 | FC001343FA003461F900204FFB000424EA001C42ED000733F7002C4FE4004172 54 | FC00143AEC00052CF7001E48F7002D59F7003967FA002457FC00111111111111 55 | 1111111111111111111111111111111111111111111111111111111111111111 56 | 1001111111111001111111110270111111110BB011111110C22B01111110577B 57 | 011111102C227011110B7B7501111111064C270110B77750111111111064CCA0 58 | 0BBB75011111111111064CCA77B750111111111111106422A77B011111111111 59 | 11110C2222701111111111111111044C22A01111111111111110DF44444A0111 60 | 11111111110D3DDCCF44601111111111103E3E400CF44601111111110E9EE801 61 | 106F446011111110999980111106D44C011111109998011111106DFC01111111 62 | 09D0111111110C40111111111001111111111001111111111111111111111111 63 | 1111111111111111111111111111111111111111111111111111} 64 | end 65 | object Pages: TPageControl 66 | Left = 0 67 | Top = 0 68 | Width = 431 69 | Height = 281 70 | ActivePage = TabSCRMulti 71 | TabOrder = 2 72 | object TabUser: TTabSheet 73 | TabVisible = False 74 | object Label3: TLabel 75 | Left = 40 76 | Top = 32 77 | Width = 4 78 | Height = 14 79 | Font.Charset = DEFAULT_CHARSET 80 | Font.Color = clNavy 81 | Font.Height = -12 82 | Font.Name = 'Tahoma' 83 | Font.Style = [fsBold] 84 | ParentFont = False 85 | end 86 | object UserName: TLabeledEdit 87 | Left = 40 88 | Top = 80 89 | Width = 353 90 | Height = 21 91 | EditLabel.Width = 175 92 | EditLabel.Height = 13 93 | EditLabel.Caption = 'User Name (leave blank for default):' 94 | TabOrder = 0 95 | end 96 | object PassWord: TLabeledEdit 97 | Left = 40 98 | Top = 128 99 | Width = 353 100 | Height = 21 101 | EditLabel.Width = 169 102 | EditLabel.Height = 13 103 | EditLabel.Caption = 'Password (leave blank for default):' 104 | TabOrder = 1 105 | end 106 | end 107 | object TabProject: TTabSheet 108 | ImageIndex = 1 109 | TabVisible = False 110 | object Label1: TLabel 111 | Left = 40 112 | Top = 32 113 | Width = 70 114 | Height = 13 115 | Caption = 'Select Project:' 116 | end 117 | object Project: TListBox 118 | Left = 40 119 | Top = 48 120 | Width = 345 121 | Height = 185 122 | ItemHeight = 13 123 | TabOrder = 0 124 | end 125 | end 126 | object TabSCR: TTabSheet 127 | ImageIndex = 2 128 | TabVisible = False 129 | object Label2: TLabel 130 | Left = 40 131 | Top = 16 132 | Width = 113 133 | Height = 13 134 | Caption = 'Choose one SCR entry:' 135 | end 136 | object SCRList: TListBox 137 | Left = 40 138 | Top = 32 139 | Width = 345 140 | Height = 225 141 | Style = lbOwnerDrawFixed 142 | ItemHeight = 13 143 | TabOrder = 0 144 | OnClick = SCRListClick 145 | OnDrawItem = SCRListDrawItem 146 | end 147 | end 148 | object TabSCRMulti: TTabSheet 149 | ImageIndex = 3 150 | TabVisible = False 151 | object Label4: TLabel 152 | Left = 40 153 | Top = 16 154 | Width = 3 155 | Height = 13 156 | end 157 | object SCRListMulti: TCheckListBox 158 | Left = 40 159 | Top = 32 160 | Width = 345 161 | Height = 225 162 | OnClickCheck = SCRListMultiClickCheck 163 | ItemHeight = 16 164 | Style = lbOwnerDrawFixed 165 | TabOrder = 0 166 | OnDrawItem = SCRListDrawItem 167 | end 168 | object BtnSelAll: TButton 169 | Left = 4 170 | Top = 168 171 | Width = 33 172 | Height = 25 173 | Hint = 'Select all entries' 174 | Caption = 'All' 175 | ParentShowHint = False 176 | ShowHint = True 177 | TabOrder = 1 178 | OnClick = BtnSelAllClick 179 | end 180 | object BtnSelNone: TButton 181 | Left = 4 182 | Top = 200 183 | Width = 33 184 | Height = 25 185 | Hint = 'Select no entry' 186 | Caption = 'None' 187 | ParentShowHint = False 188 | ShowHint = True 189 | TabOrder = 2 190 | OnClick = BtnSelAllClick 191 | end 192 | object BtnSelOpen: TButton 193 | Left = 4 194 | Top = 232 195 | Width = 33 196 | Height = 25 197 | Hint = 'Select all opened entries' 198 | Caption = 'Open' 199 | ParentShowHint = False 200 | ShowHint = True 201 | TabOrder = 3 202 | OnClick = BtnSelAllClick 203 | end 204 | end 205 | end 206 | end 207 | -------------------------------------------------------------------------------- /ProjectFormViewOne.pas: -------------------------------------------------------------------------------- 1 | /// File Versioning one file content view form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectFormViewOne; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 30 | ProjectVersioning, ProjectFrameViewer, Menus, ExtCtrls; 31 | 32 | type 33 | TFormViewOne = class(TForm) 34 | PopupMenu: TPopupMenu; 35 | Image: TImage; 36 | private 37 | { Private declarations } 38 | Current: PVersion; 39 | Versions: TVersions; 40 | Commit1, Commit2: integer; 41 | function NewMenu(const Name: string; Value: integer; Menu: TMenuItem): TMenuItem; 42 | procedure ViewCreate(aVersions: TVersions; aVersion: PVersion; fillMemo: boolean); 43 | public 44 | { Public declarations } 45 | View: TFrameViewer; 46 | procedure Load(aVersions: TVersions; aVersion: PVersion; aCommit2: integer=-1); 47 | procedure CompareMenu(Sender: TObject); 48 | end; 49 | 50 | var 51 | FormViewOne: TFormViewOne; 52 | 53 | implementation 54 | 55 | {$R *.dfm} 56 | 57 | uses 58 | ProjectCommons, 59 | ProjectRTF, 60 | ProjectDiff, 61 | ProjectFormViewTwo; 62 | 63 | { TFormViewOne } 64 | 65 | procedure TFormViewOne.CompareMenu(Sender: TObject); 66 | var Menu: TMenuItem absolute Sender; 67 | isDiff: boolean; 68 | FileName, Commit: integer; 69 | Diff: TDiffCalc; 70 | begin 71 | if not Sender.InheritsFrom(TMenuItem) or (View=nil) then exit; 72 | isDiff := (Menu.Tag and (1 shl 16))<>0; 73 | Commit := Menu.Tag; 74 | if isDiff then 75 | Commit := Commit and pred(1 shl 16); 76 | dec(Commit); 77 | FileName := Current^.FileName; 78 | if Commit=-1 then 79 | Commit := Versions.PreviousCommit(FileName,Current^.Commit); 80 | if isDiff then begin 81 | if View=nil then begin 82 | ViewCreate(Versions, Current, false); // fillMemo=false 83 | Show; 84 | end; 85 | View.Diff := true; 86 | Diff.Execute(Versions.GetVersionData(FileName,Commit), 87 | Versions.GetVersionData(FileName,Current^.Commit), 88 | nil, View.MemoEx, true); 89 | Caption := format('%s diff vs #%d: %d add, %d mod, %d del',[ 90 | Caption,Commit,Diff.linesAdd,Diff.linesMod,Diff.linesDel]); 91 | end else begin 92 | Hide; 93 | FormViewTwo.Load(Versions,Versions.GetVersion(FileName,Commit),Current,false); 94 | end; 95 | end; 96 | 97 | procedure TFormViewOne.ViewCreate(aVersions: TVersions; aVersion: PVersion; fillMemo: boolean); 98 | var firstVisible: boolean; 99 | Ext, FN, tmp: string; 100 | M, W, H: integer; 101 | begin 102 | firstVisible := View=nil; 103 | FreeAndNil(View); 104 | FN := aVersions.FileNames.Value[aVersion^.FileName]; 105 | Ext := ExtractFileExt(FN); 106 | if (GetStringIndex(VALID_PICTURES_EXT, Ext)>=0) 107 | or SameText(Ext,'.BMP') or SameText(Ext,'.ICO') then begin 108 | // 1. display picture file 109 | SetLength(tmp,255); 110 | SetLength(tmp,GetTempPath(255,pointer(tmp))); 111 | tmp := tmp+ExtractFileName(FN); // use a temporary file to load pic contents 112 | if FileExists(tmp) and not DeleteFile(tmp) then exit; 113 | try 114 | StringToFile(tmp,aVersions.GetVersionData(aVersion^.FileName,aVersion^.Commit)); 115 | Image.Picture.LoadFromFile(tmp); 116 | finally // on any load error -> exception -> delete tmp and display nothing 117 | DeleteFile(tmp); 118 | end; 119 | W := Image.Picture.Width; 120 | H := Image.Picture.Height; 121 | M := Monitor.Width div 2; 122 | if W>M then begin 123 | Image.Stretch := true; 124 | ClientWidth := M; 125 | ClientHeight := (M*H)div W; 126 | end else begin 127 | Image.Stretch := false; 128 | ClientWidth := W; 129 | ClientHeight := H; 130 | end; 131 | Image.Visible := true; 132 | Left := Monitor.Width-Width; 133 | Top := Monitor.WorkareaRect.Bottom-Height; 134 | end else begin 135 | // 2. display text content (using a TFrameViewer.MemoEx) 136 | Image.Visible := false; 137 | View := TFrameViewer.Create(self,aVersions,aVersion,true); 138 | View.Parent := self; 139 | View.Align := alClient; 140 | if firstVisible then 141 | ClientWidth := View.MemoEx.CellRect.Width*84+View.MemoEx.GutterWidth; 142 | if firstVisible then begin 143 | Top := 200; 144 | Left := Monitor.Width-Width; 145 | Height := Monitor.WorkareaRect.Bottom-Top; 146 | end; 147 | end; 148 | end; 149 | 150 | procedure TFormViewOne.Load(aVersions: TVersions; aVersion: PVersion; aCommit2: integer); 151 | procedure CompareWith(Commit: integer); 152 | begin 153 | NewMenu(format('Compare with %s',[aVersions.CommitToString(Commit)]), 154 | Commit+1,PopupMenu.Items).OnClick := CompareMenu; 155 | end; 156 | procedure DiffFrom(Commit: integer); 157 | begin 158 | NewMenu(format('Diff from %s',[aVersions.CommitToString(Commit)]), 159 | (Commit+1)or(1 shl 16),PopupMenu.Items).OnClick := CompareMenu; 160 | end; 161 | var Menu: TMenuItem; 162 | i: integer; 163 | FN, C: integer; 164 | begin 165 | if visible then begin // update only if visible 166 | ViewCreate(aVersions, aVersion, true); // fillMemo=true 167 | if View<>nil then 168 | View.MemoEx.PopupMenu := PopupMenu; 169 | end; 170 | FN := aVersion^.FileName; 171 | C := aVersion^.Commit; 172 | Caption := format('%s - #%d',[aVersions.FileNames.Value[FN],C]); 173 | Current := aVersion; // update PopupMenu (used also for caller) 174 | Versions := aVersions; 175 | Commit1 := aVersion^.Commit; 176 | Commit2 := Commit1; 177 | PopupMenu.Items.Clear; 178 | if View=nil then exit; 179 | if (aCommit2>=0) and (aCommit2<=aVersions.LastCommit) and (Commit1<>aCommit2) then begin 180 | Commit2 := aCommit2; 181 | CompareWith(-1); 182 | CompareWith(Commit2); 183 | DiffFrom(-1); 184 | DiffFrom(Commit2); 185 | end else begin 186 | CompareWith(-1); 187 | DiffFrom(-1); 188 | end; 189 | Menu := NewMenu(format('Compare #%d with',[C]),0,PopupMenu.Items); 190 | with Versions do 191 | for i := Count-1 downto 0 do 192 | with Values[i] do 193 | if FileName=FN then 194 | if Commit=C then 195 | NewMenu('-',0,Menu) else 196 | NewMenu(CommitToString(Commit),Commit+1,Menu).OnClick := CompareMenu; 197 | if Menu.Count=1 then 198 | PopupMenu.Items.Clear; // no other version -> no popupmenu 199 | end; 200 | 201 | function TFormViewOne.NewMenu(const Name: string; Value: integer; Menu: TMenuItem): TMenuItem; 202 | begin 203 | result := TMenuItem.Create(Owner); 204 | result.Caption := Name; 205 | result.Tag := Value; 206 | Menu.Add(result); 207 | end; 208 | 209 | 210 | end. 211 | -------------------------------------------------------------------------------- /ProjectFormDocWizard.dfm: -------------------------------------------------------------------------------- 1 | object ProjectDocWizard: TProjectDocWizard 2 | Left = 188 3 | Top = 142 4 | BorderStyle = bsDialog 5 | ClientHeight = 597 6 | ClientWidth = 778 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | Position = poScreenCenter 15 | OnDestroy = FormDestroy 16 | OnShow = FormShow 17 | PixelsPerInch = 96 18 | TextHeight = 13 19 | object BtnPrev: TBitBtn 20 | Left = 208 21 | Top = 552 22 | Width = 113 23 | Height = 38 24 | Caption = 'Previous' 25 | ParentShowHint = False 26 | ShowHint = True 27 | TabOrder = 1 28 | OnClick = BtnPrevClick 29 | Glyph.Data = { 30 | B6020000424DB602000000000000760000002800000030000000180000000100 31 | 04000000000040020000130B0000130B00001000000000000000055806000C84 32 | 1B00999B990010B525005CCF84008EDEAB0032BB5500CDCDCD0037C56600FC02 33 | FC007C7A7C00B0B0B000CAF0D60013A62800F8FAF800B3E9C400999999990000 34 | 00009999999999999999AAAAAAAA9999999999999900D333333D009999999999 35 | 99AA22222222AA999999999900D3333333333D0099999999AA222222222222AA 36 | 99999991133333333333333109999992222222222222222AA999991133333333 37 | 3333333310999922B222222222222222AA999913333333FEE83333333099992B 38 | B22222CEEB2222222A9991D633333FEEE53333333109922BBB222EEEE7222222 39 | 22A991866633FEEEC8333333330992BBBB22EEEEEB22222222A93D86663FEEEC 40 | 83333333331022BBBB2EEEEEBBB22222222A3688885EEE586633333333D02BBB 41 | BB7EEE7BBBBB2222222A388885EEEEECCCCCCCCF33302BBBB7EEEEEEEEEEEEEC 42 | 222A38488EEEEEEEEEEEEEEE33302BBBBEEEEEEEEEEEEEEE222A34488CEEEEEE 43 | EEEEEEEE3330277BBEEEEEEEEEEEEEEE222A345444CEEEF44444444833D0277B 44 | B7EEEEC77777777B222A3454444FEEEF8888666333D027C7BBBEEEEEBBBBBBBB 45 | 222A38554444FEEEE486333333102BCCBBBBEEEEE7BBBB2222AA935F58444FEE 46 | EF8663333309927E7BBBBEEEECBBBBB222A9934FC544445EE4866633310992BE 47 | E7BBBB7EE7BBBBBBB2A99934CC54444444466666D0999927EE7BBBBBBBBBBBBB 48 | 2A9999365CCF5488888886631099992B7EEE77BBBBBBBBB22A99999364FCCF55 49 | 4444486119999992B7EEEE7777777B22299999993385FCCFF5548D1199999999 50 | 22B7EEEEEC77B2229999999999336444446D1199999999999922B77777B22299 51 | 9999999999993333333399999999999999992222222299999999} 52 | NumGlyphs = 2 53 | end 54 | object BtnNext: TBitBtn 55 | Left = 336 56 | Top = 552 57 | Width = 113 58 | Height = 38 59 | Caption = 'Next' 60 | ParentShowHint = False 61 | ShowHint = True 62 | TabOrder = 2 63 | OnClick = BtnNextClick 64 | Glyph.Data = { 65 | B6020000424DB602000000000000760000002800000030000000180000000100 66 | 04000000000040020000130B0000130B00001000000000000000055806000C84 67 | 1B00999A990011B526005DD086008CDEAA0030BC5300CECECE0037C56500FC02 68 | FC007C7A7C00B1B1B100CCF0D80013A62800F8FAF800AFE7C000999999990000 69 | 00009999999999999999AAAAAAAA9999999999999900D333333D009999999999 70 | 99AA22222222AA999999999900D3333333333D0099999999AA222222222222AA 71 | 99999991133333333333333109999992222222222222222AA999991133333333 72 | 33333333109999222222222222222222AA99991633333338EEF3333330999922 73 | 2222222BEEC222222A9991D633333665EEEF33333109922B22222B27EEEC2222 74 | 22A9918666666668CEEEF333330992BBBBBBBBBBEEEEC22222A93D8666686666 75 | 8FEEEF33331022BBBBBBBBBBBEEEEC22222A368888888666685EEE4333D02BBB 76 | BBBBBBBBBB7EEE72222A38888FCCCCCCCCEEEEE433302BBBBEEEEEEEEEEEEEE7 77 | 222A38488EEEEEEEEEEEEEEE33302BBBBEEEEEEEEEEEEEEE222A34488EEEEEEE 78 | EEEEEEEC3330277BBEEEEEEEEEEEEEEE222A34544455444444FEEEC633D0277B 79 | B777777777CEEEEB222A3454444444888FEEEF6333D027C7BBBBBBBBBEEEEEB2 80 | 222A38F544444444EEEEF33333102BCCBBBBBBB7EEEEC222222A935C5844444F 81 | EEEF63333309927E7BBBBBBCEEEEB22222A9934FC5444445EE566633310992BE 82 | E7BBBBB7EE7BBB2222A99934CC54444444466666D0999927EE7BBBBBBBBBBB2B 83 | 2A9999365CCF5488888886631099992B7EEE77BBBBBBBBB22A99999364FCCF55 84 | 4444486119999992B7EEEE7777777B22299999993385FCCCF5548D1199999999 85 | 22B7EEEEEC77B2229999999999338444446D1199999999999922B77777B22299 86 | 9999999999993333333399999999999999992222222299999999} 87 | NumGlyphs = 2 88 | end 89 | object BtnCancel: TBitBtn 90 | Left = 640 91 | Top = 552 92 | Width = 113 93 | Height = 38 94 | Cancel = True 95 | Caption = 'Cancel' 96 | ModalResult = 2 97 | TabOrder = 3 98 | Glyph.Data = { 99 | 96010000424D9601000000000000760000002800000018000000180000000100 100 | 04000000000020010000130B0000130B0000100000000000000004029C00FC02 101 | FC001343FA003461F900204FFB000424EA001C42ED000733F7002C4FE4004172 102 | FC00143AEC00052CF7001E48F7002D59F7003967FA002457FC00111111111111 103 | 1111111111111111111111111111111111111111111111111111111111111111 104 | 1001111111111001111111110270111111110BB011111110C22B01111110577B 105 | 011111102C227011110B7B7501111111064C270110B77750111111111064CCA0 106 | 0BBB75011111111111064CCA77B750111111111111106422A77B011111111111 107 | 11110C2222701111111111111111044C22A01111111111111110DF44444A0111 108 | 11111111110D3DDCCF44601111111111103E3E400CF44601111111110E9EE801 109 | 106F446011111110999980111106D44C011111109998011111106DFC01111111 110 | 09D0111111110C40111111111001111111111001111111111111111111111111 111 | 1111111111111111111111111111111111111111111111111111} 112 | end 113 | object PanelTop: TPanel 114 | Left = 0 115 | Top = 0 116 | Width = 778 117 | Height = 33 118 | Align = alTop 119 | Alignment = taLeftJustify 120 | Font.Charset = DEFAULT_CHARSET 121 | Font.Color = clNavy 122 | Font.Height = -16 123 | Font.Name = 'Tahoma' 124 | Font.Style = [fsItalic] 125 | ParentFont = False 126 | TabOrder = 0 127 | end 128 | object Pages: TPanel 129 | Left = 0 130 | Top = 33 131 | Width = 778 132 | Height = 504 133 | Align = alTop 134 | TabOrder = 4 135 | end 136 | object BtnWelcome: TBitBtn 137 | Left = 32 138 | Top = 552 139 | Width = 113 140 | Height = 38 141 | Caption = 'Pages' 142 | ParentShowHint = False 143 | ShowHint = True 144 | TabOrder = 5 145 | OnClick = BtnWelcomeClick 146 | Glyph.Data = { 147 | 96010000424D9601000000000000760000002800000018000000180000000100 148 | 04000000000020010000130B0000130B000010000000000000001B1209009D8E 149 | 6F00D5CDB200744D21008482FC00B7A8890094612500FBFBE70059381500BCB5 150 | 9F0078705D0031261B00BF8F4600D7AF5F00AA7A3700E9D59D0043EDFFFDFCDD 151 | C38BA9777FA4483CFFDDDC6366577777777A4433F7DCC688577777777F774443 152 | 65EEE3327777777144876B408366E577777777A44441D8444863D77777777A44 153 | 444BF64443357777777794444444FE4448E777777777B4444444DC8443777777 154 | 777144444444EEEBB2777777777B444444448CDE9777777777944444444403EC 155 | 7777777777A44444444400857777777777B4444444440A85777277777FB44444 156 | 44443772771319777FE304444444417777F5A8F772DDC8444444442777DFF977 157 | 243DFC6B4444448F7FF2F772B448DDFE344444812C77777754443DDE044444B2 158 | FAE97772544446F94444446C1821B44444444417FA44445ED6104444444444A7 159 | 71444088B0044444444444B52B4444444BA444444444444BB944} 160 | end 161 | object BtnSave: TBitBtn 162 | Left = 512 163 | Top = 552 164 | Width = 113 165 | Height = 38 166 | Caption = 'Save changes' 167 | ModalResult = 1 168 | TabOrder = 6 169 | OnClick = BtnSaveClick 170 | Glyph.Data = { 171 | 96010000424D9601000000000000760000002800000018000000180000000100 172 | 04000000000020010000130B0000130B00001000000000000000046604000C7C 173 | 10001EB6340041CE67001C9830002FC54F0059E3890017AC270034B24C00FC02 174 | FC00178F24004FD977002CB2470024AA3A0038BE580024A23400999999999999 175 | 9999999999999999999999999999999999999999999999999999999999999999 176 | 9999999999999999999999999999099999999999999999999990F09999999999 177 | 99999999990D7C09999999999999999990D277D099999999999999990452277D 178 | 09999999999999904355D0C7D09999999999990ABB3C09027D09999999999906 179 | 6BE09990A7D09999999999086E099999907D0999999999903099999999077099 180 | 9999999909999999999017099999999999999999999990A09999999999999999 181 | 9999990109999999999999999999999900999999999999999999999999099999 182 | 9999999999999999999999999999999999999999999999999999999999999999 183 | 9999999999999999999999999999999999999999999999999999} 184 | end 185 | object PopupMenu: TPopupMenu 186 | Left = 2 187 | Top = 544 188 | end 189 | end 190 | -------------------------------------------------------------------------------- /synproject.css: -------------------------------------------------------------------------------- 1 | /* 2 | * synproject.css 3 | * ============== 4 | * 5 | * CSS typical for Synopse SynProject web export 6 | * http://synopse.info 7 | * Licensed under a GPL license 8 | * 9 | */ 10 | 11 | body { 12 | font-family: Arial, Verdana, sans-serif; 13 | font-size: 1em; 14 | color: black; 15 | letter-spacing: -0.01em; 16 | line-height: 150%; 17 | text-align: left; 18 | background-color: #BFD1D4; 19 | padding: 0; 20 | border: 1px solid #aaa; 21 | margin: 0px 80px 0px 80px; 22 | min-width: 740px; 23 | max-width: 1240px; 24 | } 25 | 26 | svg { 27 | max-width: 100%; 28 | } 29 | 30 | div.document { 31 | font-family: Arial, Verdana, sans-serif; 32 | color: black; 33 | background-color: white; 34 | text-align: left; 35 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAoCAYAAAA/tpB3AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gBDRUWN0N7tMwAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAN0lEQVQI16WNOQ4AIADCWv7/XhMnXdR4jC4kQAOUWlsAghIaBCECozhFHMieLatv9sOdbxfsXOngpgVLkKkPEQAAAABJRU5ErkJggg==); 36 | background-repeat: repeat-x; 37 | } 38 | 39 | div.bodywrapper { 40 | margin: 0 240px 0 0; 41 | border-right: 1px solid #ccc; 42 | } 43 | 44 | div.body { 45 | margin: 0; 46 | padding: 0.5em 20px 20px 20px; 47 | } 48 | 49 | div.related { 50 | background-color: white; 51 | font-size: 1em; 52 | } 53 | 54 | div.related a { 55 | color: #444444; 56 | } 57 | 58 | div.related ul { 59 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA8CAYAAACn8dD6AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gBDRUOAHndiZoAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAR0lEQVQY072NwRHAMAzCBPtP6wFCH6mddIF+OBlxZ6oqBrBtLKkJMBLWERJ7LJpChsAEzHSX2DZvnC6ZcfpcWR+bfnSNf48HN9YiTAPwk98AAAAASUVORK5CYII=); 60 | height: 2em; 61 | border-top: 1px solid #ddd; 62 | border-bottom: 1px solid #ddd; 63 | } 64 | 65 | div.related ul li { 66 | margin: 0; 67 | padding: 0; 68 | height: 2em; 69 | float: left; 70 | } 71 | 72 | div.related ul li.right { 73 | float: right; 74 | margin-right: 5px; 75 | } 76 | 77 | div.related ul li a { 78 | margin: 0; 79 | padding: 0 5px 0 5px; 80 | line-height: 1.75em; 81 | color: #EE9816; 82 | } 83 | 84 | div.related ul li a:hover { 85 | color: #3CA8E7; 86 | } 87 | 88 | div.sidebarwrapper { 89 | padding: 0; 90 | } 91 | 92 | div.sidebar { 93 | font-family: Arial, Verdana, sans-serif; 94 | margin: 0; 95 | padding: 0.5em 15px 15px 0; 96 | width: 210px; 97 | float: right; 98 | font-size: 1em; 99 | text-align: left; 100 | } 101 | 102 | @media (max-width: 1200px) { 103 | body { 104 | margin: 0; 105 | } 106 | } 107 | @media (max-width: 767px) { 108 | div.sidebar { 109 | float: none; 110 | padding: 0 0 0 80px 111 | } 112 | } 113 | 114 | div.sidebar h3, div.sidebar h4 { 115 | margin: 1em 0 0.5em 0; 116 | font-size: 1em; 117 | padding: 0.1em 0 0.1em 0.5em; 118 | color: white; 119 | border: 1px solid #86989B; 120 | background-color: #AFC1C4; 121 | } 122 | 123 | div.sidebar h3 a { 124 | color: white; 125 | } 126 | 127 | div.sidebar ul { 128 | padding-left: 1.5em; 129 | margin-top: 7px; 130 | padding: 0; 131 | line-height: 130%; 132 | } 133 | 134 | div.sidebar ul ul { 135 | margin-left: 20px; 136 | } 137 | 138 | div.footer { 139 | background-color: #E3EFF1; 140 | color: #86989B; 141 | padding: 3px 8px 3px 0; 142 | clear: both; 143 | font-size: 0.8em; 144 | text-align: right; 145 | } 146 | 147 | div.footer a { 148 | color: #86989B; 149 | text-decoration: underline; 150 | } 151 | 152 | p { 153 | margin: 0.8em 0 0.5em 0; 154 | } 155 | 156 | a { 157 | color: #00799A; 158 | text-decoration: none; 159 | } 160 | 161 | a:hover { 162 | color: #2491CF; 163 | } 164 | 165 | div.body a { 166 | text-decoration: underline; 167 | } 168 | 169 | h1 { 170 | margin: 2em 0 0 0; 171 | padding: 2em 0 0 0; 172 | font-size: 2em; 173 | color: black; 174 | } 175 | 176 | h2 { 177 | margin: 1.3em 0 0.2em 0; 178 | padding: 1.3em 0 0.3em 0; 179 | font-size: 1.5em; 180 | color: black; 181 | } 182 | 183 | h3, h4, h5, h6 { 184 | margin: 1em 0 -0.3em 0; 185 | padding: 1em 0 0.3em 0; 186 | font-size: 1.35em; 187 | color: black; 188 | } 189 | 190 | div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a { 191 | color: black!important; 192 | } 193 | 194 | h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { 195 | display: none; 196 | margin: 0 0 0 0.3em; 197 | padding: 0 0.2em 0 0.2em; 198 | color: #aaa!important; 199 | } 200 | 201 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, 202 | h5:hover a.anchor, h6:hover a.anchor { 203 | display: inline; 204 | } 205 | 206 | h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, 207 | h5 a.anchor:hover, h6 a.anchor:hover { 208 | color: #777; 209 | background-color: #eee; 210 | } 211 | 212 | a.headerlink { 213 | color: #c60f0f!important; 214 | font-size: 1em; 215 | margin-left: 6px; 216 | padding: 0 4px 0 4px; 217 | text-decoration: none!important; 218 | } 219 | 220 | a.headerlink:hover { 221 | background-color: #ccc; 222 | color: white!important; 223 | } 224 | 225 | cite, code { 226 | font-family: Consolas, 'Deja Vu Sans Mono', monospace; 227 | font-size: 0.95em; 228 | letter-spacing: 0.01em; 229 | } 230 | 231 | code { 232 | background-color: #f2f2f2; 233 | border-bottom: 1px solid #ddd; 234 | color: black; 235 | } 236 | 237 | code.descname, code.descclassname, code.xref { 238 | border: 0; 239 | } 240 | 241 | hr { 242 | border: 1px solid #abc; 243 | margin: 2em; 244 | } 245 | 246 | a code { 247 | border: 0; 248 | color: #CA7900; 249 | } 250 | 251 | a code:hover { 252 | color: #2491CF; 253 | } 254 | 255 | pre { 256 | font-family: Consolas, 'Deja Vu Sans Mono', monospace; 257 | font-size: 0.95em; 258 | white-space: pre-wrap; 259 | letter-spacing: 0.015em; 260 | line-height: 120%; 261 | padding: 0.5em; 262 | border: 1px solid #ccc; 263 | background-color: #f8f8f8; 264 | } 265 | 266 | pre a { 267 | color: inherit; 268 | text-decoration: underline; 269 | } 270 | 271 | td.linenos pre { 272 | padding: 0.5em 0; 273 | } 274 | 275 | div.quotebar { 276 | background-color: #f8f8f8; 277 | max-width: 250px; 278 | float: right; 279 | padding: 2px 7px; 280 | border: 1px solid #ccc; 281 | } 282 | 283 | div.topic { 284 | background-color: #f8f8f8; 285 | } 286 | 287 | table { 288 | border-collapse: collapse; 289 | margin: 0 -0.5em 0 -0.5em; 290 | color: #00498A; 291 | } 292 | 293 | table td, table th { 294 | padding: 0.2em 0.5em 0.2em 0.5em; 295 | border-top: 0; 296 | border-left: 0; 297 | border-right: 0; 298 | border-bottom: 1px solid #aaa; 299 | } 300 | 301 | table pre, table code { 302 | color: #00498A; 303 | } 304 | 305 | div.admonition, div.warning { 306 | font-size: 0.9em; 307 | margin: 1em 0 1em 0; 308 | border: 1px solid #86989B; 309 | background-color: #f7f7f7; 310 | padding: 0; 311 | } 312 | 313 | div.admonition p, div.warning p { 314 | margin: 0.5em 1em 0.5em 1em; 315 | padding: 0; 316 | } 317 | 318 | div.admonition pre, div.warning pre { 319 | margin: 0.4em 1em 0.4em 1em; 320 | } 321 | 322 | div.admonition p.admonition-title, 323 | div.warning p.admonition-title { 324 | margin: 0; 325 | padding: 0.1em 0 0.1em 0.5em; 326 | color: white; 327 | border-bottom: 1px solid #86989B; 328 | font-weight: bold; 329 | background-color: #AFC1C4; 330 | } 331 | 332 | div.warning { 333 | border: 1px solid #940000; 334 | } 335 | 336 | div.warning p.admonition-title { 337 | background-color: #CF0000; 338 | border-bottom-color: #940000; 339 | } 340 | 341 | div.admonition ul, div.admonition ol, 342 | div.warning ul, div.warning ol { 343 | margin: 0.1em 0.5em 0.5em 3em; 344 | padding: 0; 345 | } 346 | 347 | div.versioninfo { 348 | margin: 1em 0 0 0; 349 | border: 1px solid #ccc; 350 | background-color: #DDEAF0; 351 | padding: 8px; 352 | line-height: 1.3em; 353 | font-size: 0.9em; 354 | } 355 | 356 | .label { 357 | display: inline-block; 358 | max-width: 100%; 359 | padding: 1px 5px 1px 5px; 360 | margin-bottom: 5px; 361 | color: white; 362 | background-color: #428bca; 363 | font-family: 'Comic Sans MS', cursive, sans-serif; 364 | font-size: 0.95em; 365 | border: 1px solid #ccc; 366 | } 367 | 368 | .label-primary { 369 | background-color: #5ac7ff; 370 | border: 1px solid #ddd; 371 | } 372 | 373 | @media print { 374 | div.document, 375 | div.documentwrapper, 376 | div.bodywrapper { 377 | margin: 0 !important; 378 | width: 100%; 379 | } 380 | div.sidebar, 381 | div.related, 382 | div.footer, 383 | #top-link { 384 | display: none; 385 | } 386 | } -------------------------------------------------------------------------------- /ProjectFormViewTwo.pas: -------------------------------------------------------------------------------- 1 | /// File Versioning two files diff view form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectFormViewTwo; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 30 | ProjectVersioning, ProjectFrameViewer, ExtCtrls, SynMemoEx; 31 | 32 | type 33 | TDiffCalc = object 34 | FirstDiffLineIndex, 35 | linesAdd, linesMod, linesDel: integer; 36 | procedure Execute(Text1, Text2: string; Memo1, Memo2: TMemoEx; 37 | ShowDiffsOnly: boolean); 38 | end; 39 | 40 | TFormViewTwo = class(TForm) 41 | PanelLeft: TPanel; 42 | Splitter1: TSplitter; 43 | PanelRight: TPanel; 44 | procedure FormResize(Sender: TObject); 45 | procedure SynchronizeOnScroll(Sender: TObject); 46 | public 47 | View1, 48 | View2: TFrameViewer; 49 | Diff: TDiffCalc; // filled by Load() 50 | procedure Load(aVersions: TVersions; aVersion1, aVersion2: PVersion; ShowDiffsOnly: boolean); 51 | end; 52 | 53 | var 54 | FormViewTwo: TFormViewTwo; 55 | 56 | 57 | implementation 58 | 59 | {$R *.dfm} 60 | 61 | uses 62 | ProjectCommons, 63 | ProjectSections, 64 | ProjectDiffUnit; // diff calculation, less efficient than SynDiff, but human-readable 65 | 66 | 67 | 68 | { TDiffCalc } 69 | 70 | procedure TDiffCalc.Execute(Text1, Text2: string; // not const (BinToText...) 71 | Memo1, Memo2: TMemoEx; ShowDiffsOnly: boolean); 72 | var Diff: TDiff; 73 | P1, P2: PChar; 74 | i,j,k, v: integer; 75 | M1, M2: TStrings; 76 | s: string; 77 | procedure WriteIdem; 78 | begin 79 | if M1=nil then 80 | P1 := IgnoreLine(P1) else 81 | M1.AddObject(GetNextLine(P1,P1),pointer(integer(dkIdem)+j shl 3)); 82 | if M2=nil then 83 | P2 := IgnoreLine(P2) else 84 | M2.AddObject(GetNextLine(P2,P2),pointer(integer(dkIdem)+k shl 3)); 85 | inc(j); 86 | inc(k); 87 | end; 88 | begin 89 | // 1. init; 90 | linesAdd := 0; 91 | linesMod := 0; 92 | linesDel := 0; 93 | FirstDiffLineIndex := 0; 94 | if (Memo1=nil) and (Memo2=nil) then exit; 95 | Memo1.BeginUpdate; 96 | Memo2.BeginUpdate; 97 | if Memo1=nil then 98 | M1 := nil else 99 | M1 := Memo1.Lines; 100 | if Memo2=nil then 101 | M2 := nil else 102 | M2 := Memo2.Lines; 103 | try 104 | // 2. if binary file -> format as 80 bytes per line viewable text 105 | BinToTextIfNecessary(Text1); 106 | BinToTextIfNecessary(Text2); 107 | // 3. calculate changes 108 | Diff := CalculateDiff(Text1,Text2); 109 | if Diff=nil then begin 110 | if M1<>nil then 111 | M1.Text := Text1; 112 | if M2<>nil then 113 | M2.Text := Text2; 114 | exit; 115 | end; 116 | // 4. write changes 117 | if M1<>nil then 118 | M1.Clear; 119 | if M2<>nil then 120 | M2.Clear; 121 | j := 0; 122 | k := 0; 123 | P1 := pointer(Text1); 124 | P2 := pointer(Text2); 125 | for i := 0 to Diff.ChangeCount-1 do 126 | with Diff.Changes[i] do begin 127 | //first add preceeding unmodified lines 128 | if ShowDiffsOnly then begin // add from j to x 129 | v := x-j; 130 | if (i>0) and (v>3) then begin // show up to 3 lines after(i>0) modif 131 | WriteIdem; 132 | WriteIdem; 133 | WriteIdem; 134 | dec(v,3); 135 | end; 136 | if v>3 then begin // show 3 lines before modif 137 | if M2<>nil then M2.Add(' ...'); 138 | v := 3; 139 | end; 140 | inc(k, x-j-v); 141 | while j < x-v do begin 142 | P1 := IgnoreLine(P1); 143 | P2 := IgnoreLine(P2); 144 | inc(j); 145 | end; 146 | end; 147 | while j < x do 148 | WriteIdem; 149 | if FirstDiffLineIndex=0 then 150 | FirstDiffLineIndex := k+1; 151 | case Kind of 152 | ckAdd: begin 153 | for j := k to k+Range-1 do begin 154 | if M1<>nil then 155 | M1.AddObject('',pointer(integer(dkAdd))); 156 | if M2=nil then 157 | P2 := IgnoreLine(P2) else 158 | M2.AddObject(GetNextLine(P2,P2),pointer(integer(dkAdd)+j shl 3)); 159 | end; 160 | inc(linesAdd,Range); 161 | j := x; 162 | k := y+Range; 163 | end; 164 | ckModify: begin 165 | for j := 0 to Range-1 do begin 166 | s := GetNextLine(P1,P1); 167 | if M1<>nil then 168 | M1.AddObject(s,pointer(integer(dkModify)+(x+j)shl 3)); 169 | if M2=nil then 170 | P2 := IgnoreLine(P2) else begin 171 | if ShowDiffsOnly then // diff: show original line before 172 | M2.AddObject(s,pointer(integer(dkModify))); 173 | M2.AddObject(GetNextLine(P2,P2),pointer(integer(dkModify)+(k+j)shl 3)); 174 | end; 175 | end; 176 | inc(linesMod,Range); 177 | j := x+Range; 178 | k := y+Range; 179 | end; 180 | ckDelete: begin 181 | for j := x to x+Range-1 do begin 182 | s := GetNextLine(P1,P1); 183 | if M1<>nil then 184 | M1.AddObject(s,pointer(integer(dkDelete)+j shl 3)); 185 | if M2<>nil then 186 | if (M1=nil) and ShowDiffsOnly then // diff: show deleted lines in red 187 | M2.AddObject(s,pointer(integer(dkDelete))) else 188 | M2.AddObject('',pointer(integer(dkDelete))); 189 | end; 190 | inc(linesDel,Range); 191 | j := x+Range; 192 | end; 193 | end; 194 | end; 195 | //add remaining unmodified lines... 196 | if ShowDiffsOnly then begin 197 | if P1^<>#0 then begin WriteIdem; // diff: show up to 3 lines after 198 | if P1^<>#0 then begin WriteIdem; 199 | if P1^<>#0 then begin WriteIdem; 200 | if P1^<>#0 then M2.Add(' ...'); end; end; end; 201 | end else 202 | while P1^<>#0 do 203 | WriteIdem; 204 | Diff.Free; 205 | finally 206 | Memo2.EndUpdate; 207 | Memo1.EndUpdate; 208 | end; 209 | end; 210 | 211 | { TFormViewTwo } 212 | 213 | procedure TFormViewTwo.Load(aVersions: TVersions; aVersion1, aVersion2: PVersion; ShowDiffsOnly: boolean); 214 | var s: string; 215 | M: TMonitor; 216 | v1, v2: string; 217 | begin 218 | if not Visible then begin 219 | Show; 220 | if Screen.MonitorCount>1 then begin // put on other monitor 221 | if Screen.Monitors[0]=Monitor then 222 | M := Screen.Monitors[1] else 223 | M := Screen.Monitors[0]; 224 | with M.WorkareaRect do // manual maximize 225 | SetBounds(Left,Top,Right-Left,Bottom-Top); 226 | end; 227 | end; 228 | View1.Free; 229 | View1 := TFrameViewer.Create(self,aVersions,aVersion1,false); 230 | View1.Parent := PanelLeft; 231 | View1.Align := alClient; 232 | View1.Name := 'View1'; 233 | View1.Diff := true; 234 | View1.MemoEx.OnScroll := SynchronizeOnScroll; 235 | View2.Free; 236 | View2 := TFrameViewer.Create(self,aVersions,aVersion2,false); 237 | View2.Parent := PanelRight; 238 | View2.Align := alClient; 239 | View2.MemoEx.SetFocus; 240 | View2.Name := 'View2'; 241 | View2.Diff := true; 242 | View2.MemoEx.OnScroll := SynchronizeOnScroll; 243 | if (aVersion1=nil) or (aVersion2=nil) then 244 | exit; // Diff.Execute() and Caption will be done manually 245 | v1 := aVersions.GetVersionData(aVersion1^.FileName,aVersion1^.Commit); 246 | v2 := aVersions.GetVersionData(aVersion2^.FileName,aVersion2^.Commit); 247 | Diff.Execute(v1, v2, View1.MemoEx, View2.MemoEx, ShowDiffsOnly); 248 | View1.GotoNextModif; 249 | if aVersion1^.FileName=aVersion2^.FileName then 250 | s := format('%s #%d vs #%d',[ 251 | aVersions.FileNames.Value[aVersion1^.FileName],aVersion1^.Commit,aVersion2^.Commit]) else 252 | s := format('%s #%d vs %s #%d',[ 253 | aVersions.FileNames.Value[aVersion1^.FileName],aVersion1^.Commit, 254 | aVersions.FileNames.Value[aVersion2^.FileName],aVersion2^.Commit]); 255 | Caption := format('%s: %d add, %d mod, %d del',[ 256 | s,Diff.linesAdd,Diff.linesMod,Diff.linesDel]); 257 | end; 258 | 259 | procedure TFormViewTwo.FormResize(Sender: TObject); 260 | begin 261 | PanelLeft.Width := ClientWidth div 2-Splitter1.Width; 262 | end; 263 | 264 | procedure TFormViewTwo.SynchronizeOnScroll(Sender: TObject); 265 | var M: TMemoEx absolute Sender; 266 | begin 267 | if not (Sender.InheritsFrom(TMemoEx)) then exit; 268 | if M=View1.MemoEx then 269 | View2.MemoEx.SetLeftTop(0,M.TopRow) else 270 | if M=View2.MemoEx then 271 | View1.MemoEx.SetLeftTop(0,M.TopRow); 272 | end; 273 | 274 | 275 | end. 276 | -------------------------------------------------------------------------------- /ProjectFrameViewer.pas: -------------------------------------------------------------------------------- 1 | /// File Versioning file view frame 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectFrameViewer; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 30 | Dialogs, ProjectCommons, 31 | ProjectSections, ProjectVersioning, SynMemoEx; 32 | 33 | type 34 | TDiffKind = (dkIdem, dkAdd, dkDelete, dkModify); 35 | 36 | TFrameViewer = class(TFrame) 37 | MemoEx: TMemoEx; 38 | FindDialog: TFindDialog; 39 | procedure MemoExPaintGutter(Sender: TObject; Canvas: TCanvas; const Rect: TRect); 40 | procedure MemoExKeyDown(Sender: TObject; var Key: Word; 41 | Shift: TShiftState); 42 | procedure FindDialogFind(Sender: TObject); 43 | private 44 | fExt, 45 | fFileName: string; 46 | fDiff: boolean; 47 | fInternalOnGetLineAttr: TOnGetLineAttr; 48 | procedure MemoExGetLineAttr(Sender: TObject; const Line: String; 49 | index: Integer; const SelAttrs: TSelAttrs; var Attrs: TLineAttrs); 50 | procedure SetDiff(const Value: boolean); 51 | procedure SetFileName(const Value: string); 52 | public 53 | Versions: TVersions; 54 | constructor Create(AOwner: TComponent; aVersions: TVersions; 55 | aVersion: PVersion; fillMemo: boolean); reintroduce; 56 | procedure GotoNextModif; 57 | property FileName: string read fFileName write SetFileName; 58 | property Diff: boolean read fDiff write SetDiff; 59 | end; 60 | 61 | const 62 | DIFF_KIND_COLOR: array[TDiffKind] of TColor = 63 | (clWhite, $F0CCA8, $BB77FF, $6FFB8A); 64 | 65 | /// if binary file -> format as 80 bytes per line viewable text 66 | procedure BinToTextIfNecessary(var Text: string); 67 | 68 | /// if binary file -> format as 40 bytes per line viewable hex text 69 | procedure BinToHexIfNecessary(var Text: string); 70 | 71 | procedure TabToSpace(P: PChar); 72 | 73 | const 74 | BIN_MAX_SIZE = 256*1024; // truncate binary files under this size 75 | 76 | implementation 77 | 78 | {$R *.dfm} 79 | 80 | uses 81 | ProjectMemoExSyntax, ProjectRTF, ProjectVersionMain; 82 | 83 | 84 | { TFrameViewer } 85 | 86 | procedure TabToSpace(P: PChar); 87 | begin 88 | if P<>nil then 89 | while P^<>#0 do begin 90 | if P^=#9 then 91 | P^ := ' '; 92 | inc(P); 93 | end; 94 | end; 95 | 96 | procedure BinToHexIfNecessary(var Text: string); 97 | // if binary file -> format as 40 bytes per line viewable hex text 98 | var L, i, j, n: integer; 99 | old: string; 100 | S,D: PChar; 101 | begin 102 | L := length(Text); 103 | if L=0 then exit; 104 | for i := 0 to L-1 do 105 | if not (Text[i+1] in [#9,#13,#10,#26,' '..#255]) then begin // may be binary file 106 | if L>BIN_MAX_SIZE then begin 107 | L := BIN_MAX_SIZE; // trunc too big file 108 | old := Copy(Text,1,L); 109 | end else 110 | old := Text; 111 | n := (L+39) div 40; // line count 112 | SetLength(Text,L*2+n*2); 113 | S := pointer(old); 114 | D := pointer(Text); 115 | for j := 0 to n-2 do begin 116 | BinToHex(S,D,40); 117 | inc(S,40); 118 | inc(D,80); 119 | pWord(D)^ := $0a0d; 120 | inc(D,2); 121 | end; 122 | n := L mod 40; 123 | if n>0 then begin 124 | BinToHex(S,D,n); 125 | inc(D,n); 126 | pWord(D)^ := $0a0d; 127 | inc(D,2); 128 | end; 129 | D^ := #0; 130 | exit; 131 | end; 132 | TabToSpace(pointer(Text)); 133 | end; 134 | 135 | procedure GoodWrite(S,D: PChar; n: integer); 136 | var i: integer; 137 | begin 138 | for i := 1 to n do begin 139 | if S^<' ' then 140 | D^ := ' ' else 141 | D^ := S^; 142 | inc(S); 143 | inc(D); 144 | end; 145 | end; 146 | 147 | procedure BinToTextIfNecessary(var Text: string); 148 | // if binary file -> format as 80 bytes per line viewable text 149 | var L, i, j, n: integer; 150 | old: string; 151 | S,D: PChar; 152 | begin 153 | L := length(Text); 154 | if L=0 then exit; 155 | for i := 0 to L-1 do 156 | if not (Text[i+1] in [#9,#13,#10,#26,' '..#255]) then begin // may be binary file 157 | if L>BIN_MAX_SIZE then begin 158 | L := BIN_MAX_SIZE; // trunc too big file 159 | old := Copy(Text,1,L); 160 | end else 161 | old := Text; 162 | n := (L+79) div 80; // line count 163 | SetLength(Text,L+n*2); 164 | S := pointer(old); 165 | D := pointer(Text); 166 | for j := 0 to n-2 do begin 167 | GoodWrite(S,D,80); 168 | inc(S,80); 169 | inc(D,80); 170 | pWord(D)^ := $0a0d; 171 | inc(D,2); 172 | end; 173 | n := L mod 80; 174 | if n>0 then begin 175 | GoodWrite(S,D,n); 176 | inc(D,n); 177 | pWord(D)^ := $0a0d; 178 | inc(D,2); 179 | end; 180 | D^ := #0; 181 | exit; 182 | end; 183 | TabToSpace(pointer(Text)); 184 | end; 185 | 186 | constructor TFrameViewer.Create(AOwner: TComponent; aVersions: TVersions; 187 | aVersion: PVersion; fillMemo: boolean); 188 | var Text: string; 189 | begin 190 | inherited Create(AOwner); 191 | if Screen.Fonts.IndexOf('Consolas')>=0 then 192 | MemoEx.Font.Name := 'Consolas'; 193 | MemoEx.Font.Size := 9; 194 | Versions := aVersions; 195 | if (aVersion=nil) or (Versions=nil) then exit; 196 | FileName := Versions.FileNames.Value[aVersion^.FileName]; 197 | MemoEx.GutterWidth := 40; 198 | MemoEx.OnPaintGutter := MemoExPaintGutter; 199 | if fillMemo then begin 200 | Text := Versions.GetVersionData(aVersion^.FileName,aVersion^.Commit); 201 | if not Assigned(fInternalOnGetLineAttr) then 202 | BinToTextIfNecessary(Text) else 203 | TabToSpace(pointer(Text)); 204 | MemoEx.Lines.Text := Text; 205 | MemoEx.OnGetLineAttr := fInternalOnGetLineAttr; 206 | end else 207 | MemoEx.OnGetLineAttr := MemoExGetLineAttr; 208 | end; 209 | 210 | procedure LineBackColor(Color: TColor; var Attrs: TLineAttrs; L: integer); 211 | var i: integer; 212 | begin 213 | for i := 0 to L-1 do 214 | Attrs[i].BC := Color; 215 | end; 216 | 217 | procedure TFrameViewer.MemoExGetLineAttr(Sender: TObject; 218 | const Line: String; index: Integer; const SelAttrs: TSelAttrs; 219 | var Attrs: TLineAttrs); 220 | var Kind: TDiffKind; 221 | begin 222 | if Assigned(fInternalOnGetLineAttr) then // syntax highlighting of the text 223 | fInternalOnGetLineAttr(Sender,Line,Index,SelAttrs,Attrs); 224 | if Diff and (index>=0) and (indexdkIdem then // modified? -> special background color 227 | LineBackColor(DIFF_KIND_COLOR[Kind],Attrs,length(Line)); 228 | end; 229 | end; 230 | 231 | procedure TFrameViewer.MemoExPaintGutter(Sender: TObject; Canvas: TCanvas; const Rect: TRect); 232 | var L: integer; 233 | M: TMemoEx absolute Sender; 234 | s: string; 235 | i, v: integer; 236 | begin 237 | if M.GutterWidth=0 then exit; 238 | Canvas.Font.Color := clWhite; 239 | for L := 0 to M.VisibleRowCount-1 do begin 240 | v := M.TopRow+L; 241 | if v>=M.Lines.Count then exit; 242 | with M.Lines.Paragraphs[v]^ do 243 | if Diff and (FStrings[0]='') then // diff: don't show line number for void line 244 | continue else begin 245 | i := integer(FObject) shr 3; 246 | if i=0 then 247 | if Diff then 248 | continue else 249 | i := v+1; 250 | s := IntToStr(i); 251 | Canvas.TextOut(Rect.Right-Canvas.TextWidth(s)-8,Rect.Top+1+L*M.CellRect.Height,s); 252 | end; 253 | end; 254 | end; 255 | 256 | procedure TFrameViewer.GotoNextModif; 257 | var i: integer; 258 | L: TEditorStrings; 259 | K1,K2: TDiffKind; 260 | begin 261 | if not Diff then exit; 262 | L := MemoEx.Lines; 263 | if MemoEx.CaretY>=L.Count then exit; 264 | K1 := TDiffKind(integer(L.Paragraphs[MemoEx.CaretY]^.FObject) and 7); 265 | for i := MemoEx.CaretY+1 to L.Count-1 do begin // search current 266 | K2 := TDiffKind(integer(L.Paragraphs[i]^.FObject) and 7); 267 | if (K2<>dkIdem) and (K2<>K1) then begin 268 | MemoEx.TopRow := i-8; 269 | MemoEx.SetCaret(0,i); 270 | exit; 271 | end; 272 | K1 := K2; 273 | end; 274 | MemoEx.SetCaret(0,0); // not found -> will search from bottom down 275 | end; 276 | 277 | procedure TFrameViewer.MemoExKeyDown(Sender: TObject; var Key: Word; 278 | Shift: TShiftState); 279 | var P: TWinControl; 280 | W: string; 281 | begin 282 | case Key of 283 | VK_F3: 284 | if FindDialog.FindText<>'' then // F3 = Find Next 285 | FindDialog.OnFind(nil); 286 | VK_ESCAPE: begin // escape key -> hide code form 287 | P := Parent; 288 | while (P<>nil) and not P.InheritsFrom(TCustomForm) do 289 | P := P.Parent; 290 | if (P<>nil) and (P<>Application.MainForm) and P.InheritsFrom(TCustomForm) then 291 | if fsModal in TCustomForm(P).FormState then 292 | TCustomForm(P).Close else 293 | TCustomForm(P).Hide; 294 | end; 295 | VK_F7: begin 296 | GotoNextModif; // F7 for next modif 297 | Key := 0; 298 | end; 299 | ord('F'): 300 | if ssCtrl in Shift then begin 301 | W := MemoEx.GetWordOnCaret; 302 | if W<>'' then 303 | FindDialog.FindText := W; 304 | FindDialog.Execute; // Ctrl + F = find 305 | end; 306 | { ord('S'): 307 | if ssAlt in Shift then begin 308 | GotoNextModif; // Alt-S for next modif 309 | Key := 0; 310 | end; } 311 | end; // case Key of 312 | end; 313 | 314 | procedure TFrameViewer.SetDiff(const Value: boolean); 315 | begin 316 | fDiff := Value; 317 | if fDiff then 318 | MemoEx.OnGetLineAttr := MemoExGetLineAttr else 319 | MemoEx.OnGetLineAttr := fInternalOnGetLineAttr; 320 | end; 321 | 322 | 323 | procedure TFrameViewer.FindDialogFind(Sender: TObject); 324 | begin 325 | if not MemoEx.FindNext(FindDialog.FindText,not(frMatchCase in FindDialog.Options)) then 326 | FindDialog.CloseDialog; 327 | end; 328 | 329 | procedure TFrameViewer.SetFileName(const Value: string); 330 | begin 331 | fFileName := Value; 332 | fExt := ExtractFileExt(fFileName); 333 | fInternalOnGetLineAttr := TProjectSyntax.GetHighliter(fExt); 334 | end; 335 | 336 | initialization 337 | assert(integer(high(TDiffKind))<8); 338 | end. 339 | 340 | -------------------------------------------------------------------------------- /ProjectTrackerLogin.pas: -------------------------------------------------------------------------------- 1 | /// PVCS Tracker connection login form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectTrackerLogin; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | uses 29 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 30 | Dialogs, StdCtrls, Buttons, ExtCtrls, ProjectTrkTool, ProjectCommons, ComCtrls, 31 | ProjectSections, CheckLst; 32 | 33 | type 34 | TProjectTrackerLoginForm = class(TForm) 35 | BtnOk: TBitBtn; 36 | BtnCancel: TBitBtn; 37 | Pages: TPageControl; 38 | TabUser: TTabSheet; 39 | TabProject: TTabSheet; 40 | TabSCR: TTabSheet; 41 | UserName: TLabeledEdit; 42 | PassWord: TLabeledEdit; 43 | Label1: TLabel; 44 | Project: TListBox; 45 | Label2: TLabel; 46 | SCRList: TListBox; 47 | Label3: TLabel; 48 | TabSCRMulti: TTabSheet; 49 | Label4: TLabel; 50 | SCRListMulti: TCheckListBox; 51 | BtnSelAll: TButton; 52 | BtnSelNone: TButton; 53 | BtnSelOpen: TButton; 54 | procedure FormShow(Sender: TObject); 55 | procedure FormDestroy(Sender: TObject); 56 | procedure BtnOkClick(Sender: TObject); 57 | procedure SCRListDrawItem(Control: TWinControl; Index: Integer; 58 | Rect: TRect; State: TOwnerDrawState); 59 | procedure SCRListClick(Sender: TObject); 60 | procedure BtnSelAllClick(Sender: TObject); 61 | procedure SCRListMultiClickCheck(Sender: TObject); 62 | private 63 | OriginalProjectIndex: integer; 64 | public 65 | Tracker: TPVCSTracker; 66 | SelectedID: integer; 67 | procedure ShowLogin; 68 | procedure ShowSCRList; 69 | procedure ShowSCRListMulti(const Title: string); 70 | end; 71 | 72 | var 73 | ProjectTrackerLoginForm: TProjectTrackerLoginForm = nil; 74 | 75 | function TrackerLogin(forceLog: boolean): TProjectTrackerLoginForm; 76 | procedure DeleteTempForm(F: TForm); // call after TrackerLogin() 77 | 78 | procedure SCRImportOne(Tracker: TPVCSTracker; n: integer; 79 | out Description, Request: string; Body: PString=nil); 80 | 81 | // show TProjectTrackerLoginForm to select entries to import 82 | function SCRImport(SCR: TSectionsStorage; forceLog: boolean=false): boolean; 83 | 84 | 85 | resourcestring 86 | sSelectEntriesToImport = 'Select entries to import'; 87 | sLocalSCRN = 'BRS SCR #%d'; 88 | 89 | implementation 90 | 91 | uses 92 | ProjectRTF; 93 | 94 | {$R *.dfm} 95 | 96 | procedure DeleteTempForm(F: TForm); 97 | begin 98 | if F<>ProjectTrackerLoginForm then 99 | F.Free; // delete temp form created if ProjectTrackerLoginForm not available 100 | end; 101 | 102 | function TrackerLogin(forceLog: boolean): TProjectTrackerLoginForm; 103 | begin 104 | if ProjectTrackerLoginForm=nil then // create temp form if not available 105 | result := TProjectTrackerLoginForm.Create(Application) else begin 106 | result := ProjectTrackerLoginForm; 107 | if not forceLog and (result.Tracker<>nil) and result.Tracker.Logged then 108 | exit; 109 | end; 110 | try 111 | result.ShowLogin; 112 | if result.ShowModal=mrOk then 113 | assert((result.Tracker<>nil)and(result.Tracker.Logged)) else begin 114 | DeleteTempForm(result); 115 | result := nil; // return nil of error login 116 | end; 117 | except 118 | on TPVCSTrackerException do begin 119 | // if result.Visible then result.Hide; 120 | DeleteTempForm(result); 121 | result := nil; 122 | end; 123 | end; 124 | end; 125 | 126 | function StringImport(const s: string): string; 127 | var j: integer; 128 | begin 129 | result := s; 130 | j := 1; 131 | while jnil then 179 | try 180 | F.ShowSCRListMulti(sSelectEntriesToImport); 181 | if F.ShowModal=mrOk then 182 | try 183 | Screen.Cursor := crHourGlass; 184 | for i := 0 to F.SCRListMulti.Count-1 do 185 | if F.SCRListMulti.Checked[i] then begin 186 | // 1. get checked item 187 | n := integer(F.SCRListMulti.Items.Objects[i]); 188 | num := IntToStr(n); 189 | if SCR[num]<>nil then 190 | exit; // don't add if already there 191 | // 2. update SCR with PVCS values 192 | SCRImportOne(F.Tracker,n,aDescription,aRequest,@aBody); 193 | with SCR.GetOrCreateSection(num,true) do begin 194 | Value['Request'] := aRequest; 195 | Value['ShortName'] := ''; 196 | Value['Description'] := aDescription; 197 | end; 198 | SCR.WriteBody(num,aBody); 199 | end; 200 | result := true; 201 | finally 202 | Screen.Cursor := crDefault; 203 | end; 204 | finally 205 | DeleteTempForm(F); 206 | end; 207 | end; 208 | 209 | procedure TProjectTrackerLoginForm.FormShow(Sender: TObject); 210 | begin 211 | SelectedID := 0; 212 | if Tracker=nil then 213 | try 214 | Tracker := TPVCSTracker.Create; 215 | except 216 | on TPVCSTrackerException do 217 | FreeAndNil(Tracker); 218 | end; 219 | end; 220 | 221 | procedure TProjectTrackerLoginForm.FormDestroy(Sender: TObject); 222 | begin 223 | FreeAndNil(Tracker); 224 | end; 225 | 226 | procedure TProjectTrackerLoginForm.BtnOkClick(Sender: TObject); 227 | var i: integer; 228 | begin 229 | try 230 | try 231 | Screen.Cursor := crHourGlass; 232 | if Tracker<>nil then 233 | case Pages.ActivePageIndex of 234 | 0: begin 235 | Tracker.Login(UserName.Text,PassWord.Text); 236 | if Tracker.Logged then begin 237 | Pages.ActivePageIndex := 1; 238 | OriginalProjectIndex := Tracker.GetProjects(Project.Items); 239 | Project.ItemIndex := OriginalProjectIndex; 240 | end; 241 | end; 242 | 1: begin 243 | i := Project.ItemIndex; 244 | if i>=0 then begin 245 | if i<>OriginalProjectIndex then // relog only if necessary 246 | Tracker.Login(UserName.Text,PassWord.Text,Project.Items[i]); 247 | if Tracker.Logged then 248 | exit; // leave ModalResult=mrOk 249 | end; 250 | end; 251 | 2: begin 252 | SelectedID := SCRList.ItemIndex; 253 | if SelectedID>=0 then begin 254 | SelectedID := integer(SCRList.Items.Objects[SelectedID]); 255 | exit; // leave ModalResult=mrOk 256 | end; 257 | end; 258 | 3: exit; // BtnOk.enabled=true only if something was checked -> direct exit 259 | end; 260 | finally 261 | Screen.Cursor := crDefault; 262 | end; 263 | except 264 | on E: TPVCSTrackerException do 265 | ShowMessage(E.Message); // just show error message from Tracker 266 | end; 267 | ModalResult := mrNone; // don't close form 268 | end; 269 | 270 | procedure TProjectTrackerLoginForm.ShowSCRList; 271 | begin 272 | BtnOK.Enabled := false; 273 | Pages.ActivePageIndex := 2; 274 | if (Tracker=nil) or not Tracker.Logged then 275 | exit; 276 | BtnOK.Caption := ValAt(BtnOK.Hint,0); // Hint='OK,Connect' 277 | Tracker.FillQuery(SCRList.Items); 278 | end; 279 | 280 | procedure TProjectTrackerLoginForm.ShowLogin; 281 | begin 282 | Pages.ActivePageIndex := 0; 283 | BtnOK.Enabled := true; 284 | BtnOK.Caption := ValAt(BtnOK.Hint,1); // Hint='OK,Connect' 285 | Label3.Caption := Caption+' '+BtnOK.Caption; 286 | end; 287 | 288 | procedure TProjectTrackerLoginForm.SCRListDrawItem(Control: TWinControl; 289 | Index: Integer; Rect: TRect; State: TOwnerDrawState); 290 | var List: TCustomListBox absolute Control; 291 | begin 292 | with List.Canvas do begin 293 | FillRect(Rect); 294 | Font.Style := [fsBold]; 295 | TextOut(Rect.Left+4,Rect.Top,'#'+IntToStr(integer(List.Items.Objects[Index]))); 296 | Font.Style := []; 297 | TextOut(Rect.Left+40,Rect.Top,List.Items[Index]); 298 | end; 299 | end; 300 | 301 | procedure TProjectTrackerLoginForm.SCRListClick(Sender: TObject); 302 | begin 303 | BtnOk.Enabled := SCRList.ItemIndex>=0; 304 | end; 305 | 306 | procedure TProjectTrackerLoginForm.ShowSCRListMulti(const Title: string); 307 | begin 308 | Label4.Caption := Title; 309 | BtnOK.Enabled := false; 310 | Pages.ActivePageIndex := 3; 311 | if (Tracker=nil) or not Tracker.Logged then 312 | exit; 313 | BtnOK.Caption := ValAt(BtnOK.Hint,0); // Hint='OK,Connect' 314 | Tracker.FillQuery(SCRListMulti.Items); 315 | end; 316 | 317 | procedure TProjectTrackerLoginForm.BtnSelAllClick(Sender: TObject); 318 | var i: integer; 319 | begin 320 | for i := 0 to SCRListMulti.Count-1 do 321 | if Sender=BtnSelAll then 322 | SCRListMulti.Checked[i] := true else 323 | if Sender=BtnSelNone then 324 | SCRListMulti.Checked[i] := false else 325 | SCRListMulti.Checked[i] := pos('(Open)',SCRListMulti.Items[i])>0; 326 | SCRListMultiClickCheck(nil); 327 | end; 328 | 329 | procedure TProjectTrackerLoginForm.SCRListMultiClickCheck(Sender: TObject); 330 | var i: integer; 331 | begin 332 | for i := 0 to SCRListMulti.Count-1 do 333 | if SCRListMulti.Checked[i] then begin 334 | BtnOk.Enabled := true; 335 | exit; 336 | end; 337 | BtnOk.Enabled := false; 338 | end; 339 | 340 | end. 341 | -------------------------------------------------------------------------------- /ProjectEditMain.pas: -------------------------------------------------------------------------------- 1 | /// Documentation Editor main form 2 | // - this unit is part of SynProject, under GPL 3.0 license; version 1.7 3 | unit ProjectEditMain; 4 | 5 | (* 6 | This file is part of SynProject. 7 | 8 | Synopse SynProject. Copyright (C) 2008-2023 Arnaud Bouchez 9 | Synopse Informatique - https://synopse.info 10 | 11 | SynProject is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3 of the License, or (at 14 | your option) any later version. 15 | 16 | SynProject is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with SynProject. If not, see . 23 | 24 | *) 25 | 26 | interface 27 | 28 | {.$define AUTOBACKUPASZIP} 29 | { if defined, an automatic backup copy will be made in a .ZIP file for each day 30 | not to be used in global ProjectVersion (uses project differential backup) } 31 | 32 | uses 33 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 34 | Dialogs, SynMemoEx, 35 | ProjectCommons, ProjectEditor, ProjectTypes, ProjectSections, 36 | StdCtrls, ExtCtrls, ComCtrls; 37 | 38 | type 39 | TProMainForm = class(TForm) 40 | Sections: TListBox; 41 | Splitter2: TSplitter; 42 | Splitter1: TSplitter; 43 | StatusBar: TStatusBar; 44 | procedure FormCreate(Sender: TObject); 45 | procedure SectionsClick(Sender: TObject); 46 | procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 47 | procedure WholeFileClick(Sender: TObject); 48 | procedure FormShow(Sender: TObject); 49 | procedure FormDestroy(Sender: TObject); 50 | procedure SectionsMouseDown(Sender: TObject; Button: TMouseButton; 51 | Shift: TShiftState; X, Y: Integer); 52 | private 53 | fData: TSectionsStorage; 54 | OldSectionIndex: integer; 55 | procedure DataToSections; 56 | procedure EditorsToData(const FocusSectionName: string); 57 | procedure SaveToFile(Sender: TObject); 58 | public 59 | Editor, Params: TFrameEditor; 60 | procedure InitEditor(const Title, ProFileName: string); 61 | procedure DataChangedInEditorSection(Sender: TObject; const newData: string); 62 | property Data: TSectionsStorage read FData; 63 | end; 64 | 65 | var 66 | ProMainForm: TProMainForm; 67 | 68 | resourcestring 69 | sWholeFile = 'Whole File'; 70 | 71 | 72 | 73 | implementation 74 | 75 | {$R *.dfm} 76 | 77 | uses 78 | ProjectDiff, // for Adler32Asm 79 | {$ifdef AUTOBACKUPASZIP} 80 | ZipOnly, 81 | {$endif} 82 | ProjectRTF, ProjectVersionMain; 83 | 84 | procedure TProMainForm.DataToSections; 85 | var i: integer; 86 | begin 87 | if fData=nil then exit; 88 | with Sections.Items do begin 89 | BeginUpdate; 90 | Clear; 91 | Add('* '+sWholeFile); 92 | for i := 0 to fData.Sections.Count-1 do 93 | AddObject(fData.Sections[i].SectionName,fData.Sections[i]); 94 | EndUpdate; 95 | end; 96 | end; 97 | 98 | procedure TProMainForm.EditorsToData(const FocusSectionName: string); 99 | var OldSec: TSection; 100 | paramsText, bodyText: string; 101 | begin 102 | if fData=nil then exit; 103 | if OldSectionIndex>=0 then begin 104 | OldSec := TSection(Sections.Items.Objects[OldSectionIndex]); 105 | if OldSec=nil then begin // all Text 106 | if Editor.UpdateDataFromTextAllIfNecessary then 107 | DataToSections; 108 | if FocusSectionName<>'' then 109 | Sections.ItemIndex := Sections.Items.IndexOf(FocusSectionName); 110 | end else begin 111 | if Editor.Memo.Modified or Params.Memo.Modified then begin 112 | paramsText := trim(Params.Memo.Lines.Text); 113 | bodyText := trim(Editor.Memo.Lines.Text); 114 | if paramsText<>'' then begin // Params exists -> enforce separate from body 115 | if (bodyText<>'') and (bodyText[1]<>':') then 116 | paramsText := paramsText+#13#10; 117 | end else // paramsText='' -> put body after a CRLF if not title first 118 | if (bodyText<>'') and (bodyText[1]<>':') then 119 | paramsText := #13#10; 120 | OldSec.ReadSection(PChar(paramsText+bodyText)); 121 | fData.Modified := true; 122 | end; 123 | end; 124 | end; 125 | end; 126 | 127 | procedure TProMainForm.FormCreate(Sender: TObject); 128 | begin 129 | OldSectionIndex := -1; 130 | Editor := TFrameEditor.Create(Self); 131 | Editor.BtnSave.OnClick := SaveToFile; 132 | Editor.Name := 'Editor'; 133 | Editor.Parent := Self; 134 | Editor.Align := alClient; 135 | Editor.Params := false; 136 | Editor.BtnTextAll.OnClick := WholeFileClick; 137 | Params := TFrameEditor.Create(Self); 138 | Params.Parent := Self; 139 | Params.Align := alRight; 140 | Params.Params := true; 141 | Params.Panel.Width := Max((ClientWidth -Sections.Width) div 3,300); 142 | Params.BtnTextAll.OnClick := WholeFileClick; 143 | Splitter1.Left := Params.Left; 144 | OnKeyDown := Editor.OnEscKeyDown; // Escape key will close form 145 | end; 146 | 147 | procedure TProMainForm.SectionsMouseDown(Sender: TObject; 148 | Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 149 | var index: integer; 150 | E: TFrameEditor; 151 | aText: string; 152 | begin 153 | if Button=mbRight then begin 154 | index := Sections.ItemAtPos(Point(X,Y),true); 155 | if index<0 then exit; 156 | aText := fData[Sections.Items[index]].Lines.Text; 157 | if aText='' then exit; 158 | with CreateFormEditor(nil,E,false, 159 | ' ['+Sections.Items[index]+'] Section Read-Only View') do begin 160 | E.BtnWordWrap.Down := true; 161 | E.Memo.WordWrap := true; 162 | E.Memo.Lines.Text := aText; 163 | Width := Width-E.Sections.Width; 164 | E.Sections.Hide; 165 | E.ReadOnly := true; 166 | E.BtnReadOnly.Enabled := false; 167 | E.BtnSave.Enabled := false; 168 | E.BtnWizard.Enabled := false; 169 | OnClose := MainForm.FormClose; // Action := caFree 170 | Show; // show as Read-Only text 171 | end; 172 | end; 173 | end; 174 | 175 | procedure TProMainForm.SectionsClick(Sender: TObject); 176 | var Sec: TSection; 177 | i, index: integer; 178 | SecName, s: string; 179 | M: TStrings; 180 | begin 181 | if fData=nil then exit; 182 | index := Sections.ItemIndex; 183 | if index<0 then exit; 184 | if index=OldSectionIndex then exit; 185 | SecName := Sections.Items[index]; 186 | EditorsToData(SecName); // if Modified in the Editors -> save to Data 187 | Sec := TSection(Sections.Items.Objects[index]); 188 | if Sec=nil then begin // first line: all Text 189 | Params.Memo.Lines.Clear; 190 | Params.Hide; 191 | Editor.OnDataChange := nil; 192 | Editor.Memo.Lines.Text := fData.Text; 193 | Editor.TextAll := true; 194 | if OldSectionIndex>=0 then begin 195 | Sec := TSection(Sections.Items.Objects[OldSectionIndex]); 196 | if Sec<>nil then begin 197 | i := Editor.Sections.Items.IndexOf(Sec.SectionName); 198 | if i>=0 then begin 199 | Editor.Sections.ItemIndex := i; 200 | Editor.SectionsClick(self); // Sender<>nil -> no search of MemoWordClickText 201 | end; 202 | end; 203 | end; 204 | end else begin // update Params+Editor with Sec content: 205 | Params.Memo.BeginUpdate; // M.BeginUpdate is not sufficient 206 | M := Params.Memo.Lines; 207 | M.Clear; 208 | with Sec.Lines do begin 209 | i := 0; 210 | while i'' then 227 | M.Add(s); 228 | inc(i); 229 | end; 230 | Editor.Memo.EndUpdate; 231 | Editor.Memo.Modified := false; 232 | Params.Show; 233 | if Params.Memo.Lines.Count=0 then 234 | Params.Width := 140 else 235 | if M.Count=0 then 236 | Params.Width := (ClientWidth-Sections.Width)-140 else 237 | Params.Width := (ClientWidth-Sections.Width)div 2; 238 | Editor.TextAll := false; 239 | end; 240 | OldSectionIndex := index; 241 | end; 242 | 243 | procedure TProMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 244 | begin 245 | if fData=nil then exit; 246 | EditorsToData(''); // if Modified in the Editors -> save to Data 247 | if fData.Modified then // if Data modified -> save to file 248 | case MessageDlg(SErrorDocModifiedAskSave,mtConfirmation,mbYesNoCancel,0) of 249 | mrYes: SaveToFile(nil); 250 | mrCancel: CanClose := false; 251 | end; 252 | end; 253 | 254 | procedure TProMainForm.WholeFileClick(Sender: TObject); 255 | begin 256 | Sections.ItemIndex := 0; 257 | SectionsClick(nil); 258 | end; 259 | 260 | procedure TProMainForm.FormShow(Sender: TObject); 261 | begin 262 | Sections.ItemIndex := 0; 263 | SectionsClick(nil); 264 | Application.ProcessMessages; 265 | Editor.Memo.SetFocus; 266 | end; 267 | 268 | procedure TProMainForm.SaveToFile(Sender: TObject); 269 | var Bak: string; 270 | W: TStringWriter; 271 | Adler32: cardinal; 272 | {$ifdef AUTOBACKUPASZIP} 273 | SystemTime: TSystemTime; 274 | Zip: TZip; 275 | FileName: string; 276 | {$endif} 277 | begin 278 | if fData=nil then exit; 279 | EditorsToData(''); // if Modified in the Editors -> save to Data 280 | if not fData.Modified then exit; 281 | bak := ChangeFileExt(fData.FileName,'.~pro'); 282 | fData.SaveText(W); 283 | Adler32 := Adler32Asm(0,W.DataPointer,W.len); 284 | if Adler32<>fData.Adler32AsCreated then begin // if something really changed :) 285 | fData.Adler32AsCreated := Adler32; 286 | DeleteFile(bak); 287 | RenameFile(fData.FileName,bak); 288 | W.SaveToFile(fData.FileName); 289 | {$ifdef AUTOBACKUPASZIP} 290 | GetLocalTime(SystemTime); 291 | bak := ExtractFilePath(fData.FileName)+'Backup'; 292 | if not DirectoryExists(bak) then 293 | mkDir(bak); 294 | FileName := ValAt(ExtractFileName(fData.FileName),0,'.'); 295 | bak := format('%s\%s %d%.2d%.2d.zip',[bak,FileName, 296 | SystemTime.wYear,SystemTime.wMonth,SystemTime.wDay]); 297 | Zip := TZip.Create(bak); 298 | Zip.AddBuf(format('%s %.2dh%.2d%s',[ValAt(ExtractFileName(bak),0,'.'), 299 | SystemTime.wHour,SystemTime.wMinute,ExtractFileExt(fData.FileName)]), 300 | 6,W.DataPointer,W.len); 301 | Zip.Free; 302 | {$endif} 303 | end; 304 | fData.Modified := false; 305 | Editor.Memo.Modified := false; 306 | Params.Memo.Modified := false; 307 | end; 308 | 309 | procedure TProMainForm.DataChangedInEditorSection(Sender: TObject; const newData: string); 310 | begin 311 | if fData=nil then exit; 312 | fData.LoadFromMemory(pointer(newData),length(newData)); 313 | fData.Modified := true; 314 | DataToSections; 315 | Sections.ItemIndex := 0; // whole file edit 316 | SectionsClick(nil); 317 | if Sender<>nil then 318 | Editor.Memo.Command(ecEndDoc); 319 | end; 320 | 321 | procedure TProMainForm.InitEditor(const Title, ProFileName: string); 322 | begin 323 | FreeAndNil(fData); 324 | fData := TSectionsStorage.Create(ProFileName); 325 | Editor.Data := fData; 326 | Editor.Memo.RightMargin := StrToIntDef( 327 | fData.Section['Project'].Value['EditorRightMargin'],100); 328 | OldSectionIndex := -1; // force reload editor text 329 | Params.Data := fData; 330 | DataToSections; 331 | Caption := ' SynProject - '+Title; 332 | end; 333 | 334 | procedure TProMainForm.FormDestroy(Sender: TObject); 335 | begin 336 | FreeAndNil(fData); 337 | end; 338 | 339 | end. 340 | -------------------------------------------------------------------------------- /ProjectEditor.dfm: -------------------------------------------------------------------------------- 1 | object FrameEditor: TFrameEditor 2 | Left = 0 3 | Top = 0 4 | Width = 904 5 | Height = 238 6 | TabOrder = 0 7 | object Panel: TPanel 8 | Left = 0 9 | Top = 0 10 | Width = 904 11 | Height = 238 12 | Align = alClient 13 | AutoSize = True 14 | TabOrder = 0 15 | object Memo: TMemoEx 16 | Left = 121 17 | Top = 35 18 | Width = 782 19 | Height = 202 20 | Cursor = crIBeam 21 | TabOrder = 0 22 | GutterWidth = 0 23 | RightMarginColor = clSilver 24 | Completion.Separator = '=' 25 | Completion.ItemHeight = 13 26 | Completion.Interval = 800 27 | Completion.ListBoxStyle = lbStandard 28 | Completion.CaretChar = '|' 29 | Completion.CRLF = '/n' 30 | TabStops = '8' 31 | CursorBeyondEOL = True 32 | SelForeColor = clHighlightText 33 | SelBackColor = clHighlight 34 | OnKeyDown = MemoKeyDown 35 | OnChange = MemoChange 36 | OnMouseOver = MemoMouseOver 37 | OnSetCaretPos = MemoSetCaretPos 38 | Align = alClient 39 | Ctl3D = True 40 | Font.Charset = DEFAULT_CHARSET 41 | Font.Color = clWindowText 42 | Font.Height = -13 43 | Font.Name = 'Courier New' 44 | Font.Pitch = fpFixed 45 | Font.Style = [] 46 | ParentColor = False 47 | PopupMenu = EditorPopup 48 | TabStop = True 49 | UseDockManager = False 50 | WordWrap = False 51 | end 52 | object ToolBar: TToolBar 53 | Left = 1 54 | Top = 1 55 | Width = 902 56 | Height = 34 57 | ButtonHeight = 30 58 | ButtonWidth = 31 59 | DisabledImages = ImageListDisabled 60 | Images = ImageListEnabled 61 | TabOrder = 1 62 | object BtnHistoryBack: TToolButton 63 | Left = 0 64 | Top = 2 65 | Enabled = False 66 | ImageIndex = 5 67 | OnClick = BtnHistoryBackClick 68 | end 69 | object BtnHistoryNext: TToolButton 70 | Left = 31 71 | Top = 2 72 | Enabled = False 73 | ImageIndex = 6 74 | OnClick = BtnHistoryNextClick 75 | end 76 | object BtnTextAll: TToolButton 77 | Left = 62 78 | Top = 2 79 | Hint = 'Whole File edition' 80 | ImageIndex = 12 81 | ParentShowHint = False 82 | ShowHint = True 83 | end 84 | object ToolButton1: TToolButton 85 | Left = 93 86 | Top = 2 87 | Width = 8 88 | ImageIndex = 3 89 | Style = tbsSeparator 90 | end 91 | object BtnReadOnly: TToolButton 92 | Left = 101 93 | Top = 2 94 | Hint = 'Read Only' 95 | ImageIndex = 0 96 | ParentShowHint = False 97 | ShowHint = True 98 | OnClick = BtnReadOnlyClick 99 | end 100 | object BtnSave: TToolButton 101 | Left = 132 102 | Top = 2 103 | Hint = 'Save (Ctrl+S)' 104 | ImageIndex = 3 105 | ParentShowHint = False 106 | ShowHint = True 107 | end 108 | object BtnHistory: TToolButton 109 | Left = 163 110 | Top = 2 111 | Hint = 'File History' 112 | DropdownMenu = PopupMenuBtnHistory 113 | ImageIndex = 21 114 | ParentShowHint = False 115 | ShowHint = True 116 | Visible = False 117 | end 118 | object BtnWizard: TToolButton 119 | Left = 194 120 | Top = 2 121 | Hint = 'Documentation Wizard' 122 | ImageIndex = 23 123 | ParentShowHint = False 124 | ShowHint = True 125 | OnClick = BtnWizardClick 126 | end 127 | object BtnDocument: TToolButton 128 | Left = 225 129 | Top = 2 130 | Hint = 'Create Word Document' 131 | ImageIndex = 15 132 | ParentShowHint = False 133 | ShowHint = True 134 | OnClick = BtnLinkSectionClick 135 | end 136 | object ToolButton2: TToolButton 137 | Left = 256 138 | Top = 2 139 | Width = 8 140 | ImageIndex = 4 141 | Style = tbsSeparator 142 | end 143 | object BtnUndo: TToolButton 144 | Left = 264 145 | Top = 2 146 | Hint = 'Undo' 147 | ImageIndex = 10 148 | ParentShowHint = False 149 | ShowHint = True 150 | OnClick = BtnUndoClick 151 | end 152 | object BtnWordWrap: TToolButton 153 | Left = 295 154 | Top = 2 155 | Hint = 'Word Wrap' 156 | ImageIndex = 2 157 | ParentShowHint = False 158 | ShowHint = True 159 | OnClick = BtnWordWrapClick 160 | end 161 | object BtnSpellCheck: TToolButton 162 | Left = 326 163 | Top = 2 164 | Hint = 'Spell Check selection (F7)' 165 | ImageIndex = 26 166 | ParentShowHint = False 167 | ShowHint = True 168 | OnClick = BtnSpellCheckClick 169 | end 170 | object ToolButton3: TToolButton 171 | Left = 357 172 | Top = 2 173 | Width = 8 174 | ImageIndex = 3 175 | Style = tbsSeparator 176 | end 177 | object BtnBold: TToolButton 178 | Left = 365 179 | Top = 2 180 | Hint = 'Selected text to Bold (Ctrl+B)' 181 | ImageIndex = 7 182 | ParentShowHint = False 183 | ShowHint = True 184 | OnClick = BtnBoldItalicUnderlineClick 185 | end 186 | object BtnItalic: TToolButton 187 | Tag = 1 188 | Left = 396 189 | Top = 2 190 | Hint = 'Selected text to Italic (Ctrl+I)' 191 | ImageIndex = 8 192 | ParentShowHint = False 193 | ShowHint = True 194 | OnClick = BtnBoldItalicUnderlineClick 195 | end 196 | object BtnUnderline: TToolButton 197 | Tag = 2 198 | Left = 427 199 | Top = 2 200 | Hint = 'Selected text to Underline (Ctrl+U)' 201 | ImageIndex = 9 202 | ParentShowHint = False 203 | ShowHint = True 204 | OnClick = BtnBoldItalicUnderlineClick 205 | end 206 | object BtnFixedFont: TToolButton 207 | Tag = 3 208 | Left = 458 209 | Top = 2 210 | Hint = 'Selected text to FixedFont (Ctrl+0)' 211 | ImageIndex = 16 212 | ParentShowHint = False 213 | ShowHint = True 214 | OnClick = BtnBoldItalicUnderlineClick 215 | end 216 | object BtnMarkProgram: TToolButton 217 | Left = 489 218 | Top = 2 219 | Hint = 'Mark Selected lines as program code' 220 | DropdownMenu = PopupMenuProgram 221 | ImageIndex = 17 222 | ParentShowHint = False 223 | ShowHint = True 224 | OnClick = BtnMarkProgramClick 225 | end 226 | object BtnLinkSection: TToolButton 227 | Left = 520 228 | Top = 2 229 | Hint = 'Link to Section' 230 | ImageIndex = 11 231 | ParentShowHint = False 232 | ShowHint = True 233 | OnClick = BtnLinkSectionClick 234 | end 235 | object BtnLinkPeople: TToolButton 236 | Left = 551 237 | Top = 2 238 | Hint = 'Link to People' 239 | ImageIndex = 13 240 | ParentShowHint = False 241 | ShowHint = True 242 | OnClick = BtnLinkSectionClick 243 | end 244 | object BtnLinkPicture: TToolButton 245 | Left = 582 246 | Top = 2 247 | Hint = 'Link to Picture' 248 | ImageIndex = 14 249 | ParentShowHint = False 250 | ShowHint = True 251 | OnClick = BtnLinkSectionClick 252 | end 253 | object BtnLinkProgram: TToolButton 254 | Left = 613 255 | Top = 2 256 | Hint = 'Link to an Object (.pas only)' 257 | ImageIndex = 28 258 | ParentShowHint = False 259 | ShowHint = True 260 | OnClick = BtnLinkProgramClick 261 | end 262 | object ToolButton4: TToolButton 263 | Left = 644 264 | Top = 2 265 | Width = 8 266 | ImageIndex = 19 267 | Style = tbsSeparator 268 | end 269 | object BtnAddPicture: TToolButton 270 | Left = 652 271 | Top = 2 272 | Hint = 'Add Picture' 273 | ImageIndex = 19 274 | ParentShowHint = False 275 | ShowHint = True 276 | OnClick = BtnLinkSectionClick 277 | end 278 | object BtnAddGraph: TToolButton 279 | Left = 683 280 | Top = 2 281 | Hint = 'Add/Edit a Graph' 282 | ImageIndex = 25 283 | ParentShowHint = False 284 | ShowHint = True 285 | Visible = False 286 | OnClick = BtnAddGraphClick 287 | end 288 | object BtnAutoSections: TToolButton 289 | Left = 714 290 | Top = 2 291 | Hint = 'Create missing sections for current Document' 292 | ImageIndex = 18 293 | ParentShowHint = False 294 | ShowHint = True 295 | OnClick = BtnAutoSectionsClick 296 | end 297 | object BtnReleaseDocument: TToolButton 298 | Left = 745 299 | Top = 2 300 | Hint = 'Increment the the document history' 301 | ImageIndex = 22 302 | ParentShowHint = False 303 | ShowHint = True 304 | OnClick = BtnReleaseDocumentClick 305 | end 306 | object BtnAddTracker: TToolButton 307 | Left = 776 308 | Top = 2 309 | Hint = 'Add a new Tracker entry (F1)' 310 | ImageIndex = 20 311 | ParentShowHint = False 312 | ShowHint = True 313 | Visible = False 314 | end 315 | object BtnImportTracker: TToolButton 316 | Left = 807 317 | Top = 2 318 | Hint = 'Import entries from PVCS' 319 | Caption = 'BtnImportTracker' 320 | ImageIndex = 24 321 | ParentShowHint = False 322 | ShowHint = True 323 | Visible = False 324 | end 325 | object ToolButton5: TToolButton 326 | Left = 838 327 | Top = 2 328 | Width = 8 329 | Caption = 'ToolButton5' 330 | ImageIndex = 28 331 | Style = tbsSeparator 332 | end 333 | object BtnAbout: TToolButton 334 | Left = 846 335 | Top = 2 336 | Hint = 'About' 337 | ImageIndex = 27 338 | ParentShowHint = False 339 | ShowHint = True 340 | OnClick = BtnAboutClick 341 | end 342 | end 343 | object Sections: TListBox 344 | Left = 1 345 | Top = 35 346 | Width = 120 347 | Height = 202 348 | Align = alLeft 349 | ItemHeight = 13 350 | TabOrder = 2 351 | Visible = False 352 | OnClick = SectionsClick 353 | OnMouseDown = SectionsMouseDown 354 | end 355 | end 356 | object ImageListEnabled: TImageList 357 | Height = 24 358 | Width = 24 359 | Left = 168 360 | Top = 168 361 | end 362 | object ImageListDisabled: TImageList 363 | Height = 24 364 | Width = 24 365 | Left = 256 366 | Top = 168 367 | end 368 | object PopupMenuLink: TPopupMenu 369 | Images = ImageList16 370 | Left = 536 371 | Top = 40 372 | end 373 | object FindDialog: TFindDialog 374 | Options = [frDown, frHideWholeWord, frHideUpDown] 375 | OnFind = FindDialogFind 376 | Left = 128 377 | Top = 40 378 | end 379 | object PopupMenuProgram: TPopupMenu 380 | Images = ImageList16 381 | Left = 496 382 | Top = 40 383 | object PopupMenuProgramDelphi: TMenuItem 384 | Caption = 'Delphi/Pascal' 385 | Hint = '!' 386 | ImageIndex = 17 387 | ShortCut = 113 388 | OnClick = BtnMarkProgramClick 389 | end 390 | object PopupMenuProgramModula2: TMenuItem 391 | Caption = 'Modula2' 392 | Hint = #181 393 | ImageIndex = 17 394 | OnClick = BtnMarkProgramClick 395 | end 396 | object PopupMenuProgramC: TMenuItem 397 | Caption = 'C/C++' 398 | Hint = '&' 399 | ImageIndex = 17 400 | OnClick = BtnMarkProgramClick 401 | end 402 | object PopupMenuProgramCSharp: TMenuItem 403 | Caption = 'C#' 404 | Hint = '#' 405 | ImageIndex = 17 406 | OnClick = BtnMarkProgramClick 407 | end 408 | object PopupMenuProgramINI: TMenuItem 409 | Caption = 'INI/TXT' 410 | Hint = '$' 411 | ImageIndex = 17 412 | OnClick = BtnMarkProgramClick 413 | end 414 | object PopupMenuProgramXML: TMenuItem 415 | Caption = 'XML/HTML' 416 | Hint = '$$' 417 | ImageIndex = 17 418 | OnClick = BtnMarkProgramClick 419 | end 420 | object PopupMenuProgramDFM: TMenuItem 421 | Caption = 'DFM' 422 | Hint = '!$' 423 | ImageIndex = 17 424 | OnClick = BtnMarkProgramClick 425 | end 426 | object PopupMenuProgramComment: TMenuItem 427 | Caption = '; comment' 428 | Hint = ';' 429 | ImageIndex = 17 430 | OnClick = BtnMarkProgramClick 431 | end 432 | end 433 | object PopupMenuBtnHistory: TPopupMenu 434 | Left = 168 435 | Top = 40 436 | end 437 | object EditorPopup: TPopupMenu 438 | Images = ImageList16 439 | OnPopup = EditorPopupPopup 440 | Left = 464 441 | Top = 168 442 | object EditorPopupCopy: TMenuItem 443 | Caption = 'Copy' 444 | ShortCut = 16451 445 | OnClick = EditorPopupCopyClick 446 | end 447 | object EditorPopupCopyAs: TMenuItem 448 | Caption = 'Copy as' 449 | object EditorPopupCopyAsHtml: TMenuItem 450 | Caption = 'HTML' 451 | OnClick = EditorPopupCopyAsHtmlClick 452 | end 453 | object EditorPopupCopyAsBBCode: TMenuItem 454 | Caption = 'BBCODE' 455 | OnClick = EditorPopupCopyAsBBCodeClick 456 | end 457 | end 458 | object EditorPopupPaste: TMenuItem 459 | Caption = 'Paste' 460 | ShortCut = 16470 461 | OnClick = EditorPopupPasteClick 462 | end 463 | object EditorPopupCut: TMenuItem 464 | Caption = 'Cut' 465 | ShortCut = 16472 466 | OnClick = EditorPopupCutClick 467 | end 468 | object N1: TMenuItem 469 | Caption = '-' 470 | end 471 | object EditorPopupUndo: TMenuItem 472 | Caption = 'Undo' 473 | ImageIndex = 10 474 | ShortCut = 16474 475 | OnClick = BtnUndoClick 476 | end 477 | object EditorPopupWordWrap: TMenuItem 478 | Caption = 'Word Wrap' 479 | ImageIndex = 2 480 | OnClick = BtnWordWrapClick 481 | end 482 | object EditorPopupSpellCheck: TMenuItem 483 | Caption = 'Spell check' 484 | ImageIndex = 26 485 | ShortCut = 118 486 | OnClick = BtnSpellCheckClick 487 | end 488 | end 489 | object ImageList16: TImageList 490 | Left = 344 491 | Top = 168 492 | end 493 | end 494 | --------------------------------------------------------------------------------