Quote:
My complaint is I would have expected the error without using the check function. It was very frustrating to have the WindowAddHotspot function fail silently the way it did.
It is pretty standard practice with API calls in many operating systems and utilities that they return a "success" or "failure" code (or throw an exception) rather than raising a dialog box or printing something to output.
It is usually the responsibility of the programmer to check documented return codes. Those return codes are mentioned in the documentation for the MUSHclient function APIs.
You could wrap a "check" call around every Windowxxxx call, however that gets a bit messy to read.
Another approach is to automatically replace all function calls with a "stub" function that does the check for you, as shown below.
-- automatically check Window* function results
-- stub function generator to check a function call
local function make_check_func (f)
return function (...)
local results = { f (...) } -- call original function
check (results [1]) -- check return value
return unpack (results) -- return results
end -- function
end -- make_check_func
-- functions this will work with (that return eOK, and other things)
local valid_funcs = { }
for k, v in ipairs {
"WindowAddHotspot", "WindowArc", "WindowBezier", "WindowBlendImage",
"WindowCircleOp", "WindowCreate", "WindowCreateImage", "WindowDelete",
"WindowDeleteAllHotspots", "WindowDeleteHotspot", "WindowDragHandler",
"WindowDrawImage", "WindowDrawImageAlpha", "WindowFilter", "WindowFont",
"WindowGetImageAlpha", "WindowGradient", "WindowHotspotTooltip", "WindowImageFromWindow",
"WindowImageOp", "WindowLine", "WindowLoadImage", "WindowMergeImageAlpha",
"WindowMoveHotspot", "WindowPolygon", "WindowPosition", "WindowRectOp",
"WindowResize", "WindowScrollwheelHandler", "WindowSetPixel", "WindowSetZOrder",
"WindowShow", "WindowTransformImage", "WindowWrite",
} do valid_funcs [v] = true end
-- see if one of them is a C function or a Lua function
local t = debug.getinfo (WindowShow, "S")
-- replace world Window* functions with a stub
if t.short_src == "[C]" then -- if not already converted
for k, f in pairs (world) do
if type (f) == "function" and valid_funcs [k] then
world [k] = make_check_func (f) -- replace with stub
end -- if
end -- for
end -- if not done already
Put the above at the start of your world script file, or your plugin script.
Now you can call the functions normally, but an error will be raised if they fail. For example, testing (on the command line) with an non-existent window name:
Result:
Run-time error
World: smaug2
Immediate execution
[string "Immediate"]:8: Requested miniwindow does not exist
stack traceback:
[C]: in function 'error'
[string "Check function"]:1: in function 'check'
[string "Immediate"]:8: in function 'WindowShow'
[string "Command line"]:1: in main chunk
There is a bit of complexity in the above because not every function call is documented to return eOK (zero) or something else, for example WindowInfo returns a variant which is the information requested. Thus there is a table above to limit the conversion of only certain functions to the stub calls.
Quote:
I also looked through the documentation and couldn't find any mention of the requirement for all the hotspots being in one place.
The last line (presently) in the documentation for WindowAddHotspot reads:
WARNING: The hotspot callbacks are not functions, but names of functions. That is, they should be supplied as string arguments. The supplied names are looked up in the script space at the appropriate time.
Each world file (and each plugin) has their own script space, indeed those scripts might be written in different languages. The wording "the script space" is supposed to imply "of the current plugin".
I have amended the documentation in the next release to emphasise that the callbacks have to be in the same plugin. |