diff --git a/doc/wiki/Download_Release.note b/doc/wiki/Download_Release.note index e7f5506..e190658 100644 --- a/doc/wiki/Download_Release.note +++ b/doc/wiki/Download_Release.note @@ -114,7 +114,7 @@ If you wish to sync to a SMB: network share, open that connection before configu Arch and Manjaro -And other Linux Distributions that use the Arch, Pacman package system. I have made only a [GTK 64bit]($$PAC64$$) version and, recommended, a [Qt6 64bit]($$PAC64QT6$$] at this stage, could make other combinations if needed. Click the link, choose download and install with this command from ~/Downloads - +And other Linux Distributions that use the Arch, Pacman package system. I have made only a [GTK 64bit]($$PAC64$$) version and, recommended, a [Qt6 64bit]($$PAC64QT6$$) at this stage, could make other combinations if needed. Click the link, choose download and install with this command from ~/Downloads - sudo pacman -U ./tomboy-ng-$$VERSION$$-1-x86_64.pkg.tar.zst @@ -162,8 +162,8 @@ I have not made Raspberry Pi rpms, seems few users. - 2024-11-24T14:23:22.9099786+11:00 - 2024-11-24T14:23:22.9099786+11:00 + 2024-11-26T17:17:20.6169161+11:00 + 2024-11-26T17:17:20.6169161+11:00 2020-01-22T14:51:55.8970000+11:00 1 1 diff --git a/doc/wiki/Download_Release.tokens b/doc/wiki/Download_Release.tokens index 7edc910..245e164 100644 --- a/doc/wiki/Download_Release.tokens +++ b/doc/wiki/Download_Release.tokens @@ -12,6 +12,6 @@ $$RPM64QT6$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v$$VERS $$DEB32ARM$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v$$VERSION$$/tomboy-ng_$$VERSION$$-0_armhf.deb $$DEB64ARM$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v$$VERSION$$/tomboy-ng_$$VERSION$$-0_arm64.deb $$DEB64ARMQT5$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v$$VERSION$$/tomboy-ng_$$VERSION$$-0_arm64Qt5.deb -$$PAC64$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v0.40/tomboy-ng-$$VERSION$$-1-x86_64.pkg.tar.zst -$$PAC64QT6$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v0.40/tomboy-ng-$$VERSION$$-1-Qt6-x86_64.pkg.tar.zst +$$PAC64$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v$$VERSION$$/tomboy-ng-$$VERSION$$-1-x86_64.pkg.tar.zst +$$PAC64QT6$$=https://github.com/tomboy-notes/tomboy-ng/releases/download/v$$VERSION$$/tomboy-ng-$$VERSION$$-1-Qt6-x86_64.pkg.tar.zst $$GPGKEY$$=https://raw.githubusercontent.com/tomboy-notes/tomboy-ng/master/package/tomboy-ng-GPG-KEY diff --git a/prepare.md b/prepare.md index 40b4983..e3cdbaa 100644 --- a/prepare.md +++ b/prepare.md @@ -251,21 +251,22 @@ Debian need a config file, .dput.cf in $HOME that points to mentors, see mentor Pacman ====== -w have both FPC and Lazarus as non package installs, required removal of them as makedependencies. Both must be added to PATH +We have both FPC and Lazarus as non package installs now, required removal of them as makedependencies. Both must be added to PATH +So, on a clean (in my case Endeavour) machine, install gtk2 and qt6pas - - export VER=0.40b + sudo pacmand -S gtk2 qt6pas + [eg]export VER=0.40b mkdir $VER; cd $VER wget https://github.com/tomboy-notes/tomboy-ng/raw/master/scripts/PKGBUILD.gtk2 wget https://github.com/tomboy-notes/tomboy-ng/raw/master/scripts/PKGBUILD.Qt6 - cp PKGBUILD.gtk2 PKGBUILD + cp PKGBUILD.Qt6 PKGBUILD makepkg --skipinteg - mv ... ...gtk2... - copy PKGBUILD.Qt6 PKGBUILD + [eg] mv tomboy-ng-0.41-1-x86_64.pkg.tar.zst tomboy-ng-0.41-1-Qt6-x86_64.pkg.tar.zst + copy PKGBUILD.gtk2 PKGBUILD makepkg --skipinteg - mv ... ...Qt6... - + +The gtk2 version does not have a widget identifier. note that makepkg needs to see $VER too. diff --git a/source/Tomboy_NG.lpr b/source/Tomboy_NG.lpr index 402c03f..d2f005f 100644 --- a/source/Tomboy_NG.lpr +++ b/source/Tomboy_NG.lpr @@ -70,11 +70,11 @@ RequireDerivedFormResource:=True; Application.Initialize; - if ContinueToGUI then begin + if ContinueToGUI() then begin // This is in the CLI.pas, command line activity that may be all thats needed. {$ifdef APPINDPATCH} {$ifdef CPUi386} // Note: unless Ayatana fix their problem, no option for Gnome users - // https://github.com/AyatanaIndicators/libayatana-appindicator/issues/76 + // https://github.com/AyatanaIndicators/libayatana-appindicator/issues/76 UnityWSCtrls.GlobalUseAppInd := UnityWSCtrls.UseAppIndNo; // 32bit must be a 'no'. debugln('Tomboy_NG.lpr : Deciding to set UseAppInd to no to prevent AV.'); debugln('You may over rule that with --useappind=yes to see what happens.'); diff --git a/source/cli.pas b/source/cli.pas index 7fd5974..5f75b58 100644 --- a/source/cli.pas +++ b/source/cli.pas @@ -32,7 +32,8 @@ and also removes anything after it ! But does act on it. Seems both - and -- acceptable - --platformtheme qt5ct -platformtheme qt5ct - And an typo in the option value is ignored, use a space as seperator, not '=' ! + And a typo in the option value is ignored. + Use a space as seperator, not '=' ! } interface @@ -54,6 +55,7 @@ function Import_Text_MD_File(MD : boolean; FFName : string = '') : string; var SingleNoteName : string = ''; // other unit will want to know..... + OpenNewNotePlease : boolean = false; const Version_string = {$I %TOMBOY_NG_VER}; @@ -72,7 +74,7 @@ ENoNotesRepoException = class(Exception); LongOpts : TStringArray; // See initialization section const - ShortOpts = 'hgo:l:vt:m:n:'; // help gnome3 open lang ver import-[txt md note] + ShortOpts = 'hgo:l:vt:m:n:c'; // help gnome3 open lang ver import-[txt md note] { If something on commandline means don't proceed, ret True } function CommandLineError(inCommingError : string = '') : boolean; @@ -95,6 +97,7 @@ function CommandLineError(inCommingError : string = '') : boolean; debugln(' --dark-theme ' + 'Does not work for GTK2'); debugln(' -l --lang=CCode ' + rsHelpLang); // syntax depends on bugfix https://bugs.freepascal.org/view.php?id=35432 debugln(' -h --help ' + rsHelpHelp); + debugln(' -c ' + 'Create new note'); // ToDo : make rsHelpCreate debugln(' --version ' + rsHelpVersion); debugln(' --no-splash ' + rsHelpNoSplash); debugln(' --debug-sync ' + rsHelpDebugSync); @@ -277,6 +280,9 @@ function Import_Text_MD_File(MD : boolean; FFName : string = '') : string; end; + // Looks to see if user just wants some command line activity, returns + // false if GUI is not needed. + function ContinueToGUI() : boolean ; begin if CommandLineError() then exit(False); @@ -296,14 +302,21 @@ function ContinueToGUI() : boolean ; Import_Note(); exit(False); end; + if Application.HasOption('c', 'create-note') then begin + if CanSendMessage('CREATENOTE') then + exit(false) // no GUI needed, just tell existing one to open a new note + else + OpenNewNotePlease := True; // mainunit FormShow() will look there to see if it got a new note request at startup + end; // applies only when user uses -c and -ng is not already running + // Note that the useappind option is processed in the LPR file. - if HaveCMDParam() then + if HaveCMDParam() then // Only command line parameter is filename of a Single Note if SingleNoteName = '' then exit(False) // thats an error, more than one parameter - else exit(True); // proceed in SNM + else exit(True); // proceed in SNM, we set its File Name further up. // Looks like a normal startup - if CanSendMessage('SHOWSEARCH') then exit(False); + if CanSendMessage('SHOWSEARCH') then exit(False); // will fail if -ng is not already running. Result := true; end; @@ -314,8 +327,9 @@ initialization 'debug-sync', 'debug-index', 'debug-spell', 'config-dir:', 'open-note:', 'save-exit', // -o for open also legal. save-exit is legecy 'import-txt:', 'import-md:', 'import-note:', // -t, -m -n respectivly - 'title-fname', 'gnome3', 'useappind:', // -g and gnome3 is legal but legacy, ignored. - 'strict-theme', // Strict-theme applies to only Qt versions - 'allow-leftclick'); // overrule wayland decision to use only right click + 'title-fname', 'gnome3', 'useappind:', // -g and gnome3 is legal but legacy, ignored. + 'strict-theme', // Strict-theme applies to only Qt versions + 'allow-leftclick', // overrule wayland decision to use only right click + 'create-note'); // create a new note (-ng open or not), added post 0.41 end. diff --git a/source/editbox.pas b/source/editbox.pas index 0a920db..a5d0615 100644 --- a/source/editbox.pas +++ b/source/editbox.pas @@ -251,6 +251,7 @@ 2024/06/07 UTF8 bug, where missed UTF8 char ahead of file link. 2024/10/05 Made DeletingThisNote public so SearchForm can delete an Open note. 2024/10/16 Fixed the way that Save on Quit works, no contention ! + 2024/12/24 Altered Indent to work (a little) like Tomboy, embedded Tab #9 char at start line } @@ -4123,14 +4124,51 @@ procedure TEditBoxForm.KMemo1Click(Sender: TObject); // debugln('Mouseclick ' + inttostr(kmemo1.RealSelStart)); end; + procedure TEditBoxForm.KMemo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var - ABlock : TKMemoBlock; - ABlockNo, LocIndex : integer; + ABlock : TKMemoParagraph; + ABlockNo : integer; + + // returns the para block that controls text the cursor is on right now + function GetParagraphBlock(NotTitle : boolean) : TKMemoParagraph; + var + ABlockNo : integer = -1; + LocIndex : integer; + begin + ABlockNo := Kmemo1.Blocks.IndexToBlockIndex(KMemo1.Blocks.RealSelStart, LocIndex); + if (ABlockNo < 1) and NotTitle then + exit(Nil); // Dont mess with title + if KMemo1.Blocks[ABlockNo].ClassNameIs('TKMemoParagraph') then // if Ablockno is a para, use it, else we look for one further on + Result := TKMemoParagraph(KMemo1.Blocks[ABlockNo]) // works if cursor is just beyond last char in line + else Result := Kmemo1.Blocks.GetNearestParagraphBlock(ABlockNo); // Gets the following one, not the 'nearest' ! + end; + + (* function GetParagraphIndex(NotTitle : boolean) : integer; + var + LocIndex : integer; + begin + result := Kmemo1.Blocks.IndexToBlockIndex(KMemo1.Blocks.RealSelStart, LocIndex); + if (result < 1) and NotTitle then + exit(-1); + if not KMemo1.Blocks[Result].ClassNameIs('TKMemoParagraph') then + Result := Kmemo1.Blocks.GetNearestParagraphBlockIndex(result); + end; *) + + procedure IndentControl(IncreaseIndent : Boolean); // Note : at present, only one indent can be set + begin + ABlock := GetParagraphBlock(True); + if ABlock <> nil then // if zero cannot be a bullet nor indent + if (ABlock.ParaStyle.LeftPadding = 0) then // ToDo : one day, multilevel indent ?? + ABlock.ParaStyle.LeftPadding := IndentWidth; // if left padding is set, don't do bullet + Key := 0; + exit(); + end; - // ret T if it used the BS to remove an Indent. Will also 'prepare' a non-indented - // para to be merged, by KMemo, with a previous indented one. AnyPosInPara - // means we were called by Shift-Tab meaning Cursor does not need be on first char. + // ret T if it used the BS to remove an Indent. Will also 'prepare' a non-indented + // para to be merged, by KMemo, with a previous indented one. AnyPosInPara + // means we were called by Shift-Tab meaning Cursor does not need be on first char, + // it could be on first to just after the last. function RemoveIndent(AnyPosInPara : boolean = false) : boolean; var ABlock : TKMemoBlock; @@ -4139,28 +4177,45 @@ procedure TEditBoxForm.KMemo1KeyDown(Sender: TObject; var Key: Word; Shift: TShi Result := False; ABlockNo := Kmemo1.Blocks.IndexToBlockIndex(KMemo1.Blocks.RealSelStart, LocIndex); // LocIndex not certain to be in left most block. if ABlockNo < 2 then exit; + if not AnyPosInPara // AnyPosInPara means being on first char does not matter - and (not KMemo1.Blocks[ABlockNo-1].ClassNameIs('TKMemoParagraph')) then exit; // was not first block in para. + and (not KMemo1.Blocks[ABlockNo-1].ClassNameIs('TKMemoParagraph')) then exit; // was not first block in para so BS not removing indent ABlock := Nil; - ABlock := Kmemo1.Blocks.GetNearestParagraphBlock(ABlockNo); // Gets the following one, not the nearest ! + + if KMemo1.Blocks[ABlockNo].ClassNameIs('TKMemoParagraph') then // if Ablockno is a para, use it, else we look for one further on + ABlock := KMemo1.Blocks[ABlockNo] + else ABlock := Kmemo1.Blocks.GetNearestParagraphBlock(ABlockNo); // Gets the following one, not the 'nearest' ! if ABlock = Nil then exit; - if TKMemoParagraph(ABlock).Numbering <> pnuNone then exit; // Bullets are not my job + + if TKMemoParagraph(ABlock).Numbering <> pnuNone then begin // Its a bullet. We reduce bullet or Indent + if AnyPosInPara then BulletControl(False); // don't do this here if called as part of BS keystroke + exit; + end; // deal with a backspace from first char of an indented para. if (TKMemoParagraph(ABlock).ParaStyle.LeftPadding > 0) // Has padding, might be Indent - and (not KMemo1.Blocks[ABlockNo].ClassNameIs('TKMemoParagraph')) // +// and (not KMemo1.Blocks[ABlockNo].ClassNameIs('TKMemoParagraph')) // // ?????????????? and (AnyPosInPara or (LocIndex = 0)) then begin // and char position OK, must delete indent TKMemoParagraph(ABlock).ParaStyle.LeftPadding := 0; + writeln('RemoveIndent() left padding set to 0'); exit(true); end; // Deal a para being merged with a previous, indented one. Just indent current one and let KMemo handle it. + +// if (LocIndex = 0) +// and KMemo1.Blocks[ABlockNo-1].ClassNameIs('TKMemoParagraph') + if (LocIndex = 0) // this part only applies if first char of block + and KMemo1.Blocks[ABlockNo-1].ClassNameIs('TKMemoParagraph') and (TKMemoParagraph(KMemo1.Blocks[ABlockNo-1]).ParaStyle.LeftPadding > 0) and (TKMemoParagraph(KMemo1.Blocks[ABlockNo-1]).Numbering = pnuNone) then TKMemoParagraph(ABlock).ParaStyle.LeftPadding := IndentWidth; // BS will go through to kmemo who will do merge end; + + + begin if not Ready then begin // Will this help with issue #279 if [ssCtrl] = shift then @@ -4180,7 +4235,7 @@ procedure TEditBoxForm.KMemo1KeyDown(Sender: TObject; var Key: Word; Shift: TShi exit; end; if ([ssAlt, ssShift] = Shift) and ((Key = VK_RIGHT) or (Key = VK_LEFT)) then exit; // KMemo - extend selection one word left or right - {$endif} + {$endif DARWIN} if (Key = VK_ESCAPE) and Sett.CheckEscClosesNote.Checked then close; // Will do normal save stuff first. @@ -4203,7 +4258,7 @@ procedure TEditBoxForm.KMemo1KeyDown(Sender: TObject; var Key: Word; Shift: TShi Key := 0; exit(); end; - if (Key = VK_TAB) then begin + if (Key = VK_TAB) then begin // Shift-Tab, maybe anywhere in a line, first to last char. RemoveIndent(True); Key := 0; exit(); @@ -4239,6 +4294,7 @@ procedure TEditBoxForm.KMemo1KeyDown(Sender: TObject; var Key: Word; Shift: TShi VK_M : begin Key := 0; DoRightClickMenu; end; VK_N : SearchForm.OpenNote(''); VK_E : InitiateCalc(); + VK_TAB : IndentControl(True); VK_F4 : close; // close just this note, normal saving will take place VK_C, VK_A, VK_HOME, VK_END, VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_PRIOR, VK_NEXT, VK_INSERT : exit; end; @@ -4277,26 +4333,23 @@ procedure TEditBoxForm.KMemo1KeyDown(Sender: TObject; var Key: Word; Shift: TShi exit(); end; - if Key = VK_TAB then begin // A Tab insets paragraph - ABlockNo := Kmemo1.Blocks.IndexToBlockIndex(KMemo1.Blocks.RealSelStart, LocIndex); - if ABlockNo > 1 then begin // don't mess with title - ABlock := Nil; - ABlock := Kmemo1.Blocks.GetNearestParagraphBlock(ABlockNo); - if (ABlock <> Nil) {and ABlock.ClassNameIs('TKMemoParagraph') } // Might be nil if no para marker at end of content - and (TKMemoParagraph(ABlock).Numbering = pnuNone) then // Don't mix Indent with Bullets - TKMemoParagraph(ABlock).ParaStyle.LeftPadding := IndentWidth; - Key := 0; // Don't let go through to KMemo - MarkDirty(); - exit; - end; + if Key = VK_TAB then begin // A Tab insets paragraph + // Tab key sets a bullet or extends that bullet further right. + // Maybe, one day it will also extend Insert too. + ABlock := GetParagraphBlock(True); + if ABlock <> nil then + if (ABlock.ParaStyle.LeftPadding = 0) or (ABlock.Numbering <> pnuNone) then // ToDo : one day, multilevel indent ?? + BulletControl(True); // if left padding is set, don't do bullet + Key := 0; + exit(); end; if Key = VK_F3 then begin key := 0; if (EditFind.Text <> rsMenuSearch) then SpeedRightClick(self); end; - if Key <> 8 then exit(); // ======== We are watching for a BS on a Bullet OR Indent Marker ======== - if RemoveIndent() then begin + if Key <> 8 then exit(); // ======== We are watching for a BS on a Bullet ======== + if RemoveIndent(False) then begin if Verbose then debugln('Removed an Indent.'); Key := 0; MarkDirty(); diff --git a/source/loadnote.pas b/source/loadnote.pas index 9c43f36..7ecbca0 100644 --- a/source/loadnote.pas +++ b/source/loadnote.pas @@ -39,6 +39,7 @@ doing it here but blocks do not always report the correct color when asked. 2023/03/11 Allow Qt to set Text and Background colour, force Gray for Inactive Background cos Kmemo get it wrong 2024/01/23 Added support for Indent + 2024/12/24 Altered Indent to work (a little) like Tomboy, embedded Tab #9 char at start line } {$mode objfpc}{$H+} @@ -63,7 +64,10 @@ TBLoadNote = class Underline : boolean; Strikeout : boolean; FixedWidth : boolean; + TabCount : integer; +(* {$ifdef DOINDENT} Indent : boolean; + {$endif} *) //InBullet, BulletOwing : boolean; BulletLevel : integer; InStr : ANSIString; @@ -79,7 +83,7 @@ TBLoadNote = class vars (ie Bold, Strikeout) tell it about the active styles at present. This method adds one textblock (or possibly parablock) from InStr to the kmemo. It gets called when LoadFile() encounters a newline or the start of a Tag.} - procedure AddText(AddPara : Boolean); + procedure AddText(AddPara : Boolean; Tabs : integer = 0); { called when ReadTag encounters a , process through to corresponding including any intermediat pairs. Ignores any newlines in content during @@ -115,11 +119,18 @@ implementation TB_Utils, LazLogger; +{$define DEBUGMODE} + +// if the first InStr character after a paragraph block is a tab, set inset. +// drop tab that appear elsewhere on the floor. + procedure TBLoadNote.LoadFile(FileName : ANSIString; RM : TKMemo); var fs : TFileStream; ch : char = ' '; Blocks : longint = 0; + AcceptTab : boolean = false; // only true after a para, before anything else is added to InStr + begin KM := RM; FirstTime := True; @@ -128,20 +139,34 @@ procedure TBLoadNote.LoadFile(FileName : ANSIString; RM : TKMemo); while fs.Position < fs.Size do begin fs.read(ch, 1); if Ch = #13 then fs.read(ch, 1); // drop #13 on floor. Silly Windows double newline. - if Ch = #9 then Ch := ' '; // Tabs, as characters, are not allowed. + if (Ch = #9) then + if AcceptTab then begin + inc(TabCount); // Will use that to create para indent + {$ifdef DEBUGMODE}writeln('TBLoadNote.LoadFile - loaded a tab with Indent');{$endif} + continue; + end + else Ch := ' '; // convert to space, we only take leading Tabs seriously ! + + +// if Ch = #9 then Ch := ' '; // Tabs, as characters, are not allowed. // come in via pasted text, better fix during the paste process. // This might mess with UTF8 ?? if (Ch = '<') or (Ch < ' ') then begin // start of tag or ctrl char - if (Ch < ' ') then // thats a newline (other ctrl ? drop on floor) - AddText(True) // flush through to kMemo, new paragraph + if (Ch < ' ') then begin // thats a newline (other ctrl ? drop on floor) + AddText(True, TabCount); // flush through to kMemo, new paragraph + TabCount := 0; + AcceptTab := True; + end else begin AddText(false); // flush through to kmemo ReadTag(fs); // deals with _only_ tag unless its a list tag ! end; inc(Blocks); InStr := ''; // AddText does that ???? Maybe not in every case ? - end else + end else begin InStr := InStr + ch; + if AcceptTab then AcceptTab := false; + end; end; finally FreeAndNil(fs); @@ -150,7 +175,7 @@ procedure TBLoadNote.LoadFile(FileName : ANSIString; RM : TKMemo); end; -procedure TBLoadNote.AddText(AddPara : Boolean); +procedure TBLoadNote.AddText(AddPara : Boolean; Tabs : integer = 0); var FT : TFont; PB : TKMemoParagraph; @@ -191,7 +216,13 @@ procedure TBLoadNote.AddText(AddPara : Boolean); if AddPara then begin PB := KM.Blocks.AddParagraph; if not FirstTime then - AddIndentBullets(PB); // only does stuff if necessary + if Tabs > 0 then begin + {$ifdef DEBUGMODE}writeln('TBLoadNote.AddText - recorded tabs into kmemo');{$endif} + PB.ParaStyle.LeftPadding := Tabs * IndentWidth; + BulletLevel := 0; // Maybe a legacy note has both Indent AND Bullet ??? + end + else + AddIndentBullets(PB); // only does stuff if necessary if FirstTime then begin FirstTime := false; KM.Blocks.DeleteEOL(0); @@ -250,17 +281,19 @@ procedure TBLoadNote.AddIndentBullets(PB : TKMemoParagraph); PB.NumberingListLevel.FirstIndent := -20; // Note, these numbers need match SettBullet() in editbox PB.NumberingListLevel.LeftIndent := 30; {$endif} - end else // end of processing Bullet + end +(* else // we don't indent like this anymore if Indent then begin PB.ParaStyle.LeftPadding := IndentWidth; Indent := False; - end; + end *) + ; end; procedure TBLoadNote.ActOnTag(buff : string); begin case Buff of - 'indent' : Indent := true; + 'indent' : TabCount := 1; // legacy, whould come from a 0.40 to 0.41 version -ng 'note-content' : InContent := true; '/note-content' : InContent := false; 'bold' : Bold := True; diff --git a/source/mainunit.pas b/source/mainunit.pas index bf552ec..b5802a8 100644 --- a/source/mainunit.pas +++ b/source/mainunit.pas @@ -395,7 +395,7 @@ procedure TMainForm.FormDestroy(Sender: TObject); end; procedure TMainForm.CommMessageReceived(Sender : TObject); -Var +Var // CREATENOTE - REINDEX: - SHOWSEARCH S : String; begin // debugln('Here in Main.CommMessageRecieved, a message was received'); @@ -406,10 +406,13 @@ procedure TMainForm.CommMessageReceived(Sender : TObject); SearchForm.Show; // this creates a notable flicker, might be necessary //SearchForm.MoveWindowHere(SearchForm.Caption); end else - if S.StartsWith('REINDEX') then - SearchForm.IndexNewNote(copy(S, 9, 100), False) - else debugln('TMainForm.CommMessageReceived - invalid message [' + S + ']'); - // eg REINDEX:48480CC5-EC3E-4AA0-8C83-62886DB291FD.note + if S = 'CREATENOTE' then begin + SearchForm.OpenNote(''); // create new note + end else + if S.StartsWith('REINDEX') then + SearchForm.IndexNewNote(copy(S, 9, 100), False) + else debugln('TMainForm.CommMessageReceived - invalid message [' + S + ']'); + // eg REINDEX:48480CC5-EC3E-4AA0-8C83-62886DB291FD.note end; procedure TMainForm.StartIPCServer(); @@ -659,7 +662,10 @@ procedure TMainForm.FormShow(Sender: TObject); FormResize(self); // Qt5 apparently does not call FormResize at startup. if ButtSysTrayHelp.Visible then debugln('You cannot see me'); if ButtSysTrayHelp.Visible then debugln('On Gnome, install gnome-shell-extension-appindicator, logout, logon and start tomboy-ng again, "yes" to prompt.'); - + if OpenNewNotePlease then begin + OpenNewNotePlease := False; + SearchForm.OpenNote(''); + end; end; procedure TMainForm.ImageAboutLazClick(Sender: TObject); diff --git a/source/notenormal.pas b/source/notenormal.pas index 78ae32e..97240b2 100644 --- a/source/notenormal.pas +++ b/source/notenormal.pas @@ -22,6 +22,7 @@ 2021/08/19 Bug in RemoveRedundentTags that sometimes ate character after tag pair 2021/09/21 Added code to convert blocks of monospace to to now have each para wrapped. 2022/11/09 Remove any ctrl char (ie < 32) except #10 and #13, don't know its necessary but #279 + 2024/12/26 Added Tab, #9 to allowed list. Should only allow at the start of line but seems OK } @@ -295,6 +296,7 @@ procedure TNoteNormaliser.NormaliseList(STL : TStringList); ChangedLine := False; // Not a UTF8 issue, no byte in a multibyte UTF8 'set' can be lower than 128 while ChIndex <= length(TempSt) do begin if (ord(TempSt[ChIndex]) < 32) + and (ord(TempSt[ChIndex]) <> 9) // Tab, we now have to allow Tabs in the text, only interested in ones at start of line. and (ord(TempSt[ChIndex]) <> 10) and (ord(TempSt[ChIndex]) <> 13) then begin //debugln('Removing char ' + ord(TempSt[ChIndex]).ToString); // Carefull, causes memory leak when run in thread diff --git a/source/savenote.pas b/source/savenote.pas index cabb441..44b3c91 100644 --- a/source/savenote.pas +++ b/source/savenote.pas @@ -70,10 +70,14 @@ 2021/11/04 SaveNewTemplate now gets a current date stamp. 2024/01/23 Added support for Indent 2024/04/14 Stop underline appearing with text from a hyperlink block + 2024/12/24 Altered Indent to work (a little) like Tomboy, embedded Tab #9 char at start line } {$mode objfpc}{$H+} +{X$DEFINE DEBUGMODE} // think we will do away with Indent, its seriously messy. + // This define exists in EditBox, SaveNote, LoadNote + interface uses @@ -126,6 +130,7 @@ TBSaveNote = class tags accordingly. Special case when CloseOnly is true, we terminate all active styles and reactivate them (NoteNormal will move the reactivated tags to next line later). Absolutly vital that tag order be observed, crossed ove r tgas are a very bad thing.} + procedure AddIndent(BlkNo : integer; var Buf : string); function AddTag(const FT: TKMemoTextBlock; var Buff: ANSIString; CloseOnly: boolean = False; IsLink: boolean = false ): ANSIString; @@ -478,9 +483,11 @@ procedure TBSaveNote.BulletList(Level : TKMemoParaNumbering; var Buff : ANSIStri writeln('EndEnd [' + EndEndSt + ']'); } Buff := StartEndSt + Buff + EndStartSt; +(* {$ifdef DOINDENT} if Level = pnuNone then Buff := '' + Buff + '' // Indent is only ever the one level. - else begin // OK, do the bullet stuff + else{$endif} *) + begin // OK, do the bullet stuff case Level of BulletOne : iLevel := 1; BulletTwo : iLevel := 2; @@ -567,6 +574,21 @@ procedure TBSaveNote.CopyLastFontAttr(); PrevFSize := FSize; end; +procedure TBSaveNote.AddIndent(BlkNo : integer; var Buf : string); +var Indents : integer; +begin + if KM.Blocks[BlkNo].ClassNameIs('TKMemoParagraph') then begin + if TKMemoParagraph(KM.Blocks[BlkNo]).ParaStyle.LeftPadding <> 0 then begin + Indents := TKMemoParagraph(KM.Blocks[BlkNo]).ParaStyle.LeftPadding; + while Indents > 0 do begin + Buf := #9 + Buf; + dec(Indents, IndentWidth); + end; + {$ifdef DEBUGMODE}writeln('TBSaveNote.AddIndent Buf=', Buf, ']');{$endif} + end; + end else debugln('TBSaveNote.AddIndent - Warning, passed a non para block no'); +end; + // NEW : if passed a created StringList, we write to the list rather than to the // Memory Buffer. Still need to deal with Header and Footer in a line by line mode. procedure TBSaveNote.ReadKMemo(FileName : ANSIString; Title : string; KM1 : TKMemo; STL : TStringList = nil); @@ -633,7 +655,7 @@ procedure TBSaveNote.ReadKMemo(FileName : ANSIString; Title : string; KM1 : TKMe BulletList(TKMemoParagraph(KM1.Blocks.Items[BlockNo]).Numbering, Buff) else if TKMemoParagraph(KM1.Blocks.Items[BlockNo]).ParaStyle.LeftPadding > 0 then - BulletList(pnuNone, Buff); // Indent + AddIndent(BlockNo, Buff); // Indent {if TKMemoParagraph(KM1.Blocks.Items[BlockNo]).Numbering = pnuBullets then BulletList(Buff); } @@ -656,6 +678,7 @@ procedure TBSaveNote.ReadKMemo(FileName : ANSIString; Title : string; KM1 : TKMe Buff := Buff + LineEnding; OutStream.Write(Buff[1], length(Buff)) end else STL.Add(Buff); + {$ifdef DEBUGMODE}writeln('TBSaveNote.ReadKMemo Buff=[', Buff, ']');{$endif} Buff := ''; // debugln('Block=' + inttostr(BlockNo) + ' ' +BlockAttributes(KM1.Blocks.Items[BlockNo])); inc(BlockNo); diff --git a/source/trans.pas b/source/trans.pas index b10c1ad..5bb6e63 100644 --- a/source/trans.pas +++ b/source/trans.pas @@ -28,7 +28,7 @@ interface { TTomboyTrans } - TTomboyTrans = class // An abstract class, parent of eg FileTrans and Githun Trans + TTomboyTrans = class // An abstract class, parent of eg FileTrans and Github Trans private public diff --git a/source/transgithub.pas b/source/transgithub.pas index f4fb4c8..0db2a9e 100644 --- a/source/transgithub.pas +++ b/source/transgithub.pas @@ -607,10 +607,10 @@ function TGithubSync.TestTransport(const WriteNewServerID : boolean ErrorString := ExtractJSONField(ST, 'login'); if ErrorString = UserName then begin // "A" valid username ErrorString := ''; - TokenExpires := HeaderOut; + TokenExpires := HeaderOut; // this was set in DownLoader to returned header item matching "github-authentication-token-expiration" if DebugMode then debugln('TGithubSync.TestTransport - Confirmed account exists'); if TokenExpires = '' then begin - ErrorString := 'Username exists but Token Failure'; + ErrorString := 'Username exists but Token Failure'; // we did not get back an expiry date from DownLoader() exit(SyncCredentialError); // Token failure end; // If to here, we have a valid username and a valid Password but don't know if they work together @@ -1198,9 +1198,9 @@ function TGithubSync.SendFile(RemoteFName : string; STL : TstringList) : boolean Result := False; repeat - if pos('1D65A2EC-3C63-4732-8F9E-73E2A4544BC5', RemoteFName) > 0 then +{ if pos('1D65A2EC-3C63-4732-8F9E-73E2A4544BC5', RemoteFName) > 0 then ErrorString := ' ***** fakeing upload failure *****' - else + else } Result := SendData(ContentsURL(True) + '/' + RemoteFName, BodyStr, true, RemoteFName); if Result then break; @@ -1551,9 +1551,24 @@ function TGithubSync.Downloader(URL : string; out SomeString : String; end; with Client.ResponseHeaders do begin if Header <> '' then begin - if IndexOfName(Header) <> -1 then - HeaderOut := ValueFromIndex[IndexOfName(Header)] - else HeaderOut := ''; + + // if the required header is not found, we will look for another known one, X-RateLimit-Remaining + // if that is there set HeaderOut to 'unavailable' (that will appear in Sync Report) but if + // the second one fails, set HeaderOut to '' and that will abort sync + + if DebugMode then debugln('TGithubSync.Downloader - looking for a response header, ' + Header); // added post 0.41 + if DebugMode then begin + debugln('-------------------------------------'); + debugln(Client.ResponseHeaders.Text); + debugln('-------------------------------------'); + end; + if IndexOfName(Header) = -1 then + if IndexOfname('X-RateLimit-Remaining') = -1 then begin + HeaderOut := ''; // that will abort sync, we cannot have a valid header. + debugln('WARNING TGithubSync.Downloader failed to get valid header back from github'); + end else HeaderOut := 'unavailable' // Sync will proceed, token may not have an expiry date set, user's choice + else + HeaderOut := ValueFromIndex[IndexOfName(Header)]; // we found a valid expiry date. end; end; finally