Since oldfont is a lexical variable being initialized from (SelectObject fe.hdc font.font), you probably get the most information about this by going off to MSDN to study what is SelectObject. If we select an object, like a font or a brush, into a device context, we get the previous object of that type: new font kicks out old font, new brush kicks out old brush, and so on.

SelectObject's return value is a HGDIOBJ whichi s just a void * in disguise. Thus oldfont is just a FFI foreign pointer (cptr). You can do nothing with it other than compare it for equality with NULL and pass it to Win32 functions.

I have simply mirrored the C more or less as-is.

tm is a local variable; again, you just have to look where it is bound:

(tm (new TEXTMETRIC))

so you know the type from the lexical scope. This corresponds to the line of C which goes

TEXTMETRIC tm;

It's exactly the same process. In the C code if I see tm.tmAscent, I look backwards for the declaration of tm, perhaps using the Vim # key. If I see tm.tmAscent in Lisp, I look backwards to see where tm is bound, perhaps using the Vim # key. (new TEXTMETRIC) is exactly as informative as TEXTMETRIC tm;.

Any time you see a simple variable being accessed in Lisp code, it is either lexically scoped or global. If you don't see it in the lexical scope, it is the latter.

So that brings us to dstat. Another lexical which is a copy of fe.drawstatus. We can see that fe is a parameter, but what is drawstatus? No fancy IDE is needed; just Vim. Put the cursor on drawstatus, and Ctrl-] chases the tag to the definition, a line in a big struct definition:

(defstruct win-frontend win-drawing
// ...
drawstatus ;; @(or :drawing :printing nil)
// ...
)

fe is an important parameter; it is the self object of the method.

I used the pattern matching notation in the above comment to remind myself the values this can hold. The front end objects in Simon Tatham's design have a mode variable which indicates whether printing or ordinary rendering is taking place. If you're printing, you have to do different things with colors and such (possibly using hatched pens on a black-and-white printer, plus scaling of coordinates and whatnot). I just used the three symbols :drawing, :printing and nil.

Popular languages like Javascript and Python have a worse version of this "what is drawstatus" problem, yet are used by legions of programmers in all sorts of successful projects, even large ones. In these languages there is no clear place where object properties are defined, and objects can even be monkey patched with new properties, which I do not allow.

Finding out what is returned by SelectObject is the same: put the cursor on SelectObject, Ctrl-], and it jumps to the FFI definition:

(deffi SelectObject "SelectObject" HGDIOBJ (HDC HGDIOBJ))

In reading Lisp, there is no panic if we are calling some function, and capturing its return value without that being declared. Firstly, most of the time we shouldn't have to know anyway; if the program is well designed, we shouldn't care about the implementation details. Unless we are specifically looking for a bug in that aspect of the code, we can just trust that it's okay.

The trend in modern languages, including statically typed ones, is to have fewer declarations. If the original code here were C++ you could probably do:

auto oldfont = SelectObject(...);