Skip to content

Commit 46cb534

Browse files
committed
Merge remote-tracking branch 'origin/master' into vault
Brings vault up to date with the CodeSnip v4.24.2 code base. Resolved conflicts: * Rejected incoming changes from 'origin/master' in Src/VersionInfo.vi-inc * Manually resolved conflicts in Src/FrOverview.pas
2 parents 1a643e6 + 131d602 commit 46cb534

File tree

8 files changed

+135
-14
lines changed

8 files changed

+135
-14
lines changed

Diff for: CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ Releases are listed in reverse version number order.
66

77
> Note that _CodeSnip_ v4 was developed in parallel with v3 for a while. As a consequence some v3 releases have later release dates than early v4 releases.
88
9+
## Release v4.24.2 of 14 April 2025
10+
11+
Hotfix release.
12+
13+
* Updated bug fix implemented in v4.24.1 to avoid relying on a potentially problematic windows event [issue #70 (2nd attempt)].
14+
* Corrected release date error for v4.24.1 in `CHANGELOG.md`.
15+
16+
## Release v4.24.1 of 13 April 2025
17+
18+
* Fixed bug where CodeSnip occasionally crashes after a computer resumes from hibernation [issue #70].
19+
* Bumped some copyright dates for 2025.
20+
921
## Release v4.24.0 of 23 October 2024
1022

1123
* Compilers with which a snippet has not been tested are now omitted from snippet information that is copied to the clipboard and included in print outs [issue #143].

Diff for: Docs/License.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE HTML>
22

33
<!--
4-
* Copyright (C) 2012-2024, Peter Johnson (gravatar.com/delphidabbler).
4+
* Copyright (C) 2012-2025, Peter Johnson (gravatar.com/delphidabbler).
55
*
66
* CodeSnip license.
77
*
@@ -231,7 +231,7 @@ <h2>
231231
Executable Program
232232
</h2>
233233
<p>
234-
DelphiDabbler <em>CodeSnip</em> is copyright &copy; 2005-2024 by <a
234+
DelphiDabbler <em>CodeSnip</em> is copyright &copy; 2005-2025 by <a
235235
href="https://gravatar.com/delphidabbler"
236236
>Peter D Johnson</a>.
237237
</p>
@@ -1801,7 +1801,7 @@ <h2 id="ddab-exclusive">
18011801
</h2>
18021802

18031803
<p>
1804-
Files covered by this license are original work, copyright &copy; 2012-2024, <a href="https://gravatar.com/delphidabbler">Peter D Johnson</a>.
1804+
Files covered by this license are original work, copyright &copy; 2012-2025, <a href="https://gravatar.com/delphidabbler">Peter D Johnson</a>.
18051805
</p>
18061806

18071807
<p>

Diff for: Src/FmMain.pas

+21-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
44
* obtain one at https://mozilla.org/MPL/2.0/
55
*
6-
* Copyright (C) 2005-2024, Peter Johnson (gravatar.com/delphidabbler).
6+
* Copyright (C) 2005-2025, Peter Johnson (gravatar.com/delphidabbler).
77
*
88
* Application's main form. Handles the program's main window display and user
99
* interaction.
@@ -521,6 +521,12 @@ TMainForm = class(THelpAwareForm)
521521
/// <summary>Object that manages favourites.</summary>
522522
fFavouritesMgr: TFavouritesManager;
523523

524+
/// <summary>Handles the <c>WM_POWERBROADCAST</c> messages to detect and
525+
/// respond to hibernation messages.</summary>
526+
/// <remarks>!! HACK necessary as part of the fix for an obscure bug. See
527+
/// https://github.com/delphidabbler/codesnip/issues/70</remarks>
528+
procedure WMPowerBroadcast(var Msg: TMessage); message WM_POWERBROADCAST;
529+
524530
/// <summary>Displays view item given by TViewItemAction instance
525531
/// referenced by Sender and adds to history list.</summary>
526532
procedure ActViewItemExecute(Sender: TObject);
@@ -1345,7 +1351,6 @@ procedure TMainForm.FormDestroy(Sender: TObject);
13451351
// fStatusBarMgr MUST be nilled: otherwise it can be called after status bar
13461352
// control has been freed and so cause AV when trying to use the control
13471353
FreeAndNil(fStatusBarMgr);
1348-
13491354
end;
13501355

13511356
procedure TMainForm.FormResize(Sender: TObject);
@@ -1531,7 +1536,6 @@ procedure TMainForm.InitForm;
15311536
// Create object to handle compilation and assoicated UI and dialogues
15321537
fCompileMgr := TMainCompileMgr.Create(Self); // auto-freed
15331538

1534-
15351539
// Set event handler for snippets database
15361540
Database.AddChangeEventHandler(DBChangeHandler);
15371541

@@ -1599,5 +1603,19 @@ procedure TMainForm.splitVertCanResize(Sender: TObject;
15991603
Accept := False;
16001604
end;
16011605

1606+
procedure TMainForm.WMPowerBroadcast(var Msg: TMessage);
1607+
begin
1608+
// !! HACK
1609+
// Sometimes when the computer is resumed from hibernation the tree view in
1610+
// the overview frame is destroyed and recreated by Windows. Unfortunately the
1611+
// IView instances associated with the recreated tree nodes are lost.
1612+
// Attempting to read those (now nil) IView instances was resulting in an
1613+
// access violation.
1614+
case Msg.WParam of
1615+
PBT_APMSUSPEND:
1616+
fMainDisplayMgr._HACK_PrepareForHibernate;
1617+
end;
1618+
end;
1619+
16021620
end.
16031621

Diff for: Src/FrOverview.pas

+61-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
44
* obtain one at https://mozilla.org/MPL/2.0/
55
*
6-
* Copyright (C) 2005-2023, Peter Johnson (gravatar.com/delphidabbler).
6+
* Copyright (C) 2005-2025, Peter Johnson (gravatar.com/delphidabbler).
77
*
88
* Implements a titled frame that displays lists of snippets, arranged in
99
* different ways, and manages user interaction with the displayed items.
@@ -41,6 +41,29 @@ interface
4141

4242
type
4343

44+
// !! HACK
45+
// Horrible hack to expose CreateWnd for overiding TTreeView.CreateWnd for the
46+
// existing TTreeView component of TOverviewFrame. The hack avoids having to
47+
// remove the component and replacing it with a descendant class that is
48+
// manually constructed at run time.
49+
// This is here to enable the tree view to be recreated with correctly
50+
// instantiated TViewItemTreeNode nodes after Windows recreates the tree
51+
// behind the scenes after resuming from hibernation.
52+
// I am deeply ashamed of this hack.
53+
TTreeView = class(ComCtrls.TTreeView)
54+
strict private
55+
var
56+
_HACK_fOnAfterCreateNilViews: TNotifyEvent;
57+
protected
58+
procedure CreateWnd; override;
59+
public
60+
/// <summary>!! HACK. Event triggered after the inherited CreateWnd is
61+
/// called. Only called if the tree view has nil references to IView
62+
/// objects.</summary>
63+
property _HACK_OnAfterCreateNilViews: TNotifyEvent
64+
read _HACK_fOnAfterCreateNilViews write _HACK_fOnAfterCreateNilViews;
65+
end;
66+
4467
{
4568
TOverviewFrame:
4669
Titled frame that displays lists of snippets grouped in various ways and
@@ -105,6 +128,7 @@ TTVDraw = class(TSnippetsTVDraw)
105128
@return True if node is a section header, False if not.
106129
}
107130
end;
131+
108132
var
109133
fTVDraw: TTVDraw; // Object that renders tree view nodes
110134
fNotifier: INotifier; // Notifies app of user initiated events
@@ -232,6 +256,10 @@ TTVDraw = class(TSnippetsTVDraw)
232256
procedure RestoreTreeState;
233257
{Restores last saved treeview expansion state from memory.
234258
}
259+
/// <summary>!! HACK: Sets an event handler on the tree view to work
260+
/// around a bug that can occur after resuming from hibernation.</summary>
261+
/// <remarks>Method of IOverviewDisplayMgr.</remarks>
262+
procedure _HACK_SetHibernateHandler(const AHandler: TNotifyEvent);
235263
{ IPaneInfo }
236264
function IsInteractive: Boolean;
237265
{Checks if the pane is currently interactive with user.
@@ -975,6 +1003,12 @@ procedure TOverviewFrame.UpdateTreeState(const State: TTreeNodeAction);
9751003
end;
9761004
end;
9771005

1006+
procedure TOverviewFrame._HACK_SetHibernateHandler(
1007+
const AHandler: TNotifyEvent);
1008+
begin
1009+
tvSnippets._HACK_OnAfterCreateNilViews := AHandler;
1010+
end;
1011+
9781012
{ TOverviewFrame.TTVDraw }
9791013

9801014
function TOverviewFrame.TTVDraw.GetVaultID(const Node: TTreeNode): TVaultID;
@@ -984,7 +1018,7 @@ function TOverviewFrame.TTVDraw.GetVaultID(const Node: TTreeNode): TVaultID;
9841018
begin
9851019
// TODO -cBug: Exception reported as issue #70 could have moved here
9861020
ViewItem := (Node as TViewItemTreeNode).ViewItem;
987-
if Supports(ViewItem, ISnippetView, SnippetView) then
1021+
if Assigned(ViewItem) and Supports(ViewItem, ISnippetView, SnippetView) then
9881022
Result := SnippetView.Snippet.VaultID
9891023
else
9901024
Result := TVaultID.CreateNull;
@@ -1000,7 +1034,31 @@ function TOverviewFrame.TTVDraw.IsSectionHeadNode(
10001034
ViewItem: IView; // view item represented by node
10011035
begin
10021036
ViewItem := (Node as TViewItemTreeNode).ViewItem;
1003-
Result := ViewItem.IsGrouping;
1037+
// Workaround for possibility that ViewItem might be nil when restarting after
1038+
// hibernation.
1039+
if Assigned(ViewItem) then
1040+
Result := ViewItem.IsGrouping
1041+
else
1042+
Result := False;
1043+
end;
1044+
1045+
{ TTreeView }
1046+
1047+
procedure TTreeView.CreateWnd;
1048+
var
1049+
HasNilViews: Boolean;
1050+
Node: TTreeNode;
1051+
begin
1052+
inherited;
1053+
HasNilViews := False;
1054+
for Node in Items do
1055+
begin
1056+
HasNilViews := not Assigned((Node as TViewItemTreeNode).ViewItem);
1057+
if HasNilViews then
1058+
Break;
1059+
end;
1060+
if HasNilViews and Assigned(_HACK_fOnAfterCreateNilViews) then
1061+
_HACK_fOnAfterCreateNilViews(Self);
10041062
end;
10051063

10061064
end.

Diff for: Src/Help/HTML/license.htm

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
55
* obtain one at https://mozilla.org/MPL/2.0/
66
*
7-
* Copyright (C) 2012-2024, Peter Johnson (gravatar.com/delphidabbler).
7+
* Copyright (C) 2012-2025, Peter Johnson (gravatar.com/delphidabbler).
88
*
99
* Help topic containing summary of CodeSnip license.
1010
-->
@@ -27,7 +27,7 @@ <h1>
2727
<a name="license"></a>Summary of End User License Agreement
2828
</h1>
2929
<p>
30-
DelphiDabbler <em>CodeSnip</em> is copyright &copy; 2005-2024 by Peter D
30+
DelphiDabbler <em>CodeSnip</em> is copyright &copy; 2005-2025 by Peter D
3131
Johnson, <a
3232
href="https://gravatar.com/delphidabbler"
3333
class="weblink"

Diff for: Src/Install/Assets/License.rtf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deftab709{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
22
{\colortbl ;\red0\green0\blue255;}
33
{\*\generator Riched20 10.0.18362}\viewkind4\uc1
4-
\pard\sa113\f0\fs18\lang1033 DelphiDabbler CodeSnip is copyright \'a9 2005-2024 by Peter D Johnson, {{\field{\*\fldinst{HYPERLINK https://en.gravatar.com/delphidabbler }}{\fldrslt{https://en.gravatar.com/delphidabbler\ul0\cf0}}}}\f0\fs18 . \par
4+
\pard\sa113\f0\fs18\lang1033 DelphiDabbler CodeSnip is copyright \'a9 2005-2025 by Peter D Johnson, {{\field{\*\fldinst{HYPERLINK https://en.gravatar.com/delphidabbler }}{\fldrslt{https://en.gravatar.com/delphidabbler\ul0\cf0}}}}\f0\fs18 . \par
55
The executable version of CodeSnip is made available under the terms of the Mozilla Public License 2.0 ({{\field{\*\fldinst{HYPERLINK https://www.mozilla.org/MPL/2.0/ }}{\fldrslt{https://www.mozilla.org/MPL/2.0/\ul0\cf0}}}}\f0\fs18 ). This means you can use, copy and distribute CodeSnip as you wish.\par
66
You may also modify CodeSnip as you wish and you may distribute copies of your modified version under the terms of the Mozilla Public License. The only exception is that you may not use the CodeSnip name or branding (e.g. the program icon) in any modification you distribute unless you have the explicit permission of the copyright holder. \par
77
For full information see the file \i License.html\i0 installed with this program.\fs24\lang2057\par

Diff for: Src/IntfFrameMgrs.pas

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
44
* obtain one at https://mozilla.org/MPL/2.0/
55
*
6-
* Copyright (C) 2005-2021, Peter Johnson (gravatar.com/delphidabbler).
6+
* Copyright (C) 2005-2025, Peter Johnson (gravatar.com/delphidabbler).
77
*
88
* Declares interfaces, constants and enumerations required to manage various
99
* parts of CodeSnip's UI.
@@ -19,6 +19,7 @@ interface
1919
uses
2020
// Delphi
2121
SHDocVw, ActiveX,
22+
Classes, // !! For HACK
2223
// Project
2324
Browser.IntfDocHostUI,
2425
DB.Snippets,
@@ -149,6 +150,9 @@ interface
149150
/// <summary>Restore expand / collapse state of treeview to last save
150151
/// state.</summary>
151152
procedure RestoreTreeState;
153+
/// <summary>!! HACK: Sets an event handler on the tree view to work
154+
/// around a bug that can occur after resuming from hibernation.</summary>
155+
procedure _HACK_SetHibernateHandler(const AHandler: TNotifyEvent);
152156
end;
153157

154158
type

Diff for: Src/UMainDisplayMgr.pas

+30-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
44
* obtain one at https://mozilla.org/MPL/2.0/
55
*
6-
* Copyright (C) 2005-2021, Peter Johnson (gravatar.com/delphidabbler).
6+
* Copyright (C) 2005-2025, Peter Johnson (gravatar.com/delphidabbler).
77
*
88
* Class that manages and co-ordinates the display of the program's main UI.
99
* Calls into subsidiary manager objects to perform display operations.
@@ -165,6 +165,11 @@ TMainDisplayMgr = class(TObject)
165165
procedure DisplayViewItem(ViewItem: IView; Mode: TDetailPageDisplayMode);
166166
overload;
167167

168+
/// <summary>!! HACK event handle to redisplay the overview pane treeview.
169+
/// Called only if Windows has mysteriously recreated the treeview and lost
170+
/// necessary object references.</summary>
171+
procedure _HACK_HibernateHandler(Sender: TObject);
172+
168173
public
169174
/// <summary>Object contructor. Sets up object to work with given frame
170175
/// manager objects.</summary>
@@ -291,6 +296,14 @@ TMainDisplayMgr = class(TObject)
291296

292297
/// <summary>Prepares display ready for database to be reloaded.</summary>
293298
procedure PrepareForDBReload;
299+
300+
/// <summary>!!HACK: gets the overview frame prepared for program
301+
/// hibernation.</summary>
302+
/// <remarks>Saves the overview tree view state ready for restoring after
303+
/// hibernation if Windows has recreated the overview pane's treeview,
304+
/// losing necessary IView object references..</remarks>
305+
procedure _HACK_PrepareForHibernate;
306+
294307
end;
295308

296309

@@ -693,5 +706,21 @@ procedure TMainDisplayMgr.UpdateOverviewTreeState(const State: TTreeNodeAction);
693706
(fOverviewMgr as IOverviewDisplayMgr).UpdateTreeState(State);
694707
end;
695708

709+
procedure TMainDisplayMgr._HACK_HibernateHandler(Sender: TObject);
710+
begin
711+
(fOverviewMgr as IOverviewDisplayMgr).Display(Query.Selection, True);
712+
(fOverviewMgr as IOverviewDisplayMgr).RestoreTreeState;
713+
// disable this handler until next resume from hibernation
714+
(fOverviewMgr as IOverviewDisplayMgr)._HACK_SetHibernateHandler(nil);
715+
end;
716+
717+
procedure TMainDisplayMgr._HACK_PrepareForHibernate;
718+
begin
719+
(fOverviewMgr as IOverviewDisplayMgr).SaveTreeState;
720+
(fOverviewMgr as IOverviewDisplayMgr)._HACK_SetHibernateHandler(
721+
_HACK_HibernateHandler
722+
);
723+
end;
724+
696725
end.
697726

0 commit comments

Comments
 (0)