Age | Commit message (Collapse) | Author |
|
|
|
Some of the checks are likely redundant, but the Windows API
documentation rarely makes it clear WHICH errors may be returned (and
under which circumstances) rather than simply WHETHER errors may be
returned (under any circumstances, including those that do not apply
in the given case).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Speaking of unclear documentation, it is not obvious whether it is
necessary for programs calling into Prolog to manually mark and
release strings. I suppose that it should be, if the same logic that
applies to terms apply to strings.
On the other hand, the stack in which the strings are stored belongs
to Prolog, and there is nothing that would prevent Prolog from
cleaning up the strings when called at a later time. I am not sure.
But better safe than sorry, I guess.
The Mark class acts like the Frame class. The constructor and
destructor are equivalent to the PL_STRINGS_MARK and
PL_STRINGS_RELEASE macros.
Unlike for 34c3280, I did not notice any differences in memory usage
after this change. Perhaps that is because it has no effect; perhaps
it is because Prolog's stack is very big.
|
|
Apparently foreign frames ARE needed when calling Prolog from C. The
official documentation is very terse and could make this clearer.
To summarize, whenever a term is created (e.g., PL_new_term_refs), its
reference count is increased by one. It is garbage-collected when its
reference count hits zero. But the reference count is never decreased
unless (a) control returns to Prolog after executing a foreign
predicate -- which does not happen in my application -- or (b) the
foreign frame in which the term was created is closed.
In other words, terms must be created within a foreign frame. This is
achieved by initializing a Frame object before creating the term and
destroying it once the term has served its purpose.
The destructor for Frame does not DISCARD the frame, only CLOSE it.
The former would also invalidate all data bound by the terms, which is
usually undesirable.
|
|
|
|
It isn't really more safe, but it removes the need for a confusing
function pointer cast, which is easy to get wrong. As far as the
compiler is concerned, the result is literally the same, but it does
force the caller to (indirectly, via the template parameter) cast the
return value, which may be a good thing.
|
|
|
|
|
|
|
|
|
|
|
|
PL_new_atom(_wchars) creates an atom with a reference count of one,
which is never decreased, and the atom is thus never garbage
collected.
|
|
Apparently, = {0} does not zero a structure in C++.
|
|
|
|
f(void) is a C-ism that is valid but unnecessary in C++.
|
|
A getter offers encapsulation, but it is also less transparent in a
sense. Thinking of ListView as a struct, it is natural to expose hWnd
as a public member variable.
|
|
|
|
This is obviously a lot less obtuse.
|
|
It seems that "right-spaced" pointers are more widely used among C++
programmers.
|
|
Note that I did NOT add const to non-pointer/non-reference arguments
in function declarations (without a following definition), as they do
not mean anything there.
|
|
If needed in the future, it is possible to simply copy it from the Git
history.
|
|
This avoids the use of TsmFromSz.
|
|
|
|
I.e. using std::basic_string<TCHAR> instead of TCHAR *. This removes
all unmanaged frees.
|
|
This avoids g_hWnd.
|
|
This is feasible now that the makedeps script exists to automatically
manage build dependencies (see 6034fe2, d00f8b3).
|
|
|
|
|
|
|
|
This requires C++17.
|
|
|
|
In the future, it may be desirable to convert Prolog exceptions to C++
exceptions.
|
|
This is a bit safer and about as complex.
|
|
|
|
|
|
|
|
On WM_DESTROY, the "this" property was removed before it could be
retrieved and dereferenced, making it impossible for WM_DESTROY
messages to be passed to the WndProc method.
|
|
Bug introduced in 26f70ab. DataListView was initialized with g_iDPI
set to -1, which is obviously incorrect. The default value of -1 is a
remnant of earlier code and is no longer necessary.
|
|
Height(DLVSIKEY) was incorrect. The argument to Height is supposed to
be a boolean value, in this case false. It happened to work because
DLVSIKEY is 0 (because Key is the 0th column in the data list view).
|
|
The rules for what messages are sent at window creation -- and in
which order -- are neither intuitive or clear. WM_CREATE can NOT be
relied upon to initialize global state required by handlers of other
messages (such as WM_GETMINMAXINFO, which seems to be sent before
WM_CREATE).
Thus, the better solution is to initialize everything using a CBT hook
before the window procedure is even run. Because CBTProc creates
(child): windows of its own, though, one must be careful to only run
the initialization once, which is done by checking g_hWnd.
|
|
|
|
|
|
I already hit upon some object-oriented programming patterns in
*listview.c, so I felt that it would be natural to use this as an
opportunity to learn C++.
|
|
|