1V-code Technical Reference
2
3
4
5-------------------------------------------------
6
7== Introduction ==
8
9V-code got its name from a void pointer. As bytecode is comprised of 'char', so
10V-code is of 'void *'. Therefore, "V".
11
12V-code engine runs mtPaint's GUI - and its commandline and scripts - but it is
13less a widget toolkit per se, than a technique of abstraction. The idea was to
14decouple the semantics of controls from the particulars of implementation - and
15to get rid of the mind-numbing boilerplate that invariably accompanies anything
16having to do with a GUI. And when I compare what it takes to create a new dialog
17now with V-code, to what it had taken without - I much prefer the new way.
18
19V-code is declarative. I describe an interface component, and leave it to the
20engine to make it - or to pretend convincingly enough, so that the rest of the
21program does not notice a difference. Whatever specialcasing is needed, is done
22within the engine, never to poke its ugly snout outside.
23
24While the declarative part is quite extensive, the runtime API is simplistic. It
25does not need complexity; when creation is firmly separated into its own phase,
26only a few tweaks remain to be done at runtime.
27
28Another reason for the simplicity is that I made things interchangeable. There
29are no special accessor functions for any type of widget, and callback signatures
30never differ without a very compelling reason. This way, one event handler can
31serve a number of different widgets with minimal effort.
32
33This absence of widget functions/methods is an intentional feature and the core
34difference of V-code from usual GUI toolkits. All actions are done through a
35compact set of call points, and while internally tasks get routed to specific
36effector modules, calling code takes no part in the decisions what to use, how,
37and when. Interdependences of some operations arising in some cases are thus
38easily tracked and handled, entirely within the engine. Equally easy are
39conditional replacements of a component with a differently implemented, or a
40simulated one.
41
42V-code is not told what to do; it receives commands as to what it should make
43happen. It is the principle of the thing.
44
45The function handlers are minimalistic. No sanity checks; if something is done
46wrong, code signals that by crashing. But no strictness either; if a function is
47called on an unhandled widget type, it simply does nothing. Default values are
48sometimes substituted, but only where doing it once in the handler made more
49sense than repeating the same at several call sites.
50
51Neither declarative nor runtime part is providing complete coverage; only the
52widgets and operations needed by mtPaint. When for a new feature I need something
53that is not yet there, I extend the V-code engine.
54
55
56== Overview ==
57
58The pegasus-eye view of how V-code is used, is this.
59- You prepare a V-code description of, say, a dialog window.
60- You fill a struct with initial values for it.
61- You hand off both to **run_create_()**.
62- It executes the description: allocates memory, copies the struct in there,
63  creates widgets, setups callbacks, does initializations, and shows the finished
64  result to the user.
65- User does some things to controls in the dialog, changing some values, then
66  presses "OK".
67- The callback sees that it was "OK", calls **run_query()** to read back values
68  from all the controls.
69- The new values in the copy of struct and/or in global variables are used to do
70  something.
71- The callback calls **run_destroy()** to finish off the window, and returns.
72- Done.
73
74
75There are ways and means to do more complicated things, but this simple scenario
76is done this simply; in exactly 3 function calls.
77
78This is how it can work.
79
80Every V-code command describing a control - say, a spinbutton or a text entry -
81has a memory reference; either to a global variable, or to a field in a struct.
82When the control is created, it is initialized from that memory; when it is read,
83the result goes to that memory. When **run_create()** makes that control, it
84saves the address of that V-code command, and the widget it created, into its
85"tape" (a flat array of "slots"). When you call **run_query()**, it iterates over
86slots in the "tape" and looks at commands; it reads back values from every control
87it finds, each into the place that its command refers to. When you call
88**run_destroy()**, after the widgets get destroyed it again iterates over slots
89and looks at commands, to do cleanup actions if needed; after that, the attached
90struct and "tape" are freed.
91
92When you need to add a callback, you put an //EVENT()// command, with a type ID
93and a function reference, after a control; this command also gets a slot in the
94"tape". The function gets called when the control sitting before it in the "tape"
95wants to raise an event of that type. With the //TRIGGER// command, you can raise
96the preceding //EVENT()// just after **run_create()** finishes creating things;
97doing it to a list control's //SELECT// event is the natural way to make other
98controls reflect initial selection in the list. Some commands that create
99controls, have //EVENT()// built in, some even two of them; for them, function
100references go as parameters to the commands. A //TRIGGER// command after a
101two-event control triggers its second builtin //EVENT()//.
102
103When you need to, say, hide a control, you pass address of its slot to
104**cmd_showhide()**. To get that address, you put a //REF()// command right before
105the command that creates the control. //REF()//, again, has a memory reference
106(to a field of type **void**** ; for a variable, you use //REFv()//); into that
107memory, **run_create()** will put the current position in the "tape".
108
109For a container widget, you create it with a command such as //VBOX//, and
110everything you create after it will go into it, till you close it with //WEND//.
111One-place containers, such as //FRAME()//, close by themselves after accepting a
112widget (or you can close them by //WEND// leaving them empty). One command can
113also create more than one container; //DOCK()// has two panes, each filled
114separately and finished by its own //WEND//.
115
116Most container widgets do not get slots of their own, but are fill-and-forget. If
117you need to interact with them, say hide a box with all its contents, you need a
118version with a slot; those are tagged with "r", like //VBOXr// vs //VBOX//.
119
120When you want to include some commands only if a condition holds (say, with an
121RGB image you offer to select red, green, or blue channel, and with indexed ones
122you don't), you can use simple conditionals //IF()// and //UNLESS()//, affecting
123one command, or extended ones //IFx()// and //UNLESSx()// that affect everything
124till the matching //ENDIF()//. They get a memory reference (to an **int**), and
125check it for being zero or nonzero.
126
127When you need to allocate some memory (say, a buffer for a histogram image to be
128displayed), you use the //TALLOC()// command; it takes two fields - from one it
129takes the size, into the other it puts the resulting pointer. Such memory is
130allocated as part of the same memory block that holds the struct and the "tape",
131so if there isn't enough memory for it, then nothing at all gets allocated and
132**run_create()** itself fails (returning NULL).
133
134If you put a pointer to some separately allocated object into the struct, you can
135even tell **run_destroy()** to free it along with everything else; for that, you
136use the //CLEANUP()// command.
137
138A complete command sequence is one that creates a self-contained interface
139element (usually a toplevel window, but not necessarily). There are two things
140required from it. It has to define something in where all the controls will go;
141a //WINDOW()//, //TOPVBOX// etc. And it has to terminate the sequence, telling
142**run_create()** what to do with it; use //WDIALOG()// command to run it as a
143dialog, //WSHOW// to show it to the user, or //WEND// to hand it off to the
144program to be shown later.
145
146
147== V-code as written ==
148
149Declarative V-code is an array of pointers to void:
150
151**void *whatever_code[] = { ... };**
152
153The array is initialized by a sequence of command macros, with their parameters.
154In case the commands are referring to **ddata** fields, the struct type to use
155must be set before that, as the //WBbase// macro:
156
157**#define WBbase whatever_dd**
158
159So nearly all V-code chunks in mtPaint look like this:
160```
161#define WBbase whatever_dd
162void *whatever_code[] = { ... };
163#undef WBbase
164```
165
166In a simplest case, one V-code chunk creates something from beginning to end, but
167there are also other possibilities.
168
169The most complex part of mtPaint, the main window, is defined part by part in
170several chunks in several source files, which the main chunk, fittingly named
171**main_code[]**, calls one by one using the //CALL()// command; some then call
172yet other chunks in their turn.
173
174The least complex parts, the lowly filter windows, use a reverse approach; a
175small filter-specific code chunk which is a V-code subroutine, indirectly called
176(with //CALLp()// command) by **filterwindow_code[]** chunk between it building
177the generic top part and the equally generic bottom part of the window.
178
179
180== In-memory structure ==
181
182The memory block allocated by **run_create_()** is structured this way:
183
184| ddata | User-provided backing struct |
185| vdata | Internal window-info struct  |
186| wdata | "Tape" of "slots" referring to widgets, events, etc. |
187| dtail | Extra memory allocated to widgets and to/by other V-code commands |
188
189All this is allocated as one single block, which not only greatly simplifies
190memory management, but also, with all references to anything of note sitting in a
191flat array of "slots", makes all kinds of reflection trivial. This is by virtue
192of V-code being processed in two passes; first, **predict_size()** counts how
193many "slots" and how much extra memory the V-code sequence wants, then memory for
194all that is allocated and partitioned up, the user-provided struct copied in, and
195only then the commands actually get executed one after another; creating and
196setting up widgets, taking up chunks of dtail area, and filling "slots".
197
198A canonical reference to a block is the address of its **wdata**; i.e. it points
199into middle of the block. The reason for that is purely historical; nothing
200prevents setting up **ddata** and **vdata** after **dtail** area instead, but
201given that a block should never be deallocated in any other way than by calling
202**run_destroy()**, the arrangement is not relevant to anything.
203
204A "slot" in **wdata** consists of 3 pointers:
205| 0 | Widget/something else |
206| 1 | V-code command that set up the slot |
207| 2 | Dtail chunk |
208
209Slot where "something else" is its **dtail** chunk (i.e. 0th cell equals 2nd) is
210considered "unreal"; such slots are set up by pseudo-widgets used to simulate
211real ones when running scripts, thus the name. With the V-code command obviously
212being the same in either case (real and simulated), this is the only way to tell
213the two apart.
214
215The first slot of **wdata** is a fake one, used for linking all this together:
216| 0 | **ddata** |
217| 1 | **vdata** |
218| 2 | Dtail chunk |
219The **vdata** structure masquerades as a V-code command //WDONE//; as no regular
220//WDONE// gets a slot of its own, the slot is thus unique. The **wdata_slot()**
221function just steps through the "tape" before a slot till it finds this marker,
222and returns its address.
223
224The second slot must belong to a toplevel widget. No other thing should be put
225into the "tape" before it.
226
227And the last slot in **wdata**, marking its end, is all NULLs; all functions
228iterating over slots, depend on it being there. //WEND//, //WSHOW// and
229//WDIALOG()// put it into the "tape", before doing all other finishing touches.
230
231Macro **GET_DDATA()** gets from **wdata** to **ddata** (just reads the 0th cell
232of the first slot). The macro GET_VDATA(), internal to vcode.c, gets from
233**wdata** to **vdata** (by reading the 1st cell).
234
235
236== Structure of V-codes ==
237
238As said above, V-code is an array of pointers to void. The array contains a
239sequence of commands - each consisting of one or more pointer values: an
240instruction header, and a specified number of parameters.
241
242The parameters can be either constants, or memory references. The latter may be
243either addresses of globals (string constants, variables, cells in global arrays,
244functions), or offsets in **ddata** struct, of the type designated by the
245//WBbase// macro. Encoding the field references is done with the //WBfield()//
246macro:
247
248**..., WBfield(field), ...**
249
250Other things are encoded as per usual; variables with the "&" operator, strings,
251arrays and functions as is, constants with a "(void *)" cast:
252
253**&(variable), "string", array, array + 2, function, (void *)1**
254
255The responsibility of a high-level command macro is to pack its parameters in the
256way and order that the underlying instruction code expects them. Like this:
257
258**OKBTN(_("OK"), conf_done)**
259
260translates to this:
261
262**WBr2h_x(OKBTN, 1 + 2), (_("OK")), EVENT(OK, conf_done)**
263
264Here you see a command macro expanding into an instruction header macro, a string
265constant (wrapped in a no-op translation marker), and a nested command macro
266which in its turn expands to another header and a function constant:
267
268**WBrh(EVT_OK, 1), (conf_done)**
269
270Instruction headers are in fact 31-bit integer values, to be able to comfortably
271reside in a pointer on a 32-bit system, and to avoid the signed/unsigned hassle.
272As of mtPaint 3.50, the bits are allocated this way:
273
274|| Bits | Function             | Values   |
275|  0-11 | Instruction code     | op_*     |
276| 12-15 | Packing mode         | pk_*     |
277| 16-17 | Number of slots      | WB_REF*  |
278|    18 | Indirection flag     | WB_NFLAG |
279|    19 | Field flag           | WB_FFLAG |
280|    20 | Script flag          | WB_SFLAG |
281| 21-23 | Reserved             | 0        |
282| 24-30 | Number of parameters | 0-127    |
283
284
285The number of parameters is how many pointers after the header are part of the
286command in question; i.e. how many to skip to get to the next header. In the
287example above it is 1 + 2: 1 for the string, and 2 more for the nested
288//EVENT()// command (which in its own header has 1, for the function).
289
290The first pointer after the header (given the number of parameters is nonzero) is
291intended to be interpreted as pointer to data; this is in no way a hard
292requirement, and many instructions use it for constants instead, but the prologue
293code in V-code functions pre-interprets this field in accordance to field flag and
294indirection flag, so if an instruction refers to in-memory data, it is easiest to
295place the most used (or only) location in there.
296
297- Initially, the first pointer is read as, well, a pointer (and by default, left
298unmodified);
299- With the field flag on, it is reinterpreted as an integer offset from the start
300of **ddata**, and the current **ddata** base address gets added to it;
301- With the indirection flag on, it is interpreted as a pointer to a pointer, and
302that pointer is read in.
303
304
305The script flag, if set, selects nondefault scripting-related behaviour for some
306few commands (specifics depend on command). Not even looked at for all the rest
307of them.
308
309The number of slots (from 0 to 3) tells //run_create_()// how many slots in the
310"tape" this command needs. The first slot refers to the command itself, the
311second and third are set up for its builtin //EVENT()// subcommands (each one a
312pair of pointers at end of the parameters area). A command not taking any slots,
313is executed and forgotten; this fits the widgets that do not need any interaction
314(such as most containers) and modifier commands. The example command above takes
315two slots; it is what the "r2" in its header macro means. The //EVENT// command
316on its own takes one, thus the plain "r" in its.
317
318The packing mode denotes how the widget the command creates should be packed into
319its container, in case the container supports this mode of packing. The small
320assortment of choices is this:
321
322| pk_NONE    | not intended to be packed (modifier, event, etc.) |
323| pk_PACK    | from beginning of container, not expanding |
324| pk_XPACK   | from beginning, expanding |
325| pk_EPACK   | from end, expanding |
326| pk_PACKEND | from end, not expanding |
327| pk_TABLE1x | into first free cell in first/second column of a table, not expanding |
328| pk_TABLE   | into specified row and column(s) of a table, not expanding |
329| pk_TABLEx  | into specified row and column(s) of a table, expanding |
330
331- //pk_PACK// and //pk_XPACK// are allowed for any kind of container, other modes
332require a matching container type.
333- //pk_TABLE// and //pk_TABLEx// take an extra pointer value, from the very end
334of command's parameters, and interpret it as 3 byte values denoting X, Y, and
335length, as packed by the //WBxyl()// macro. Like in this command macro for a
336horizontal box that can take several table columns:
337**#define TLHBOXl(X,Y,L) WBh_t(HBOX, 1), WBxyl(X, Y, L)**
338
339
340Returning to the example, //OKBTN()// command does //pk_XPACK//, as denoted by
341the "_x" in its header macro; the //EVENT()// command does //pk_NONE//, as
342denoted by the lack of "_" in its.
343
344And finally, the instruction code tells //run_create_()// what to do with it all
345(and later, is used to recognize the objects to which the slots in the "tape"
346refer). In the example, it is //op_OKBTN// for the command itself, and
347//op_EVT_OK// for its builtin //EVENT()// command.
348
349On the preprocessor side of things, instruction codes are assembled in stages.
350First, a set of macros is used as shorthand representations for every combination
351of flags and slots that ever arises in some command. For example, //WB_R2F//
352denotes two slots asked for, and the field flag set:
353
354**#define WB_R2F (WB_REF2 + WB_FFLAG)**
355
356Then goes the basic macro encoding the instruction header: //WBp_()//, taking
357instruction code, length, packing mode, and a flags and slots combination.
358However, for brevity, actual command macros use one of the many pre-encoded
359//WB*h*()// macros that need take only instruction name and length. Like the one
360from the example:
361
362**#define WBr2h_x(NM,L) WBp_(op_##NM, L, XPACK, R2)**
363
364In these macros, the part between "WB" and "h" denotes the slots and flags, and
365the part after "h", packing mode.
366
367Additionally, there is a set of helper macros that some commands use to pack two
368byte values into a single pointer: //WBwh()//, //WBnh()//, and //WBbs()//; the
369difference is purely semantic, they do the same thing. And another set for three
370values: //WBpbs()// and //WBppa()//, again doing the same.
371
372
373== V-code commands ==
374
375All high-level command macros are listed below. The list is not final, for new
376commands can be derived from opcodes and lower-level macros any time when existing
377combinations of parameters do not cover a new use case.
378
379In the descriptions below, unless noted differently, the string parameters are
380constants or global **char** arrays, the numeric parameters are constants.
381
382Packing mode for the commands producing widgets (controls and containers),
383unless noted differently, is the default one, //pk_PACK//.
384
385Naming guidelines (not 100% followed) for the macros:
386- "**u**" prefixed to "unreal" (script-only, simulated) version of a widget:
387  //uSPIN()//
388- "**a**" affixed to a version that takes an array instead of several constant
389  parameters: //TSPINa()//
390- "**c**" affixed to a version that is centered: //MLABELc()//
391- "**e**" affixed to a version that has a builtin event: //RPACKe()//
392- "**p**" affixed to a version that takes string parameter by reference instead
393  of a string constant: //WINDOWp()//
394- "**r**" affixed to a version that has a slot in the "tape": //VBOXr//
395- "**s**" affixed to a version that is scriptable: //MENUITEMs()//
396- "**v**" affixed to a version that refers to a variable/array instead of a field:
397  //CSCROLLv()//
398- "**x**" affixed to a version that has extra parameters: //TLABELx()//
399- "**T**" or "**T1**" prefixed to a version packed in first/second table column:
400  //TLABEL()//, //TSPIN()//, //T1SPIN()//
401- "**TL**" prefixed to a version packed into table at (//x, y//): //TLLABEL()//
402- "**TL...l**" circumfixed to a version packed into table at (//x, y//)
403  taking //length// cells: //TLLABELl()//
404- "**X**" prefixed to a version that is packed expanding: //XTABLE()//
405- "**F**" prefixed to a version that has a frame around: //FTABLE()//
406
407
408=== Finalizers ===
409
410All these commands finish element creation and cause **run_create()** to return.
411They differ in what else they do between those two points.
412
413: //WDONE// :
414  do nothing extra
415: //WSHOW// :
416  show the toplevel
417: //WDIALOG(field)// :
418  show, then process input till the **void**** field changes to non-NULL
419
420
421=== Toplevels ===
422
423All toplevels are one-place containers, unless noted differently. All have a slot
424in the "tape" (and extra slots for builtin events, if have any).
425
426: //MAINWINDOW(title, icon, width, height)// :
427  program's main window, with specified title, XPM icon, default width and height
428: //WINDOW(title)// :
429  a regular non-modal window with specified title
430: //WINDOWp(field)// :
431  as above, with title passed in a **char*** field
432: //WINDOWm(title)// :
433  a regular modal window with title
434: //WINDOWpm(field)// :
435  as above, with title in a **char*** field
436: //DIALOGpm(field)// :
437  a modal dialog, with title in a **char*** field; is a double container: the top
438  (the first accessible) is dialog's "content area" (a vertical box), the
439  bottom/second is its "action area" (the one with buttons, a horizontal box)
440: //FPICKpm(title_field, mode_field, filename_field, OK_handler, CANCEL_handler)// :
441  a file selector window, with **char*** title, **int** mode, and **char[]**
442  filename (in system encoding) in fields, and handlers for //OK// and //CANCEL//
443  events; is a box container (horizontal) for extra controls
444: //POPUP(title)// :
445  a popup window with specified title (which, while not shown, is still useful for
446  identifying the window in window manager's lists)
447: //TOPVBOX// :
448  a pseudo-toplevel, for elements created to sit in //MOUNT// containers or purely
449  for scripting; is a box container (vertical)
450: //TOPVBOXV// :
451  same thing but with different sizing: fills space vertically, but horizontally
452  is only centered, not stretched
453: //IDENT(id)// :
454  set a non-default identifying string for the toplevel; is needed when one
455  toplevel has separate V-code descriptions for different parts: the case in point
456  is file selector, where the //FPICKpm()// command builds its fixed part through
457  a nested **run_create()** using an //IDENT()//
458
459
460=== Containers ===
461
462Table containers have a border area by default; its size can be set by
463//BORDER(TABLE)// (see "Sizing and placement" category below). Other containers
464do not, unless specifically noted.
465
466: //WEND// :
467  close the current container
468: //TABLE(columns, rows)// :
469  a table of given dimensions (those currently are initial, not a hard limit)
470: //TABLE2(rows)// :
471  a two-column table
472: //TABLEs(columns, rows, spacing)// :
473  a table with specified spacing (same for rows and columns)
474: //TABLEr(columns, rows)// :
475  a table that gets a slot in the "tape"
476: //XTABLE(columns, rows)// :
477  a table that is packed expanding (//pk_XPACK//)
478: //ETABLE(columns, rows)// :
479  a table that is packed from the end (//pk_PACKEND//)
480: //VBOX// :
481  a vertical box
482: //VBOXr// :
483  a vertical box with slot in the "tape"
484: //VBOXbp(spacing, border, padding)// :
485  a vertical box with specified spacing, border, and padding
486: //VBOXP// :
487  a vertical box with padding of default size (5 pixels)
488: //VBOXB// :
489  a vertical box with border of default size (5 pixels)
490: //VBOXS// :
491  a vertical box with spacing of default size (5 pixels)
492: //VBOXPS// :
493  a vertical box with padding and spacing of default size (5 pixels each)
494: //VBOXBS// :
495  a vertical box with border and spacing of default size (5 pixels each)
496: //VBOXPBS// :
497  a vertical box with padding, border and spacing of default size (5 pixels each)
498: //XVBOX// :
499  a vertical box that is packed expanding
500: //XVBOXbp(spacing, border, padding)// :
501  same, with specified spacing, border, and padding
502: //XVBOXP// :
503  a vertical box, packed expanding, with default padding
504: //XVBOXB// :
505  a vertical box, packed expanding, with default border
506: //XVBOXBS// :
507  a vertical box, packed expanding, with default border and spacing
508: //EVBOX// :
509  a vertical box, packed from the end
510: //HBOX// :
511  a horizontal box
512: //HBOXbp(spacing, border, padding)// :
513  a horizontal box with specified spacing, border, and padding
514: //HBOXP// :
515  a horizontal box, with default padding
516: //HBOXPr// :
517  same, with slot in the "tape"
518: //HBOXB// :
519  a horizontal box, with default border
520: //XHBOX// :
521  a horizontal box, packed expanding
522: //XHBOXbp(spacing, border, padding)// :
523  same, with specified spacing, border, and padding
524: //XHBOXP// :
525  a horizontal box, packed expanding, with default padding
526: //XHBOXS// :
527  a horizontal box, packed expanding, with default spacing
528: //XHBOXBS// :
529  a horizontal box, packed expanding, with default border and spacing
530: //TLHBOXl(x, y, length)// :
531  a horizontal box, packed into //length// columns in a table, starting at
532  column //x//, row //y//
533: //TLHBOXpl(x, y, length)// :
534  same, with default padding
535: //EQBOX// :
536  a horizontal box with equal space allocated to contents
537: //EQBOXbp(spacing, border, padding)// :
538  same, with specified spacing, border, and padding
539: //EQBOXP// :
540  a horizontal box with equal space, with default padding
541: //EQBOXB// :
542  a horizontal box with equal space, with default border
543: //EQBOXS// :
544  a horizontal box with equal space, with default spacing
545: //EEQBOX// :
546  a horizontal box with equal space, packed from the end
547
548
549==== Frames ====
550
551Frames have an empty border area around them by default, its size can be set by
552//BORDER(FRAME)//. A container sitting inside a frame can also have a border of
553its own, even if both are created by one command.
554
555: //FRAME(name)// :
556  a frame with specified name
557: //XFRAME(name)// :
558  same, packed expanding
559: //XFRAMEp(field)// :
560  a frame, packed expanding, with name passed in a **char*** field
561: //EFRAME// :
562  a frame without name, with an "etched out" look
563: //FTABLE(name, columns, rows)// :
564  a table of given dimensions sitting in a named frame
565: //FVBOX(name)// :
566  a vertical box sitting in a named frame
567: //FVBOXB(name)// :
568  a vertical box in a named frame, with default border
569: //FVBOXBS(name)// :
570  a vertical box in a named frame, with default border and spacing
571: //FXVBOX(name)// :
572  a vertical box in a named frame, packed expanding
573: //FXVBOXB(name)// :
574  same, with default border
575: //EFVBOX// :
576  a vertical box with twice the default border (10 pixels), sitting in an
577  "etched out" nameless frame
578: //FHBOXB(name)// :
579  a horizontal box in a named frame, with default border
580
581
582==== Scrolling ====
583
584Scrolling containers have a default border area: //BORDER(SCROLL)//.
585
586: //SCROLL(horiz_mode, vert_mode)// :
587  a scrolling container, with display modes for its horizontal and vertical
588  scrollbar: 0 - do not show, 1 - show when needed, 2 - show always
589: //XSCROLL(horiz_mode, vert_mode)// :
590  same, packed expanding
591: //FSCROLL(horiz_mode, vert_mode)// :
592  a scrolling container in an unnamed frame, packed expanding
593: //CSCROLLv(array)// :
594  a scrolling container acting as a control: with its own slot, and with
595  horizontal and vertical positions read into/reset from **int[2]** array
596  (zeroed out by **run_create()**); horizontal and vertical scrollbars are shown
597  when needed
598
599
600==== Notebook ====
601
602Regular notebook widgets have a default border area: //BORDER(NBOOK)//.
603
604: //NBOOK// :
605  a notebook with tabs on top, packed expanding; is a container for //PAGE//'s
606: //NBOOKr// :
607  same, with a slot in the "tape"
608: //NBOOKl// :
609  a notebook with tabs on the left, packed expanding
610: //PAGE(name)// :
611  a page for a notebook, with a name; is a box container (vertical)
612: //PAGEvp(var)// :
613  same, with name passed in a **char*** variable
614: //PAGEi(icon, spacing)// :
615  a page for a notebook, with an icon instead of name, and specified spacing
616: //PAGEir(icon, spacing)// :
617  same, with a slot in the "tape"
618: //PLAINBOOK// :
619  a "notebook" without any visible trappings, just to show either of two boxes in
620  same place; has a slot in the "tape", through which to command it to switch
621  pages; is a double container - page 0 is the top, all pages vertical boxes
622: //PLAINBOOKn(num_pages)// :
623  same but with specified number of pages (3 or more); a multiple container, page
624  0 is the top
625: //BOOKBTN(name, field)// :
626  a toggle button with a name, for switching pages of a //PLAINBOOK// whose slot
627  is in the **void**** field: show page 1 if toggled, page 0 if not
628
629
630==== Special ====
631
632: //DOCK(ini_var_name)// :
633  a splitter adding a dock pane on the right, that can be hidden/shown; the
634  specified inifile variable (integer) holds the pane's width when it is shown;
635  has a slot in the "tape"; is a double container, with left (main) pane the top,
636  and dock pane the bottom, both panes are vertical boxes
637: //HVSPLIT// :
638  a splitter that can be switched between single-pane, horizontal, and vertical;
639  packed expanding, has a slot; is a container for two widgets, the first for
640  single/left/top pane, the second for hidden/right/bottom one; still needs
641  //WEND// after them
642: //VSPLIT// :
643  a regular vertical splitter, packed expanding, has a slot; a container for two
644  widgets, first is for the top pane, the second for the bottom, needs //WEND//
645  after them
646: //TWOBOX// :
647  a container for two widgets, holding them in one row if enough horizontal space,
648  or in two rows if not
649: //MOUNT(field, create_func, CHANGE_handler)// :
650  a container holding and "leasing" an element created by a specified **mnt_fn**
651  function (returns **wdata**), with **int** field set to TRUE while holding it,
652  and a handler for //CHANGE// event, triggered when leasing/unleasing; has a
653  slot for itself and another for the event
654: //PMOUNT(field, create_func, CHANGE_handler, ini_var_name, def_height)// :
655  same, but with the element held in a resizable vertical pane with specified
656  default height, with specified inifile variable (integer) storing modified
657  height
658: //REMOUNTv(var)// :
659  a container that, when created, "leases" the element from the //MOUNT// whose
660  slot is in the **void**** variable, and when destroyed, returns it back; is
661  packed expanding, has a slot
662: //HEIGHTBAR// :
663  a modifier that requests the max height of all the widgets following it in the
664  same container, whether visible or not; used to prevent jitter when those
665  widgets get shown/hidden later
666
667
668==== Statusbar ====
669
670: //STATUSBAR// :
671  a statusbar, packed from the end, has a slot, is a box container (horizontal)
672: //STLABEL(width, align)// :
673  a statusbar label, with specified width and alignment: 0 - left, 1 - center,
674  2 - right; has a slot
675: //STLABELe(width, align)// :
676  same, packed from the end
677
678
679=== Separators ===
680
681: //HSEP// :
682  a horizontal separator
683: //HSEPl(width)// :
684  same, with specified minimum width
685: //HSEPt// :
686  a thin (minimum height) horizontal separator
687
688
689=== Labels ===
690
691All labels, when packed into boxes and tables, have padding by default; its size
692can be set by //BORDER(LABEL)//. Labels are left aligned by default.
693
694Labels identify adjacent controls to scripts, unless prevented from it or have no
695control to attach to.
696
697: //MLABEL(text)// :
698  a regular label with text
699: //MLABELr(text)// :
700  same, with a slot of its own
701: //MLABELc(text)// :
702  a centered label with text
703: //MLABELcp(field)// :
704  same, with text passed in a **char*** field
705: //MLABELxr(text, x_padding, y_padding, x_align)// :
706  a label with text, with specified extra horizontal and vertical padding, and
707  horizontal alignment at //x_align/10//: 0 - left, 5 - center, 10 - right; has
708  a slot
709: //MLABELpx(field, x_padding, y_padding, x_align)// :
710  same, but with text passed in a **char*** field, and without a slot of its own
711: //WLABELp(field)// :
712  a centered label with text passed in a **char*** field, packed expanding,
713  ignored by scripts
714: //XLABELcr(text)// :
715  a centered label with text, packed expanding, has a slot
716: //TLABEL(text)// :
717  a label with text, packed into the first free cell of the first column of a
718  table
719: //TLABELr(text)// :
720  same, with a slot of its own
721: //TLABELx(text, x_padding, y_padding, x_align)// :
722  same, with specified padding and alignment, and without a slot
723: //TLLABELl(text, x, y, length)// :
724  a label with text, packed into //length// columns in a table, starting at
725  column //x//, row //y//
726: //TLLABEL(text, x, y)// :
727  same, packed into one column
728: //TLLABELx(text, x, y, x_padding, y_padding, x_align)// :
729  same, with specified padding and alignment
730: //TLLABELxr(text, x, y, x_padding, y_padding, x_align)// :
731  same, with a slot of its own
732: //TLLABELp(field, x, y)// :
733  a label with text passed in a **char*** field, packed into a table at
734  column //x//, row //y//
735: //TLLABELpx(field, x, y, x_padding, y_padding, x_align)// :
736  same, with specified padding and alignment
737: //TXLABEL(text, x, y)// :
738  a label with text, packed expanding into a table at column //x//, row //y//,
739  aligned at 0.3 of its width
740: //HLABELp(field)// :
741  a helptext label with text passed in a **char*** field
742: //HLABELmp(field)// :
743  same with monospace font
744: //TLTEXT(text, x, y)// :
745  text, separated into columns by tabs and into rows by newlines, is placed into
746  a table starting at column //x//, row //y//
747: //TLTEXTf(field, x, y)// :
748  same, with text stored in a **char** array field
749: //TLTEXTp(field, x, y)// :
750  same, but with text passed in a **char*** field
751
752
753=== Image display ===
754
755All widgets in this group have slots in the "tape".
756
757: //COLORPATCHv(rgb_array, width, height)// :
758  areа of specified size, filled with RGB color passed in an **unsigned char[3]**
759  array (or a string constant), packed expanding
760: //RGBIMAGE(image_field, w_h_array_field)// :
761  area of size passed in **int[2]** array field, displaying an image pointed to
762  by **unsigned char*** field
763: //TLRGBIMAGE(image_field, w_h_array_field, x, y)// :
764  same, packed into a table at column //x//, row //y//
765: //RGBIMAGEP(array_field, width, height)// :
766  area of specified size, displaying an image stored in **unsigned char[]**
767  array field
768: //CANVASIMGv(array, width, height)// :
769  framed canvas widget (one able to properly receive clicks, releases, and
770  movement, and efficiently handle scrolling) of specified size, displaying an
771  image stored in **unsigned char[]** array
772: //CCANVASIMGv(array, width, height)// :
773  same, packed from the end, expanding (//pk_EPACK//)
774: //CANVASIMGB(image_field, w_h_bkg_array_field)// :
775  framed canvas widget of minimum size passed in first 2 cells of **int[3]** array
776  field, displaying an image pointed to by **unsigned char*** field, and filling
777  the extra space, if any, with RGB color packed in an **int** in the cell 2 of
778  the **int[3]** array
779: //FCIMAGEP(image_field, x_y_array_field, w_h_array_field)// :
780  focusable widget displaying an image pointed to by **unsigned char*** field,
781  of size passed in **int[2]** array field, contoured by a frame, with a
782  ring-shaped location marker on it at coordinates given in another **int[2]**
783  array field
784: //TLFCIMAGEP(image_field, x_y_array_field, w_h_array_field, x, y)// :
785  same, packed into a table at column //x//, row //y//
786: //TLFCIMAGEPn(image_field, w_h_array_field, x, y)// :
787  same, but without a location marker
788: //CANVAS(init_width, init_height, cost, EXT_handler)// :
789  framed canvas widget of specified initial size, that triggers //EXT// event to
790  redraw an area (handled by an **evtxr_fn**); the //cost// value is defined as
791  how many pixels likely could be redrawn in the time needed to call the event
792  once more (i.e. its init+teardown cost), and is used for deciding whether to
793  redraw multiple subregions one by one, or their encompassing region once; has
794  a slot for itself and an extra one for the event
795
796
797The //EXT// handler of //CANVAS()// receives in its //xdata// parameter a pointer
798to **rgbcontext** (see mygtk.h). Its task is to render into the buffer there an
799RGB image of the denoted area of canvas, and return TRUE.
800
801
802=== Spinbuttons and spinsliders ===
803
804All spinbuttons and spinsliders, when packed into boxes and tables, have padding
805by default; its size can be set by //BORDER(SPIN)// and //BORDER(SPINSLIDE)//.
806They all have slots in the "tape", unless specifically noted.
807
808: //NOSPINv(var)// :
809  displays an **int** variable in a non-modifiable spinbutton, has no slot
810: //TLNOSPIN(field, x, y)// :
811  displays an **int** field value in a non-modifiable spinbutton, packed into a
812  table at column //x//, row //y//, has no slot
813: //TLNOSPINr(field, x, y)// :
814  same but has a slot
815: //TLSPIN(field, min, max, x, y)// :
816  a spinbutton with **int** field, range //min// to //max//, packed into a table
817  at column //x//, row //y//
818: //TLXSPIN(field, min, max, x, y)// :
819  same, packed there expanding
820: //TLXSPINv(var, min, max, x, y)// :
821  same, with **int** variable
822: //T1SPIN(field, min, max)// :
823  a spinbutton with **int** field, packed into the first free cell of the second
824  column of a table
825: //TSPIN(text, field, min, max)// :
826  same combined with label that goes into the first column
827: //TSPINv(text, var, min, max)// :
828  same, with **int** variable
829: //TSPINa(text, array_field)// :
830  same, but with value, min and max in **int[3]** array field
831: //SPIN(field, min, max)// :
832  a spinbutton with **int** field, range //min// to //max//
833: //SPINv(var, min, max)// :
834  same, with **int** variable
835: //SPINc(field, min, max)// :
836  a spinbutton with **int** field, centering the value
837: //XSPIN(field, min, max)// :
838  a spinbutton with **int** field, packed expanding
839: //FSPIN(field, min, max)// :
840  a fixedpoint spinbutton with **int** field holding value * 100, range //min//
841  to //max// (both * 100)
842: //FSPINv(field, min, max)// :
843  same, with **int** variable
844: //TFSPIN(text, field, min, max)// :
845  a fixedpoint spinbutton with **int** field, packed into the second column of
846  a table, combined with label that goes into the first column
847: //FSPIN(field, min, max, x, y)// :
848  a fixedpoint spinbutton with **int** field, packed into a table at column //x//,
849  row //y//
850: //SPINa(array_field)// :
851  a spinbutton with value, min and max in **int[3]** array field
852: //XSPINa(array_field)// :
853  same, packed expanding
854: //uSPIN(field, min, max)// :
855  a script-only simulated spinbutton with **int** field, range //min// to //max//
856: //uSPINv(var, min, max)// :
857  same, with **int** variable
858: //uFSPINv(var, min, max)// :
859  same, but fixedpoint
860: //uSPINa(array_field)// :
861  a script-only simulated spinbutton with value, min and max in **int[3]** array
862  field
863: //uSCALE(field, min, max)// :
864  a script-only simulated spinbutton with **int** field, with extended syntax:
865  interprets values like "x1.5" as "original value multiplied by 1.5"
866: //TLSPINPACKv(array, count, CHANGE_handler, width, x, y)// :
867  a grid of //count// spinbuttons arranged in //width// columns, packed into a
868  table starting at column //x//, row //y//, with values, min and max for each in
869  **int[][3]** array which is automatically updated when any of values changes,
870  with a handler for //CHANGE// event that is triggered after (handled by an
871  **evtx_fn**); has a slot for itself and another for the event
872: //T1SPINSLIDE(field, min, max)// :
873  a spinslider with **int** field, range //min// to //max//, packed into the first
874  free cell of the second column of a table, with preset size (255 x 20 pixels)
875: //TSPINSLIDE(text, field, min, max)// :
876  same combined with label that goes into the first column
877: //TSPINSLIDEa(text, array_field)// :
878  same, but with value, min and max in **int[3]** array field
879: //TLSPINSLIDE(field, min, max, x, y)// :
880  a spinslider with **int** field, packed into a table at column //x//, row //y//
881: //TLSPINSLIDEvs(var, min, max, x, y)// :
882  same, with **int** variable and preset width (150 pixels)
883: //TLSPINSLIDExl(field, min, max, x, y, length)// :
884  a spinslider with **int** field, packed expanding into //length// columns in a
885  table, starting at column //x//, row //y//
886: //TLSPINSLIDEx(field, min, max, x, y)// :
887  same, packed into one column
888: //SPINSLIDEa(array_field)// :
889  a spinslider with value, min and max in **int[3]** array field
890: //XSPINSLIDEa(array_field)// :
891  same, packed expanding
892
893
894The //CHANGE// handler of //TLSPINPACKv()// receives in its //xdata// parameter
895an **int** index of the spinbutton that changed, cast into **void***.
896
897
898=== Checkbuttons ===
899
900All checkbuttons have a default border area: //BORDER(CHECK)//. They all have
901slots in the "tape".
902
903: //CHECK(name, field)// :
904  a named checkbutton with **int** field
905: //CHECKv(name, var)// :
906  same, with **int** variable
907: //CHECKb(name, field, ini_var_name)// :
908  a named checkbutton with **int** field, with specified inifile variable
909  (integer) storing its value
910: //XCHECK(name, field)// :
911  a named checkbutton with **int** field, packed expanding
912: //TLCHECKl(name, field, x, y, length)// :
913  same, packed into //length// columns in a table, starting at column //x//,
914  row //y//
915: //TLCHECK(name, field, x, y)// :
916  same, packed into one column
917: //TLCHECKvl(name, var, x, y, length)// :
918  a named checkbutton with **int** variable, packed into //length// columns in a
919  table, starting at column //x//, row //y//
920: //TLCHECKv(name, var, x, y)// :
921  same, packed into one column
922: //uCHECK(name, field)// :
923  a script-only simulated named checkbutton with **int** field
924: //uCHECKv(name, var)// :
925  same, with **int** variable
926
927
928=== Radiobutton packs ===
929
930All radiobutton packs have a default border area: //BORDER(RPACK)//. They all have
931slots in the "tape", those with a builtin event have an extra slot for the event.
932
933: //RPACK(names_array, count, height, field)// :
934  a box of radiobuttons with **int** field that stores the index of the active
935  one, with names in **char*[]** array, //count// of them in total (0 if array of
936  names is NULL-terminated), arranged in columns of no more than //height// (0 if
937  all in a single column), packed expanding
938: //RPACKv(names_array, count, height, var)// :
939  same, with **int** variable
940: //FRPACK(frame_name, names_array, count, height, field)// :
941  a box of radiobuttons with **int** field, sitting in a named frame
942: //FRPACKv(frame_name, names_array, count, height, var)// :
943  same, with **int** variable
944: //RPACKe(names_array, count, height, field, SELECT_handler)// :
945  a box of radiobuttons with **int** field and a handler for //SELECT// event,
946  packed expanding
947: //FRPACKe(frame_name, names_array, count, height, field, SELECT_handler)// :
948  same, sitting in a named frame
949: //RPACKD(names_field, height, field)// :
950  a box of radiobuttons with **int** field, with **char**** field pointing to a
951  NULL-terminated **char*[]** array of names, packed expanding
952: //RPACKDv(names_field, height, var)// :
953  same, with **int** variable
954: //RPACKDve(names_field, height, var, SELECT_handler)// :
955  same, with a handler for //SELECT// event
956
957
958In case a radiobutton's name is an empty string, the corresponding index is just
959skipped.
960
961
962=== Option menus and comboboxes ===
963
964All option menus and comboboxes have a default border area: //BORDER(OPT)//. They
965all have slots in the "tape", those with a builtin event have an extra slot for
966the event.
967
968: //OPT(names_array, count, field)// :
969  an option menu with **int** field, with list of choices' names in **char*[]**
970  array, //count// of them in total (0 if array of choices is NULL-terminated)
971: //OPTv(names_array, count, var)// :
972  same, with **int** variable
973: //TOPTv(text, names_array, count, var)// :
974  same, packed into the second column of a table, combined with label that goes
975  into the first column
976: //TLOPT(names_array, count, field, x, y)// :
977  an option menu with **int** field, packed into a table at column //x//,
978  row //y//
979: //TLOPTv(names_array, count, var, x, y)// :
980  same, with **int** variable
981: //OPTe(names_array, count, field, SELECT_handler)// :
982  an option menu with **int** field and a handler for //SELECT// event
983: //OPTve(names_array, count, var, SELECT_handler)// :
984  same, with **int** variable
985: //XOPTe(names_array, count, field, SELECT_handler)// :
986  an option menu with **int** field and a handler for //SELECT// event, packed
987  expanding
988: //TLOPTle(names_array, count, field, SELECT_handler, x, y, length)// :
989  same, packed into //length// columns in a table, starting at column //x//,
990  row //y//
991: //TLOPTvle(names_array, count, var, SELECT_handler, x, y, length)// :
992  same, with **int** variable
993: //TLOPTve(names_array, count, var, SELECT_handler, x, y)// :
994  same, packed into one column
995: //OPTD(names_field, field)// :
996  an option menu with **int** field, with **char**** field pointing to a
997  NULL-terminated **char*[]** array of choices' names
998: //XOPTD(names_field, field)// :
999  same, packed expanding
1000: //TOPTDv(text, names_field, field)// :
1001  same with **int** variable, packed into the second column of a table, combined
1002  with label that goes into the first column
1003: //OPTDe(names_field, field, SELECT_handler)// :
1004  an option menu with **int** field, **char**** field pointing to choices' names,
1005  and a handler for //SELECT// event
1006: //XOPTDe(names_field, field, SELECT_handler)// :
1007  same, packed expanding
1008: //TOPTDe(text, names_field, field, SELECT_handler)// :
1009  same, packed into the second column of a table, combined with label that goes
1010  into the first column
1011: //COMBO(names_array, count, field)// :
1012  a combobox with **int** field, with list of choices' names in **char*[]**
1013  array, //count// of them in total (0 if array of choices is NULL-terminated)
1014: //PCTCOMBOv(var, array, CHANGE_handler)// :
1015  a combobox displaying percent zoom values, with **int** variable, an **int[]**
1016  array (0-terminated) of some values, and a handler for //CHANGE// event; has no
1017  border
1018
1019
1020In case a choice's name is an empty string, the corresponding index is just
1021skipped.
1022
1023
1024=== Specialized controls ===
1025
1026All widgets in this group have slots in the "tape", those with a builtin event
1027have an extra slot for the event.
1028
1029: //PROGRESSp(text_field)// :
1030  a progressbar, with text for it passed in a **char*** field
1031: //GRADBAR(chan_field, idx_field, len_field, max, map_array_field, cmap_array_field, SELECT_handler)// :
1032  a "gradient bar" for displaying and selecting points in a gradient, with
1033  currently selected index in **int** //idx_field//, gradient's length in
1034  //len_field//, gradient's channel in **int** //chan_field//, colormap for
1035  non-RGB cases in **unsigned char[768]** //cmap_array_field//, gradient's
1036  values/colors at points in **unsigned char[]** //map_array_field//, and a
1037  handler for //SELECT// event
1038: //KEYBUTTON(field)// :
1039  a button for choosing key combos, with **char*** field where it places keyname
1040  string
1041: //TABLETBTN(name)// :
1042  a named button for calling up tablet configuration dialog
1043: //FONTSEL(array_field)// :
1044  a font chooser, with font description string and the text to render in a
1045  **char*[2]** array field, packed expanding
1046: //EYEDROPPER(field, CHANGE_handler, x, y)// :
1047  a button calling up eyedropper, with color it picked up in an **int** field, and
1048  a handler for //CHANGE// event, packed into a table at column //x//, row //y//
1049: //COLOR(array_field)// :
1050  a color chooser for opaque colors, with RGBA in **unsigned char[4]** array field
1051: //TCOLOR(array_field)// :
1052  same for colors with alpha
1053
1054
1055=== Lists ===
1056
1057The //LISTCC*// widgets have a default border area: //BORDER(LISTCC)//. All list
1058widgets and columns have slots in the "tape", those with a builtin event have an
1059extra slot for the event, those with two, extra two slots.
1060
1061: //COLORLIST(names_field, idx_field, rgb_array_field, SELECT_handler, EXT_handler)// :
1062  a list of named colors, with currently selected index in **int** field, a
1063  **char**** field pointing to a NULL-terminated **char*[]** array of names,
1064  colors themselves in **unsigned char[]** array field, a handler for //SELECT//
1065  event, and a handler for //EXT// event (an **evtx_fn**)
1066: //COLORLISTN(cnt_field, idx_field, rgb_array_field, SELECT_handler, EXT_handler)// :
1067  same for numbered colors, with count of them in **int** field
1068: //LISTCCHr(idx_field, len_field, max, SELECT_handler)// :
1069  a simpler (headerless, unsorted) columned list, with index and length (dynamic,
1070  limited to //max// items) in **int** fields, and a handler for //SELECT// event
1071: //LISTCCHr(idx_field, len_field, SELECT_handler)// :
1072  same with static (unchanging) length
1073: //LISTC(idx_field, len_field, SELECT_handler)// :
1074  a complex (with column headers and sorting) columned list, with index and length
1075  in **int** fields, and a handler for //SELECT// event
1076: //LISTCu(idx_field, len_field, SELECT_handler)// :
1077  same, unsorted
1078: //LISTCd(idx_field, len_field, SELECT_handler)// :
1079  same, with draggable rows
1080: //LISTCS(idx_field, len_field, sortmode_field, SELECT_handler)// :
1081  a complex columned list, with selectable sort column and direction; the sort
1082  mode in **int** field is column+1 if sorted ascending, and the same negated if
1083  descending
1084: //LISTCX(idx_field, len_field, sortmode_field, map_field, SELECT_handler, EXT_handler)// :
1085  same, with user-resizable columns and filtering: **int**** field points to
1086  mapping array (row indices to display, in order; also used for sorting); and
1087  with a handler for //EXT// event (an **evtx_fn**)
1088
1089
1090Index in //LISTC()// and its brethren refers to raw (unsorted and unfiltered)
1091data. The //EXT// handler of //LISTCX()// is triggered by right click on a row,
1092and receives in its //xdata// parameter an **int** index of that row.
1093
1094The //EXT// handler of //COLORLIST()// and //COLORLISTN()// is triggered by click
1095on a color, and receives in its //xdata// parameter a pointer to **colorlist_ext**.
1096
1097The columns of a columned list sit between //WLIST// command and the list itself,
1098and describe what, how, and where from goes into each. They can refer either to
1099an array, or to a structure and a field in it; if the latter, the //COLUMNDATA()//
1100command is needed, describing an array of those structures.
1101
1102: //WLIST// :
1103  start a group of columns
1104: //COLUMNDATA(field, step)// :
1105  set a **void*** field as pointer to the array of data structures for columns in
1106  this group
1107: //IDXCOLUMN(init, step, width, align)// :
1108  add a column of indices, starting at //init// and changing by //step//,
1109  //width// pixels wide, aligned per //align//: 0 - left, 1 - center, 2 - right
1110: //TXTCOLUMNv(array, step, width, align)// :
1111  add a column of text strings from **char[]** array (buffers, not pointers), with
1112  specified step, width and alignment
1113: //XTXTCOLUMNv(array, step, width, align)// :
1114  same, expanding
1115: //NTXTCOLUMNv(name, array, step, width, align)// :
1116  add a column of text strings from **char[]** array, with column name/title
1117: //NTXTCOLUMND(name, struct_type, struct_field, width, align)// :
1118  same, from a **char[]** array field (buffer) in //COLUMNDATA//
1119: //PTXTCOLUMN(array_field, step, width, align)// :
1120  add a column of text strings from **char*[]** array field (pointers)
1121: //PTXTCOLUMNp(field, step, width, align)// :
1122  same, from **char*[]** array pointed to by //field//
1123: //RTXTCOLUMNDi(width, align)// :
1124  add a column of text strings relative to elements of **int[]** array that is
1125  //COLUMNDATA//: each element holds an offset **from itself** to the string
1126: //RTXTCOLUMND(struct_type, struct_field, width, align)// :
1127  same, relative to **int** field in //COLUMNDATA//
1128: //NRTXTCOLUMND(name, struct_type, struct_field, width, align)// :
1129  same, with column name/title
1130: //NRTXTCOLUMNDax(name, index, width, align, ini_var_name)// :
1131  same, relative to //index//-th element of **int[]** sub-array in //COLUMNDATA//,
1132  with inifile variable (integer) storing modified width
1133: //NRTXTCOLUMNDaxx(name, index, width, align, ini_var_name, test_string)// :
1134  same, at least wide enough for //test_string//
1135: //NRFILECOLUMNDax(name, index, width, align, ini_var_name)// :
1136  add a column of filenames relative to element of sub-array: the 0th character
1137  denotes the type: 'F' for file, 'D' for directory, ' ' for ".."
1138: //CHKCOLUMNv(array, step, width, align, CHANGE_handler)// :
1139  add a column of checkbuttons from **int[]** array, with a handler for //CHANGE//
1140  event (an **evtxr_fn**)
1141
1142
1143The //CHANGE// handler of //CHKCOLUMNv()// receives in its //xdata// parameter
1144an **int** index of the row that was toggled.
1145
1146
1147=== Text entry fields ===
1148
1149All entry widgets, when packed into boxes and tables, have padding by default;
1150its size can be set by //BORDER(ENTRY)//. All pathboxes have a default border
1151area: //BORDER(PATH)//. All widgets in this group have slots in the "tape", those
1152with a builtin event have an extra slot for the event.
1153
1154: //XENTRY(field)// :
1155  an entry with **char*** field, packed expanding
1156: //XLENTRY(field, max)// :
1157  same, with max length in chars
1158: //TLENTRY(field, max, x, y, length)// :
1159  same, packed into //length// columns in a table, starting at column //x//,
1160  row //y//
1161: //MLENTRY(field)// :
1162  a multiline entry (accepts **Ctrl+Enter** for a newline) with **char*** field
1163: //XPENTRY(field, max)// :
1164  an entry for filenames (in system encoding) with **char*** field, with max
1165  length in chars, packed expanding
1166: //TPENTRYv(text, var, max)// :
1167  an entry for filenames with **char*** variable, with max length, packed into the
1168  second column of a table, combined with label that goes into the first column
1169: //PATH(name, fsel_name, mode, field)// :
1170  a pathbox (a named frame with entry in system encoding and button calling up
1171  file selector) with **char*** field, with name and mode for the fileselector
1172: //PATHv(name, fsel_name, mode, var)// :
1173  same, with **char*** variable
1174: //PATHv(name, fsel_name, mode, ini_var_name)// :
1175  same, with inifile variable (string)
1176: //TPATHv(name, fsel_name, mode, var)// :
1177  a frameless pathbox with **char*** variable, packed into the second column of a
1178  table, combined with label that goes into the first column
1179: //uPATHSTR(field)// :
1180  a script-only simulated entry for filenames with **char*** field
1181: //TEXT(field)// :
1182  a text widget with **char*** field, packed expanding
1183: //COMBOENTRY(field, list_field, OK_handler)// :
1184  an entry with dropdown list with **char*** field, with **char**** //list_field//
1185  pointing to NULL-terminated **char*[]** array of choices, and a handler for
1186  //OK// event, packed expanding
1187: //HEXENTRY(field, CHANGE_handler, x, y)// :
1188  an entry for color hex code / name, with **int** field (packed RGB), and a
1189  handler for //CHANGE// event, packed into a table at column //x//, row //y//
1190
1191
1192The //XENTRY//, //*LENTRY// and //COMBOENTRY// widgets immediately replace the
1193string values used for initialization with copies owned by the widgets, so that
1194there is no chance of incidental access if the original strings are freed after
1195**run_create()**. The //TEXT// widget just replaces it with NULL, for the same
1196reason.
1197
1198
1199=== Buttons ===
1200
1201All buttons have a default border area: //BORDER(BUTTON)//. They all have two
1202slots in the "tape": for themselves and for their builtin event.
1203
1204Buttons, except toggle buttons, are not scriptable by default, unless explicitly
1205tagged by the "script flag"; some of macros below are for such buttons.
1206
1207: //OKBTN(name, OK_handler)// :
1208  a named button reacting to **Enter** key, with //OK// event handler, packed
1209  expanding
1210: //uOKBTN(OK_handler)// :
1211  a script-only simulated button with //OK// event handler
1212: //CANCELBTN(name, CANCEL_handler)// :
1213  a named button reacting to **Esc** key, with //CANCEL// event handler, packed
1214  expanding
1215: //CANCELBTNp(field, CANCEL_handler)// :
1216  same, with name in a **char*** field
1217: //UCANCELBTN(name, CANCEL_handler)// :
1218  a cancel button packed the default way (//pk_PACK//)
1219: //ECANCELBTN(name, CANCEL_handler)// :
1220  same, packed from the end
1221: //UDONEBTN(name, OK_handler)// :
1222  a named button reacting to **Enter** and **Esc** keys, with //OK// event handler
1223: //TOGGLE(name, field, CHANGE_handler)// :
1224  a named toggle button with an **int** field and //CHANGE// event handler, packed
1225  expanding
1226: //UTOGGLEv(name, var, CHANGE_handler)// :
1227  same with an **int** variable, packed the default way
1228: //BUTTON(name, CLICK_handler)// :
1229  a named button with //CLICK// event handler, packed expanding
1230: //BUTTONs(name, CLICK_handler)// :
1231  same, scriptable
1232: //BUTTONp(field, CLICK_handler)// :
1233  same, with name in a **char*** field, not scriptable
1234: //UBUTTON(name, CLICK_handler)// :
1235  a named button with //CLICK// event handler, packed the default way
1236: //EBUTTON(name, CLICK_handler)// :
1237  same, packed from the end
1238: //EBUTTONs(name, CLICK_handler)// :
1239  same, scriptable
1240: //TLBUTTON(name, CLICK_handler, x, y)// :
1241  a named button with //CLICK// event handler, packed into a table at column
1242  //x//, row //y//
1243: //TLBUTTONs(name, CLICK_handler, x, y)// :
1244  same, scriptable
1245: //uBUTTONs(name, CLICK_handler)// :
1246  a script-only simulated named button with //CLICK// event handler, scriptable
1247  (obviously)
1248: //OKBOX(ok_name, OK_handler, cancel_name, CANCEL_handler)// :
1249  a convenience macro creating an //EQBOX// with //CANCELBTN// and //OKBTN//; the
1250  box is left unclosed (without //WEND//) but no practical reason to add more
1251  things into it, and it is normally the last thing in a dialog anyway
1252: //OKBOXP(ok_name, OK_handler, cancel_name, CANCEL_handler)// :
1253  same, with a box with padding (//EQBOXP//)
1254: //OKBOXB(ok_name, OK_handler, cancel_name, CANCEL_handler)// :
1255  same, with a box with border (//EQBOXB//)
1256: //OKBOX3(ok_name, OK_handler, cancel_name, CANCEL_handler, button_name, CLICK_handler)// :
1257  an //EQBOX// with //CANCELBTN//, regular //BUTTON//, and //OKBTN//
1258: //OKBOX3B(ok_name, OK_handler, cancel_name, CANCEL_handler, button_name, CLICK_handler)// :
1259  same, with a box with border
1260
1261
1262=== Toolbar ===
1263
1264Toolbars are containers for their buttons, and need //WEND// to close.
1265//TOOLBAR*// widgets have a default border area: //BORDER(TOOLBAR)//. All toolbars
1266and toolbar buttons have slots in the "tape"; the toolbars have an extra slot or
1267two for their builtin events. Toolbar buttons call their toolbar's event handlers
1268when things happen to them, so that they do not need //EVENT//s of their own.
1269
1270: //TOOLBAR(CHANGE_handler)// :
1271  a regular toolbar with //CHANGE// event handler (to which, despite the name,
1272  regular toolbuttons getting pressed is routed too)
1273: //TOOLBARx(CHANGE_handler, CLICK_handler)// :
1274  same, with also a //CLICK// event handler for right-clicking on a button
1275: //SMARTTBAR(CHANGE_handler)// :
1276  a toolbar that, if buttons do not fit, adds a dropdown with the overflow ones;
1277  with //CHANGE// event handler
1278: //SMARTTBARx(CHANGE_handler, CLICK_handler)// :
1279  same, with also a //CLICK// event handler
1280: //SMARTTBMORE(name)// :
1281  a button that shows said dropdown; after it go regular widgets (not toolbuttons)
1282  that will stay displayed regardless
1283: //TBBUTTON(name, icon, action)// :
1284  a toolbar button with icon, tooltip (also used for scripting), and action code
1285  (two numbers packed into one by //ACTMOD()// macro)
1286: //TBBUTTON(name, icon, action, rclick_action)// :
1287  same, with another action code for right click
1288: //TBTOGGLE(name, icon, action, field)// :
1289  a toolbar toggle button with an **int** field, icon, tooltip, and action code
1290: //TBTOGGLEv(name, icon, action, var)// :
1291  same, with an **int** variable
1292: //TBTOGGLExv(name, icon, action, rclick_action, var)// :
1293  same, with another action code for right click
1294: //TBBOXTOGxv(name, icon, action, rclick_action, var)// :
1295  a regular toggle button that actually goes into the container that the toolbar
1296  sits in, but still acts like //TBTOGGLExv//
1297: //TBRBUTTONv(name, icon, action, var)// :
1298  a toolbar radiobutton with an **int** variable, icon, tooltip, and action code
1299: //TBRBUTTONxv(name, icon, action, rclick_action, var)// :
1300  same, with another action code for right click
1301: //TBSPACE// :
1302  a toolbar separator
1303
1304
1305=== Menu ===
1306
1307Menubars and submenus are containers for menuitems and submenus, and need //WEND//
1308to close. They and menuitems all have slots in the "tape"; the menubars have an
1309extra slot for their builtin event. Menuitems call their menubar's event handler
1310when they activate.
1311
1312Menuitems are not scriptable by default; those that are (tagged by "script flag")
1313have their macros' names ending in "s".
1314
1315: //MENUBAR(CHANGE_handler)// :
1316  a regular menubar with //CHANGE// event handler, to which all its menuitems'
1317  activations get routed
1318: //SMARTMENU(CHANGE_handler)// :
1319  a menubar that, if not wide enough, moves some of regular submenus into an
1320  overflow submenu; with //CHANGE// event handler
1321: //SUBMENU(name)// :
1322  a submenu
1323: //ESUBMENU(name)// :
1324  a submenu placed at the end of menubar
1325: //SSUBMENU(name)// :
1326  the overflow submenu
1327: //MENUITEM(name, action)// :
1328  a menuitem with action code (//ACTMOD()// made)
1329: //MENUITEMs(name, action)// :
1330  same, scriptable
1331: //MENUITEMi(name, action, icon)// :
1332  a menuitem with an icon, with action code
1333: //MENUITEMis(name, action, icon)// :
1334  same, scriptable
1335: //MENUCHECKv(name, action, var)// :
1336  a check menuitem with an **int** variable, with action code
1337: //MENUCHECKvs(name, action, var)// :
1338  same, scriptable
1339: //MENURITEMv(name, action, var)// :
1340  a radio menuitem with an **int** variable, with action code
1341: //MENURITEMvs(name, action, var)// :
1342  same, scriptable
1343: //MENUTEAR// :
1344  a tearoff menuitem
1345: //MENUSEP// :
1346  a menu separator
1347: //MENUSEPr// :
1348  same, with a slot of its own (to hide/show it)
1349: //uMENUBAR(CHANGE_handler)// :
1350  a script-only simulated menubar with //CHANGE// event handler
1351: //uMENUITEM(name, action)// :
1352  a script-only simulated menuitem; not scriptable, is used for keybindings
1353: //uMENUITEMs(name, action)// :
1354  same, scriptable
1355
1356
1357=== Control flow ===
1358
1359The commands in this group control what other commands get executed after.
1360
1361: //GOTO(array)// :
1362  go execute specified V-code array
1363: //CALL(array)// :
1364  push current execution address onto return stack, and go execute specified
1365  V-code array
1366: //CALLp(field)// :
1367  same, with address of the array given in **void**** field
1368: //RET// :
1369  pop execution address from return stack, and continue from there
1370: //IF(field)// :
1371  if **int** field is 0, skip the next command (caution: do not put before those
1372  macros that are internally multiple commands)
1373: //IFv(var)//
1374  same, if **int** variable is 0
1375: //IFx(field, id)// :
1376  if **int** field is 0, skip the following commands till an //ENDIF()// with the
1377  same id number
1378: //IFx(var, id)// :
1379  same, if **int** variable is 0
1380: //UNLESS(field)// :
1381  if **int** field isn't 0, skip the next command
1382: //UNLESSv(field)// :
1383  same, if **int** variable isn't 0
1384: //UNLESSx(field, id)// :
1385  if **int** field isn't 0, skip the following commands till an //ENDIF()// with
1386  the same id
1387: //UNLESSbt(ini_var_name)// :
1388  if inifile variable (boolean) isn't FALSE, skip the next command
1389: //ENDIF(id)// :
1390  mark the point for //IFx/UNLESSx// with corresponding id, otherwise do nothing
1391
1392
1393Complex conditions can be implemented in three ways; either the flag
1394variable/field itself can be calculated from the condition, or //IFx/UNLESSx// can
1395be wrapped around another (sharing the same //ENDIF//), or //IF//UNLESS// can
1396precede another conditional to skip it: "//IF(A), IF(B), command//" results in
1397"if (!a || b) command".
1398
1399
1400=== Memory allocation and referencing ===
1401
1402: //REF(field)// :
1403  put address of current slot in the "tape" into **void**** field
1404: //REFv(var)// :
1405  same, into **void**** variable
1406: //CLEANUP(field)// :
1407  in **run_destroy()** free the memory block pointed to by the **void*** field
1408: //TALLOC(field, length_field)// :
1409  in **run_create()** allocate **int** //length_field// bytes (**void*** aligned)
1410  below current **dtail** and put their address (new **dtail**) into **void***
1411  field
1412: //TCOPY(field, length_field)// :
1413  same but copy whatever the **void*** field was pointing to into the allocated
1414  block before overwriting the field with its (now the copy's) address
1415
1416
1417In case //TALLOC()// is used to allocate **double** arrays on a 32-bit
1418architecture, the block will need be allocated with one **double** extra, and
1419properly aligned on **double** afterwards.
1420
1421
1422=== Keymap and action map ===
1423
1424Action map serves to easily enable/disable or show/hide multiple widgets in
1425response to combinations of various conditions.
1426
1427: //VISMASK(mask)// :
1428  choose which bits of action map will control visibility instead of sensitivity
1429  (default is none)
1430: //ACTMAP(mask)// :
1431  the widget after whose slot in the "tape" this goes, will be sensitive/shown
1432  when any bits in the mask are set in the action map, and insensitive/hidden
1433  when none are
1434
1435
1436Keymap serves to dynamically map keys to widgets (represented as their slots in
1437the "tape"). The default mappings are set in V-code, and keymap allows to modify
1438them afterwards and saves/restores the modifications using the inifile.
1439
1440: //KEYMAP(field, name)// :
1441  add a named keymap, with **void**** field to put the found slot into
1442: //SHORTCUTs(string)// :
1443  add a shortcut represented in GTK+ string format, like "<Alt><Shift>F1"
1444: //SHORTCUT(keyval, mods)// :
1445  add a shortcut representes as keyname and modifiers, like //SHORTCUT(F2, CS)//
1446  for Ctrl+Shift+F2
1447: //SHORTCUT0//
1448  add no shortcut but tell the keymap to allow user to add one (or more)
1449
1450
1451All //SHORTCUT*// commands affect the last widget with a slot in the "tape" before
1452them, as does //ACTMAP// and other "postfix modifier" commands.
1453
1454
1455=== Grouping ===
1456
1457Group marks serve to direct **cmd_reset()** to a range of widgets all at once,
1458and to differentiate groups of like-named widgets for scripting. They all have a
1459slot in the "tape".
1460
1461: //GROUPR// :
1462  begin a resetting-group
1463: //GROUPN// :
1464  begin a scripting-group, taking its name from the preceding label
1465: //GROUP(name)// :
1466  begin a scripting-group with specified name
1467: //GROUP0// :
1468  end the current group
1469
1470
1471=== Sizing and placement ===
1472
1473: //BORDER(category, num)// :
1474  set border/spacing for specified category of widgets to specified number of
1475  pixels
1476: //DEFBORDER(category)// :
1477  set border/spacing for specified category of widgets to the default (5 pixels)
1478: The categories are:
1479| TABLE     | tables
1480| NBOOK     | notebooks
1481| SCROLL    | scrolledwindows
1482| SPIN      | spinbuttons
1483| SPINSLIDE | spinsliders
1484| LABEL     | labels
1485| OPT       | option menus
1486| BUTTON    | buttons
1487| TOOLBAR   | toolbars
1488| POPUP     | popup windows
1489| TOPVBOX   | toplevel vboxes
1490| CHECK     | checkbuttons
1491| FRAME     | frames
1492| RPACK     | radiobutton packs
1493| ENTRY     | text entries
1494| LISTCC    | simple lists
1495| PATH      | pathboxes
1496: //MKSHRINK// :
1497  make toplevel window shrinkable (to prevent it becoming larger than screen)
1498: //NORESIZE// :
1499  make toplevel window not user-resizable (to make it automatically shrink when
1500  widgets get hidden)
1501: //WANTMAX// :
1502  tell scrolledwindow that goes //after// it to request full size of its contents
1503: //WANTMAXW// :
1504  same, for width only
1505: //WXYWH(prefix, width, height)//
1506  make the toplevel save/restore its size and position using inifile variables
1507  with specified prefix, and set default width and height for it
1508: //DEFW(width)// :
1509  set default width for toplevel
1510: //DEFH(height)// :
1511  set default height for toplevel
1512: //DEFSIZE(width, height)// :
1513  set default width and height for toplevel
1514: //WPMOUSE// :
1515  tell window manager to show the toplevel at the mouse cursor location
1516: //WPWHEREVER// :
1517  tell window manager to show the toplevel wherever it chooses
1518: //WIDTH(width)// :
1519  set width for the next widget
1520: HEIGHT(height)// :
1521  set height for the next widget
1522: //MINWIDTH(width)// :
1523  set minimum width for the next widget
1524: //KEEPWIDTH// :
1525  make the //preceding// widget to never shrink in width
1526: //KEEPHEIGHT// :
1527  same in height
1528: //ONTOP(field)// :
1529  make the toplevel sit above the one whose **wdata** is passed in **void****
1530  field (set it as its transient parent)
1531: //ONTOP0// :
1532  let the toplevel sit either over or under the main window (which is default
1533  transient parent of everything else **run_create()** makes); i.e. unset
1534  transient parent
1535
1536
1537By default, **run_create()** tells window manager to show the toplevels in the
1538center of the screen.
1539
1540
1541=== Initial state ===
1542
1543: //HIDDEN// :
1544  make the preceding widget initially hidden
1545: //INSENS// :
1546  make it initially insensitive
1547: //FOCUS// :
1548  make it initially focused
1549: //RAISED// :
1550  initially raise the toplevel above other windows
1551
1552
1553=== Cursors ===
1554
1555These commands make cursors for later use. They all have slots in the "tape",
1556by which the cursors can later be referred to.
1557
1558: //XBMCURSOR(xbm_name, x, y)// :
1559  a 21x21 cursor from two XBM bitmaps (image and mask) specified by the variable
1560  part of their filenames ("select" for xbm_select.xbm and xbm_select_mask.xbm,
1561  for example), with specified hotspot coordinates
1562: //SYSCURSOR(id)// :
1563  a builtin cursor, identified as per GdkCursorType
1564
1565
1566=== Events ===
1567
1568Event handlers, in V-code, get a slot in the "tape" after the widget they are
1569attached to. There should be only one handler for a given event type per widget.
1570
1571: //EVENT(type, handler)// :
1572  add a handler for specified event type to the preceding widget
1573: //TRIGGER// :
1574  trigger the preceding event handler after **run_create()** finishes creating
1575  widgets (but before the toplevel gets shown); has a slot of its own
1576: //MTRIGGER(handler)// :
1577  trigger specified event handler (should be the same as on the menubar) for the
1578  preceding menuitem; has a slot of its own and another for the //CHANGE// event
1579: //WANTKEYS(handler)// :
1580  install priority //KEY// event handler for when the preceding widget is focused;
1581  has a slot of its own and another for the //KEY// event
1582
1583
1584The event types and their causes (widgets denoted by underlying opcodes):
1585: OK :
1586  - pressing //OKBTN// or //DONEBTN//
1587  - pressing //Enter// in text entry or pathbox's entry
1588  - choosing from list or pressing //Enter// in //COMBOENTRY//
1589  - double click or pressing //Enter// in a complex list
1590: CANCEL :
1591  - pressing //CANCELBTN//
1592  - closing a window (call **run_destroy()** if agreeing to it, return without
1593    doing that if ignoring the request)
1594: CLICK :
1595  - pressing //BUTTON//
1596  - right click on a toolbar button
1597: SELECT :
1598  - changing selection in radiobutton pack, option menu, list, or //GRADBAR//
1599: CHANGE :
1600  - changing value in spinbutton or spinslider
1601  - changing value in //TLSPINPACK//, //PCTCOMBO//, //HEXENTRY//, //EYEDROPPER//
1602  - changing text in text entry, pathbox, or //TEXT//
1603  - changing color in color selector
1604  - changing state of //TOGGLE// or checkbutton
1605  - pressing a toolbar button
1606  - selecting a menuitem
1607  - leasing/unleasing the element from //MOUNT//
1608  - scrolling a //CSCROLL//
1609  - resizing //CANVAS//
1610  - changing sort mode in //LISTCX// (should re-sort its map array)
1611: DESTROY :
1612  - running **run_destroy()** (after the toplevel is unrealized but before most
1613    everything else)
1614: SCRIPT :
1615  - setting value in the widget from a script
1616: MULTI :
1617  - setting a list of values to the widget from a script - **evtxr_fn**
1618: KEY :
1619  - pressing a key when focus is in the widget - **evtxr_fn**
1620: MOUSE and XMOUSE:
1621  - pressing a mouse button in the widget - **evtxr_fn**
1622: MMOUSE and MXMOUSE:
1623  - moving mouse in the widget - **evtxr_fn**
1624: RMOUSE and RXMOUSE:
1625  - releasing a mouse button after pressing it in the widget - **evtxr_fn**
1626: CROSS :
1627  - cursor entering or leaving the widget - **evtx_fn**
1628: SCROLL :
1629  - rotating mouse scroll wheel in the widget - **evtx_fn**
1630: EXT :
1631  - needing to render an area of //CANVAS// - **evtxr_fn**
1632  - right click in //LISTCX// - **evtx_fn**
1633  - click in //COLORLIST// - **evtx_fn**
1634: DRAGFROM :
1635  - dragging from //DRAGDROP//'s widget - **evtxr_fn**
1636: DROP :
1637  - dropping to //DRAGDROP//'s widget - **evtx_fn**
1638: COPY :
1639  - data request from //CLIPBOARD// - **evtx_fn**
1640: PASTE :
1641  - data received by //CLIPBOARD// - **evtxr_fn**
1642
1643
1644Unless otherwise noted, the event handlers are of type **evt_fn**. For those of
1645types **evtx_fn** and **evtxr_fn**, what they get in the extra parameter and what
1646their return value does, is described under "Callbacks" below.
1647
1648The difference between //MOUSE/MMOUSE/RMOUSE// and //XMOUSE/MXMOUSE/RXMOUSE//
1649events is, the latter 3 ask for, and report, tablet pressure.
1650
1651Outside //EVENT()// commands, event types are referred to by their opcodes, which
1652have "//op_EVT_//" prefix; like //op_EVT_OK// for //OK// event.
1653
1654
1655=== Clipboard and drag-drop ===
1656
1657Clipboard and drag-drop use the same type of data format descriptions. The
1658//CLIPFORM// command prepares those descriptions for them; its slot in the "tape"
1659is then passed to the commands that use the formats.
1660
1661: //CLIPFORM(array, count)// :
1662  a group of formats from **clipform_dd[]** array; has a slot in the "tape"
1663: //DRAGDROP(field, DRAGFROM_handler, DROP_handler)// :
1664  add handlers for drag and/or drop to the preceding widgets, with formats in
1665  **void**** field; has a slot for itself and two more for the events
1666: //DRAGDROPm(field, DRAGFROM_handler, DROP_handler)// :
1667  the same but allows the "move" type of drop in addition to "copy" (some programs
1668  use the "move" type when they really should not)
1669: //CLIPBOARD(field, which, COPY_handler, PASTE_handler)// :
1670  add handlers for copy and paste for specified clipboards (//which//: 1 if the
1671  regular clipboard, 2 if the "primary selection" i.e. what is highlighted, 3 if
1672  both at once), with formats in **void**** field; has a slot for itself and two
1673  more for the events
1674
1675
1676The //DROP// event handler receives in its //xdata// parameter a pointer to
1677**drag_ext**;  the //PASTE// event, to **copy_ext** and returns TRUE if
1678successfully imported the data. The //DRAGFROM// and //COPY// events are handled
1679differently from most others; their handlers receive in their //xdata// parameter
1680a slot (dynamically created) with which they then interact to send or receive the
1681data. //DRAGFROM// handler also should return TRUE if it agrees to initiate drag,
1682FALSE otherwise.
1683
1684
1685=== Scripting ===
1686
1687The below commands exist solely to facilitate scripting.
1688
1689: //ALTNAME(name)// :
1690  add another name (identifier) for the preceding widget; has a slot in the
1691  "tape"
1692: //FLATTEN// :
1693  make option names from the preceding option menu or radiobutton pack be
1694  directly referrable from script like widget names (in addition to being
1695  referrable as values); has a slot in the "tape"
1696: //OPNAME(name)// :
1697  set (override) name for the preceding widget
1698: //OPNAME0// :
1699  unset the current name (the initial empty-string one, or the preceding
1700  unattached label) to prevent it mis-attaching to the next widget
1701: //UNNAME// :
1702  hide the preceding widget from scripts (by setting it an impossible name)
1703: //SCRIPTED// :
1704  tell **run_create()** to start a range of "live-scriptable" widgets (those
1705  get extra //ALTNAME// slots automatically added, to make them visible from
1706  script despite being real widgets)
1707: //ENDSCRIPT// :
1708  end a range of "live-scriptable" widgets; has a slot in the "tape" (to tell
1709  script interpreter where the range ends)
1710
1711
1712== Functions and macros ==
1713
1714There are two main groups of functions; the **run_*()** that affect the entire
1715"tape", and the **cmd_*()** affecting a single slot. Also a few assorted helper
1716functions and macros.
1717
1718: **void **run_create_(void **ifcode, void *ddata, int ddsize, char **script);**
1719  build a dialog window out of V-code decription; takes an array with that
1720  description, address and size of the struct that will be copied into its
1721  **ddata**, and an array of script commands or NULL; returns **wdata** of what
1722  got built (possibly already freed, if script was passed in), or NULL if failed
1723: **void **run_create(void **ifcode, void *ddata, int ddsize);**
1724  same without script commands (a convenience macro)
1725: **void run_query(void **wdata);**
1726  query dialog contents using its "tape"; takes dialog's **wdata**
1727: **void run_destroy(void **wdata);**
1728  destroy a dialog; takes dialog's **wdata**
1729
1730
1731: **void cmd_event(void **slot, int op);**
1732  raise event (specified by opcode) on slot
1733: **void cmd_sensitive(void **slot, int state);**
1734  set sensitive state on slot
1735: **void cmd_showhide(void **slot, int state);**
1736  set visible state on slot
1737: **void cmd_set(void **slot, int v);**
1738  set value on slot
1739: **int cmd_setstr(void **slot, char *s);**
1740  set text-encoded value on slot; returns -1 if failed, 0 if value was left
1741  unused (when only the fact of setting something mattered), 1 if set
1742: **void *cmd_read(void **slot, void *ddata);**
1743  read back slot value (as is) given **ddata** (to calculate fields' addresses
1744  faster); returns the value's storage location
1745: **void cmd_repaint(void **slot);**
1746  repaint slot
1747: **void cmd_reset(void **slot, void *ddata);**
1748  reset slot or group given **ddata**; causes the widget(s) to reinitialize
1749: **void cmd_cursor(void **slot, void **cursor);**
1750  set cursor on slot (for its widget's window) given the cursor's slot
1751: **int cmd_run_script(void **slot, char **strs);**
1752  run script on slot; returns -1 if error happened, 0 if //OK// event handler got
1753  activated, 1 if not
1754
1755
1756: **void **get_wdata(GtkWidget *widget, char *id);**
1757  from widget to its **wdata**
1758: **void **wdata_slot(void **slot);**
1759  from slot to its **wdata**
1760: **void **origin_slot(void **slot);**
1761  from event to its originator
1762: **void *slot_data(void **slot, void *ddata);**
1763  from slot to its storage location (its own, //not// originator's), given
1764  **ddata**
1765: **void **find_slot(void **slot, char *id, int l, int mlevel);**
1766  find slot by text name (with explicit length) and menu level (//MLEVEL_*//)
1767: **void do_evt_1_d(void **slot);**
1768  run event handler in slot, defaulting to run_destroy() if NULL there
1769: **void dialog_event(void *ddata, void **wdata, int what, void **where);**
1770  handle dialog buttons' events (from //OKBTN// and //CANCELBTN//)
1771
1772
1773The next three are for those (widget-type-specific) actions that the above
1774functions do not cover. Such actions were not made into functions to avoid the
1775interface ballooning up with functions that are applicable to very few widgets
1776each. Sending requests and receiving responses through a generic interface
1777instead, is convenient enough in practice.
1778
1779: **void cmd_peekv(void **slot, void *res, int size, int idx);**
1780  read extra data from slot, given data's index/id, destination, and size
1781: **void cmd_setv(void **slot, void *res, int idx);**
1782  set extra data on slot, given data's index/id and source; for some functions,
1783  //res// itself is the value (**int** converted to pointer)
1784: **int cmd_checkv(void **slot, int idx);**
1785  check extra state on slot, given state's index/id
1786
1787
1788Now, the indices/ids per slot type, what each does, and what type of data expects.
1789Types are denoted by representative opcodes. Most actions are either get or set,
1790only very few are valid for both; the check actions are not valid for either get
1791or set and vice versa, as in totally unrelated.
1792
1793- //FPICK// :
1794 : //FPICK_VALUE//
1795   get/set the filename with full path, in system encoding: **char[]**
1796 : //FPICK_RAW//
1797   get/set the raw filename; only the file part without path, in UTF8: **char[]**
1798- //PATH// and //PENTRY// :
1799 : //PATH_VALUE//
1800   get/set the filename: **char[]**
1801 : //PATH_RAW//
1802   get/set the raw filename: **char[]**
1803- //LISTCC// :
1804 : //LISTCC_RESET_ROW//
1805   set the row index to reset: **int**
1806- //LISTC// :
1807 : //LISTC_RESET_ROW//
1808   set the row index to reset: **int**
1809 : //LISTC_ORDER//
1810   get sort order: **int[]**
1811 : //LISTC_SORT//
1812   set sort mode: **int**
1813- //LABEL// and //MENUITEM// :
1814 : //LABEL_VALUE//
1815   set label text: **char***
1816- //NBOOK// :
1817 : //NBOOK_TABS//
1818   set show/hide tabs: **int**
1819- //ENTRY// and //COMBOENTRY// :
1820 : //ENTRY_VALUE//
1821   set value: **char***
1822- //TEXT// :
1823 : //TEXT_VALUE//
1824   set value: **char***
1825- **wdata** :
1826 : //WDATA_ACTMAP//
1827   set action map: **unsigned int**
1828 : //WDATA_TABLET//
1829   get name of tablet device: **char****
1830- //WINDOW// :
1831 : //WINDOW_TITLE//
1832   set window title: **char***
1833 : //WINDOW_ESC_BTN//
1834   set slot to react (get "clicked") to //Esc// keypress in window: **void****
1835 : //WINDOW_FOCUS//
1836   set focus to slot (or to nowhere if NULL): **void****
1837 : //WINDOW_RAISE//
1838   set window to raise; value is ignored: **void**
1839 : //WINDOW_DISAPPEAR//
1840   set window to hide from view (to allow a screenshot), or to unhide: **int**
1841 : //WINDOW_DPI//
1842   get DPI: **int***
1843 : //WINDOW_TEXTENG//
1844   set to render text: **texteng_dd***
1845- //COLOR// :
1846 : //COLOR_RGBA//
1847   set current color and alpha: **int[2]**
1848 : //COLOR_ALL//
1849   set current and previous color and alpha: **int[4]**
1850- //SPIN// and //SPINSLIDE// :
1851 : //SPIN_ALL//
1852   set value, min and max: **int[3]**
1853- //COLORLIST// :
1854 : //COLORLIST_RESET_ROW//
1855   set the row index to reset: **int**
1856- //PROGRESS// :
1857 : //PROGRESS_PERCENT//
1858   set progress percentage: **int**
1859- //CSCROLL// :
1860 : //CSCROLL_XYSIZE//
1861   get x offset, y offset, onscreen width, onscreen height: **int[4]**
1862 : //CSCROLL_LIMITS//
1863   get full width minus onscreen width, and full height minus onscreen height:
1864   **int[2]**
1865 : //CSCROLL_XYRANGE//
1866   set x offset, y offset, full width, and full height, for a delayed resize:
1867   **int[4]**
1868- //CANVASIMG//:
1869 : CANVAS_SIZE
1870   set full size: **int[2]**
1871- //CANVAS// :
1872 : CANVAS_SIZE
1873   get onscreen size / set full size: **int[2]**
1874 : CANVAS_VPORT
1875   get viewport (x, y, x + width, y + height): **int[4]**
1876 : CANVAS_REPAINT
1877   set area that needs repaint (x, y, x + width, y + height): **int[4]**
1878 : CANVAS_PAINT
1879   set area you want to repaint (//rgb// = NULL) - bounds will be modified and
1880   buffer allocated / set image data (//rgb// != NULL) - buffer will be painted
1881   into the bounded area: **rgbcontext***
1882 : CANVAS_FIND_MOUSE
1883   get mouse state: **mouse_ext***
1884 : CANVAS_BMOVE_MOUSE
1885   set to nudge mouse cursor by dx, dy: **int[2]**
1886- //FCIMAGE// :
1887 : //FCIMAGE_XY//
1888   set location marker to x, y: **int[2]**
1889- //KEYMAP// :
1890 : //KEYMAP_KEY//
1891   set key to map to slot: **key_ext***
1892 : //KEYMAP_MAP//
1893   get/set keymap: **keymap_dd***
1894- //EV_MOUSE// :
1895 : //MOUSE_BOUND//
1896   check to keep cursor inside canvas' visible area, by scrolling the canvas &
1897   moving the cursor back in; return TRUE if moved it
1898- //EV_DRAGFROM// :
1899 : //DRAG_DATA//
1900   set start & end of data exported through drag: **char*[2]**
1901 : //DRAG_ICON_RGB//
1902   set RGB color (packed) for drag icon (color patch): **int**
1903- //EV_COPY// :
1904 : //COPY_DATA//
1905   set start & end of data exported through copying: **char*[2]**
1906- //CLIPBOARD// :
1907 : //CLIP_TEXT//
1908   set text to export through clipboard: **char***
1909 : //CLIP_OFFER//
1910   check to offer data through clipboard; return TRUE if successful
1911 : //CLIP_PROCESS//
1912   check to request data from clipboard; return TRUE if successful
1913- all regular widgets :
1914 : //SLOT_SENSITIVE//
1915   check sensitive state; return TRUE if sensitive
1916 : //SLOT_FOCUSED//
1917   check focused state; return TRUE if focus in toplevel window is inside the
1918   widget
1919 : //SLOT_SCRIPTABLE//
1920   check scriptability; return TRUE if script flag is set in opcode
1921 : //SLOT_UNREAL//
1922   check unreality; return TRUE if the widget is simulated
1923 : //SLOT_RADIO//
1924   check radio-ness; return TRUE if the widget is radio toolbutton or radio
1925   menuitem
1926- //FONTSEL// :
1927 : //FONTSEL_DPI//
1928   set DPI: **int**
1929
1930
1931Finally, the macros.
1932
1933: //VSLOT_SIZE// :
1934  size of a slot, in void pointers: 3
1935: //GET_DDATA(wdata)// :
1936  from **wdata** to **ddata**: **void***
1937: //GET_WINDOW(wdata)// :
1938  from **wdata** to its toplevel widget's slot: **void****
1939: //GET_REAL_WINDOW(wdata)// :
1940  from **wdata** to actual toplevel widget: **void***, in fact **GtkWidget***
1941: //NEXT_SLOT(slot)// :
1942  from slot to the next one: **void****
1943: //PREV_SLOT(slot)// :
1944  from slot to the previous one: **void****
1945: //SLOT_N(slot, n)// :
1946  from slot to the n-th one after: **void****
1947: //TOOL_ID(slot)// :
1948  get toolbutton's action code: **int**
1949: //TOOL_IR(slot)// :
1950  get toolbutton's right-click action code: **int**
1951: //ACTMOD(action, mode)// :
1952  combine action and mode into action code
1953
1954
1955== Callbacks ==
1956
1957Most events are handled by **evt_fn** function (the default one):
1958
1959**void (*evt_fn)(void *ddata, void **wdata, int what, void **where);**
1960
1961The //ddata// and //wdata// parameters are precisely that; the backing struct, and
1962the "tape". The //what// parameter is the event's opcode, and the //where// is
1963its slot.
1964
1965One handler for all (or most) events happening in the dialog, is the usual
1966pattern when using V-code. When inside it need do different things depending on
1967what is happening to what, there are 3 ways to make the decision.
1968
1969One is to use the "//what//" parameter; it is mostly done to separate out final
1970button presses (the //op_EVT_OK// and //op_EVT_CANCEL//) from everything else.
1971
1972Another is to do "**void *cause = cmd_read(where, ddata);**" and compare the
1973"//cause//" to addresses of variables and/or fields that V-code commands refer to.
1974This serves for most types of controls, and with them **cmd_read()** is usually
1975needed anyway, to get the newly-modified value (a few are "self-reading" but that
1976is rarely significant; only affects when to save the previous value if you need
1977it).
1978
1979The third is to do "**void **slot = origin_slot(where);**" and compare the slot
1980with controls' slots stored using //REF()// commands. This in practice is only
1981needed when several //BUTTON()//s are in one dialog; with them all having
1982//CLICK// events and not referring to any memory locations, their slots are the
1983only thing differentiating them.
1984
1985Now, some events need send some extra data to their handler. Those are handled by
1986**evtx_fn** function:
1987
1988**void (*evtx_fn)(void *ddata, void **wdata, int what, void **where, void *xdata);**
1989
1990What, specifically, the handler receives in //xdata//, depends on the event.
1991
1992: //CROSS// :
1993  TRUE if entering, FALSE if leaving: **int** converted to pointer
1994: //SCROLL// :
1995  pointer to **scroll_ext**
1996: //EXT// from //LISTCX// :
1997  row index where right click happened: **int** converted to pointer
1998: //EXT// from //COLORLIST//:
1999  pointer to **colorlist_ext**
2000: //DROP// :
2001  pointer to **drag_ext**
2002: //COPY// :
2003  pointer to **copy_ext**
2004
2005
2006Yet other events not only send extra data to the handler, but also await a return
2007value from it. The value, for nearly all, is simply TRUE or FALSE, and the function
2008handling them is **evtxr_fn**:
2009
2010**int (*evtxr_fn)(void *ddata, void **wdata, int what, void **where, void *xdata);**
2011
2012What the handler receives in //xdata//, and what its return value means, again
2013depends on the event.
2014
2015: //KEY// :
2016  pointer to **key_ext**; return TRUE if the key was handled, FALSE otherwise
2017: //MOUSE//, //XMOUSE//, //MMOUSE//, //MXMOUSE//, //RMOUSE//, //RXMOUSE//:
2018  pointer to **mouse_ext**; return TRUE if the mouse event was handled
2019: //EXT// from //CANVAS//:
2020  pointer to **rgbcontext**; return TRUE if something was rendered into buffer
2021: //DRAGFROM// :
2022  pointer to **drag_ext**; return TRUE to initiate drag
2023: //PASTE// :
2024  pointer to **copy_ext**; return TRUE if data successfully imported
2025: //MULTI// :
2026  pointer to **multi_ext**; return 0 if error, 1 if success and the //xdata// not
2027  needed anymore, -1 if success and the struct should be kept (not freed)
2028
2029
2030Handling some events can include system-dependent interactions with their
2031//xdata//. Instead of saddling some poor unsuspecting widget with those, an
2032"intercessor" capable of processing that is passed as the originating event, in
2033the "//where//" parameter. The intercessors' opcodes are //op_EV_*// to their
2034events' //op_EVT_*//; their functions are described under the headings
2035//EV_MOUSE//, //EV_DRAGFROM//, and //EV_COPY// in the "Functions and macros"
2036chapter above. They are accessed like this: "**cmd_setv(where, pp, DRAG_DATA);**".
2037
2038
2039== THE END ==
2040