A C Graphical User Interface [add on to Allegro] by Christer Sandberg
The Manual of CGUI 2.0.4


Using CGUI

When you want to compile and link your own program that uses CGUI you need to know the following Fundamental in CGUI is the event driven approach. This means that your program doesn't need to check for certain operator actions like mouse clicks and key presses. Instead you must write functions that will be called by CGUI when those events occure. Therefore you must inform CGUI which function to call. You do that by passing a pointer to your function when creating any object that needs such a callback. Your callback function may do whatever it likes, e.g. start a new dialogue (i.e. put another window above the current) or close the current window or exit (by calling exit) or call `StopProcessEvents', etc.

A few word to those that are not used with function pointers:
Maybe you find the declaration of functions in CGUI a bit messy because of the callback parameter, but don't worry - when writing your code for the actual call you will find it quite ok.
The C-code in the callback may look like the code of any of the functions you have written before, there are no special requirements except that the declaration (the function head) must match that of the function pointer - so there will be a void* pointer involved in most cases.

   my_type *my_data;
   AddButton(DOWNLEFT, "OK", my_okfun, my_data);
   void my_okfun(void *data)
      my_type *my_data = data;
      /* Do whatever you need */
The declaration of the function passed to AddButton must be like above (i.e. taking a single parameter of type void*). To use the data you need to copy the pointer to one of a type that is not void* like above. That type must of course be the one of the last parameter passed to AddButton.
When passing your function pointer and data pointer lika this, e.g.
   AddButton(DOWNLEFT, "Label", fptr, dataptr);
You should think like this:
When the button is pressed by the user, the call fptr(dataptr); will be done, and you must write the code of fptr to match that.

Lots of important functions in CGUI needs function pointer and void* pointers, and they should all be handled similarly.
There are also several examples in the directory "cgui/examples" which can be useful to look at.

int InitCgui(int w, int h, int color_depth);

This function initializes CGUI. This includes setting a graphic mode as specified by the parameters. CGUI will also take over the keyboard and mouse, and this is done by the initialization function. A desktop will be created automatically.
There are some alternative initialization functions: InitCguiLoadMode, InitCguiFullscreenMode, InitCguiWindowedMode and InitCguiKeepCurrent that differs only in how the graphics is initialized. Se the sections for these if you want to know details.
Parameters: Simple initialisation: just call the initialization function at program start (i.e. without initializing any part of Allegro, CGUI will do that for you).
Whenever CGUI fails to set a graphics mode (this applies also to the alternative initialization functions) it will do the following: The first attempt is to try another colour depth. If the requested colour depth was If the above fails, it will try with a lower pixel resolution and the same sequence as above including the requested colour depth. This will be repeared until an accepted screen mode was found or there are only modes using 8 bits colour depth left (in which case it will try all resolutions from 640x480 and less in 8 bpp, and if still no one is accepted it will terminate the program by a call to exit).
You can do subsequent calls to `InitCgui' to change the the screen mode (resolution and/or colour depth). Some CGUI-objects needs to be notified about the change, so to handle a screen mode change properly you should use this method instead of setting it directly with Allegro's set_gfx_mode() (if you still prefere the latter way you should call InitCgui afterwards). Returns always non-0 (does never fail).
See also: CguiUseUTF8, InitCguiLoadMode, InitCguiFullscreenMode, InitCguiWindowedMode, InitCguiKeepCurrent, DeInitCgui.
int InitCguiLoadMode(void)

Will look for a full screen mode setting in the current config file.
   Width = 1024
   Height = 768
   Colour_depth = 15
The above numbers are a examples, you can preset these values to whateever you like. If you make CGUI's screen mode selector available for the user of your program that dialogue will uppdate the values. If no settings were found, then 1024x768x32 will be used.
See also: InitCgui, DeInitCgui.
int InitCguiFullscreenMode(void)

Will try to pick the current screen mode from the system and then use these when trying to set a full screen mode.
See also: InitCgui, DeInitCgui.
int InitCguiWindowedMode(void)

Will try to keep the current screen mode of a windowed environment and try to set the CGUI screen to windowed mode, with the same colour depth, and a window size equal to the next smaller possible resolution.
See also: InitCgui, DeInitCgui.
int InitCguiKeepCurrent(void)

Will no set the grapics mode at all. This requires the graphic to be initialized before calling InitCguiKeepCurrent (i.e. call set_gfx_mode first).
In paletted mode CGUI will make no changes to the palette.
See also: InitCgui, DeInitCgui.
void DeInitCgui(void);

Closes all windows, removes the event queue and frees all data allocated by CGUI.
DeInitCgui will be automatically called at exit, so normally you don't need to call it yourself.
NOTE! It is important that you call DeInitCgui NOT from within any callback from CGUI, i.e. the call must be after the event processing has terminated (immediately after the call to ProcessEvents()).
If graphics were initialized before the first call to InitCgui() then the screen content will be restored to what is was by that time, but the screen mode will not.
See also: InitCgui.
void CguiUseUTF8(void);

By default CGUI assume strings to be in 8 bit ascii. To change this and force handling UTF-8 encoding of unicode, you can call this function. You should call it before calling CguiInit().
int cgui_ver, cgui_rev, cgui_minor_rev, cgui_release_date;

int HookExit(int id, void (*ExitFun)(void *data), void *data);

This function installs the callback function `ExitFun'. This is a pointer to a function written by you. It will be called by CGUI when the object `id' is destroyed, and it will be passed the pointer `data'.
If `id' refers to an object that has an "action-callback", like e.g. a button that has a call-back that will be called when the button is clicked, and such a function destroys the object `id' then `ExitFun' will be called when the "action-callback" is finished. To be more precise, `ExitFun' will be pushed on to the event queue. Installing an `ExitFun' may be useful if you want to free some memory allocated for e.g. a dialog, and wants a somple way to catch all possibilities of its closing.
Returns 1 if id referes to an existing object, otherwise 0.
See also: InitCgui, DeInitCgui, CloseWin, Remove, Destroy.


Windows are areas that are visible on the screen and they serve as containers for objects. Windows will be placed at a position decided by the windowing system itself - it will try to centre them around the current cursor position. Windows can by default be moved with the mouse (by gripping the window header). There is always one window that is "in focus" i.e. that receives mouse commands and keyboard commands. If the same hot key is defined in several windows, the event of pressing that key will go to the focused window. So hot keys defined only in windows that are not in focus will be ignored. Hot keys may however be defined globally, and these will be handled even no matter which window is in focus. By default windows works like a stack: opening a new window makes that one be the active one displayed on top of the others. Closing a window lets the previous one be the active (top) window. There are several ways to override this, see MkDialogue for details. About requesters: This is a special type of windows, that wait until the user answers, i.e. you can use it without the "event driven" style of the code, but rather like the classical linear programming like when using scanf, getchar etc. You should however know that the event processing is still running while your function is waiting for the requester to return. So if other events like serial port, time-events etc. occur, these will be put into the event queue and will be processed in proper order while the requester is up. Processing these events can, if needed, open new windows and requesters without any problem.
See also: Objects, Containers, Menus, Listboxes, Tabwindows.
int MkDialogue(int width, int height, const char *title, int options);

Creates a new window. The window is however not completed (and not visible) until you call `DisplayWin'. In between you should add some objects to make it meaningful.
Windows can be closed by `CloseWin'.
The created window will be the child of the window that is in focus when calling `MkDialogue'. The new window will automatically be set in focus when it is created. It will also be set to be the "operating window" (i.e. the one into which objects will be put when created).
In case you need to create multiple windows there are some window behaviour that needs to be discussed: In CGUI windows are arranged in a tree relation, where there is a virtual root and the the desktop (created by `InitCgui') is tha child of that. So if the first window you create has default settings it will be the child of the desktop. The properties that acomplishes the above behavior in CGUI are controlled by some optional flags listed below.
When using which? By default the window will be a child and a child is by default "modal", (non-floating).
Parameters: Return value: an id (in the same domain as objects).
See also: DisplayWin, CloseWin, ScrMode, SetFocusOn, Req, SetWindowPosition.
void DisplayWin(void);

`DisplayWin' must be called to complete a window and to make it visible. When adding various object into an opened window, these objects can not be completed immediately (e.g. their sizes and positions can in general not be computed until all of them are there). `DisplayWin' will do this completion, and also draw the objects onto the screen.
`DisplayWin' may also be called later on to make all its object refreshed. Such a repeated call will also re-build the window, which is necessary if you remove or add objects to the window after the first call to `DisplayWin'.
The window that will be affected is the one in focus.
See also: MkDialogue, Refresh, SetFocusOn.
void CloseWin(void *dummy);

Closes an open window. The parameter will not be used, it's there just to conform to the standard event-handler form - just pass a NULL-pointer.
The window that will be affected is the one in focus.
See also: MkDialogue, DisplayWin, SetFocusOn.
void SetWindowPosition(int x, int y);

By default a window will be opened at a position that is assumed to be convenient for the user (se `MkDialogue' for details). This automatic behaviour can be overridden by calling `SetWindowPosition' with the desired position (upper x,y is the upper left corner of the window) after `MkDialogue' but before `DisplayWin'.
See also: GetWinInfo, MkDialogue, DisplayWin.
void DesktopImage(BITMAP *bmp);

Sets the desktop image (the screen background).
If bmp refers to the screen, then a copy of it will created. (This memory will be properly released when CGUI terminates.) If bmp is a memory bitmap, this function will just take a copy of the pointer, so it is your responsibility to keep it as long as CGUI is alive, and then do destroy_bitmap(bmp).
If the size of the bitmap doesn't fit to the current size of the screen, then the following will be done: The desktop is not updated until `Refresh' is called. Use ID_DESKTOP for `id' when calling `Refresh'.
int Request(const char *title, int options, int width, const char *format, ...)

Opens a requester window of the same type as 'Req', but here you can specify the width of the text and also pass a format string of 'printf' type together with the necessary variable arguments.
Parameters: Return value: as for `Req'.
See also: Req, MkDialogue.
int Req(const char *title, const char *format);

A window for prompting the user for a simple question or givin some brief information in a simple way.
Parameters: In opposit to other windows functions, this one will wait until the user has clicked one of the buttons. Before it returns it will close itself, so don't do that.
Example of simple usage:
 switch (Req("Operation request",
            "Do you really want to do this?|~Yes|~No|Confirm_each ste~p")){
 case 0:
 case 1:
 case 2:
Return value: The push-button number that the user selected. 0 is the first button in format string, 1 is the next etc.
See also: Request, Labels.
void RedrawScreen(void);

Redraws the entire screen. All windows that are at least partly visible on the screen will be redrawn.
void GetWinInfo(int id, int *x, int *y, int *width, int *height);

Returns the coordinates and size of the specified window. The results will be given in screen coordiantes (with (0, 0) in upper left corner).
See also: SetWindowPosition.
int CurrentWindow(void);

Returns the id number for the current operating window.
See also: SetOperatingWindow, SelectContainer.
void SetOperatingWindow(int winid);

Sets a new window to be the the "operating window". Most functions that operates on objects require an id-key for reference. For your conveniance that is not necessary when creating new objects, they will be put into the most recently created container in the most recently created window. That is the "operating window". Normally the operating window is the same as the one in focus. Occasionally you may later on want to add some objects to a window that is not in focus. Then you must use `SetOperatingWindow' (and maybe also SelectContainer) before adding the objects. Just use the id-key returned when the window was created, and pass it to SetOperatingWindow.
See also: CurrentWindow, SelectContainer.
int MkProgressWindow(const char *wlabel, const char *blabel, int w);

A simple progress-bar window containing a progress bar and a status field.
Parameters: Return value is the id of the window. This can be used to update the current value by calling UpdateProgressValue'.
See also: UpdateProgressValue, AddProgressBar.


Window objects may be of different types. Below is a list of the "simple" types. You can find contaners and menus in other sections. A window object is an object that is in a window. It is assigned a rectangular area within this window, and it has the full responsibility for that area. This responsibility includes: These tasks are performed automatically - you don't need to bother about _how_ to do it, but maybe you need to know that it works in this way (in fact an object also has some more tasks that we don't talk about for the moment). As a consequence of the above, there will be problems if simple objects like push buttons etc., overlap each other (which of them should draw and which of them should receive mouse messages?). To make it easy for you to avoid overlapping, you can use direction commands rather than specify the coordinates of the object; see the "Direction commands for object positioning" section. How do you know the width and height of an object? In fact you normally don't need to bother about this in CGUI - the objects will adapt their size to be large enough. For example: Some types of objects need explicit coordinates (e.g. the width field of edit boxes), see the specific object type for more information. Also note that to create a nice interface you may use the container facility to create subgroups of objects. Containers are discribed in another section.
See also: Containers, Windows, Menus, Listboxes, Tabwindows.
int AddButton(int x, int y, const char *label, void (*CallBack) (void *data), void *data);

This function creates the standard type of push button.
Parameters: The default behaviour is to ignore right mouse button clicks. Return value: an identification key to the object.
See also: CguiLoadImage, AddIcon, Direction commands for object positioning, Labels.
int AddCheck(int x, int y, const char *label, int *sel);

This is a check box which toggles between being on and being off when the user clicks it. `sel' points to an integer, which is 1 for on and 0 for off. Return value: an identification key to the object.
See also: AddRadioButton, AddDropDown, AddCheck, Direction commands for object positioning, Labels.
int AddFlip(int x, int y, const char *label, const char *const*strs, int *sel);

This is like a check box, but displayed differently: `strs' is an array of two strings, the first of which will be displayed when `sel=0' and the second when `sel=1'. Return value: an identification key to the object.
See also: AddRadioButton, AddDropDown, AddCheck, Direction commands for object positioning, Labels.
int MkRadioContainer(int x, int y, int *var, int direction);

To create a group of radio buttons, call first this function, then add the radio buttons using `AddRadioButton', and finally call `EndRadioContainer' to finish.
Return value: an identification key to the container. Prameters: Return value: an identification key to the container.
See also: EndRadioContainer, AddRadioButton, AddFlip, AddCheck, AddDropDown, Direction commands for object positioning.
int AddRadioButton(const char *name);

Adds a radio button to a radio button sequence. The first button added will get number 0, next 1 and so on. To start a radio button sequence, call `MkRadioContainer'.
Return value: The id number of the button.
Parameter: Return value: an identification key to the object.
See also: MkRadioContainer, EndRadioContainer, AddButton, AddHandler, MkMenuRadio, Labels.
void EndRadioContainer(void);

Terminates a sequence of radio buttons. If you don't terminate it, subsequent objects will go into the same container and your window will not look very nice.
See also: AddRadioButton, MkRadioContainer.
int AddIcon(int id, int x, int y, const char *iconname, void (CallBack)(void*), void *data);

This function adds an icon object to the specified node. An icon object is a movable bitmap (i.e. the user can "drag and drop" it with right mouse button). The image is specified in the label text, just like with buttons.
Currently you can only place icons on the desktop, so pass ID_DESKTOP for id.
You can obtain the current position of the icon by calling `GetObjectPosition' (this can be useful e.g. if you want the program to arrange the icons in the same way next time you start it).
Return value: The id number of the icon.
Parmeters: Return value: an identification key to the object.
See also: AddButton, GetObjectPosition, Labels, CguiLoadImage.
int GetObjectPosition(int id, int *x, int *y, int *wx, int *wy);

Gives the current position (top left corner) of an object.
Parameters: Return value: 1 if ok 0 if error (i.e. invalid id).
See also: AddIcon, GetWinInfo.
int AddDropDown(int x, int y, int width, const char *label, int *sel, const void *data, int n, void (*CallBack) (const void *data, int i, char *s));

Drop down boxes can be used for the same purpose as radio buttons, i.e. let the user make a selection from several alternatives. The selection will be reflected in the program as one of the values in the range [0..n-1] The DropDownBox uses another way for presentation of the alternatives. The DropDownBox requires less space in the dialogue window than the radio-buttons. On the ohter hand it is required one extra command to make the different alternatives visible (dropped down). If there are lots of alternatives or if there are lots of controls in the dialogue window, the DropDownBox is to prefer.
To achieve the result of a selection - just examine your value pointed to by sel. This can typically be done when the dialogue window is closed. Optionally this may be done by an additional call-back function, which will be called after each selection made by the user. See AddHandler
If the DropDownBox shall be used just to display a certain state or setting, rather than to provide a control to the user: use `DeActivate'
Parameters: Return value: an identification key to the object.
See also: AddDropDownS, Activate, DeActivate, AddHandler, Direction commands for object positioning, Labels.
int AddSlider(int x, int y, int length, int *ctrl, int start, int end, int option, int id);

int AddSliderFloat(int x, int y, int length, float *ctrl, float start, float end, int ndecimals, int option, int id);

The default direction of a slider is horizontal.
Parameters: Return value: an identification key to the object.
int AddDropDownS(int x, int y, int width, const char *label, int *sel, const char * const *strs, int n);

This is a simplified version of AddDropDown. I can be used only if your text-alternatives happens to be an array of pointers to strings. In other respects it is equivalent to AddDropDown.
Return value: an identification key to the object.
See also: AddDropDown, Direction commands for object positioning.
int MkCanvas(int x, int y, int width, int height, void (*CallBack)(BITMAP *bmp, int x, int y, void *data), void *data);

This function will create a canvas on which your function `CallBack' may draw whatever it want. It will be called each time the mouse generates an event, i.e. when the position or button state has changed. The current co-ordinates will be passed to the call-back together with the private data. If you will also examine all key-presses, you can install a new KeyBoard handler.
Parmeters: Return value: an identification key to the object.
See also: InstallKBHandler, Direction commands for object positioning, SetBlitLimit, cgui_use_vsync.
void SetBlitLimit(int x1, int y1, int x2, int y2);

This function may be used to reduce the area of an object that CGUI blits to screen. It must be called prior to the call to Refresh, and has effect only during that call (you must call it each time). The coordinates shall be related to the object and are inclusive. The function is only meaningful to call for canvas object blitting. The call to SetBlitLimit is not identical to a call to set_clip.
extern int cgui_use_vsync;

A global variable that may be used to switch off vsync in CGUI (it is set to 1 by default). CGUI uses vsync when Refresh or DisplayWin is called directly or when these functions are indirectly called.
int AddTag(int x, int y, const char *tag);

Tag is simple text object with the default grey background and it doesn't handle any events, and it is not outlined in any way.
Parameters: Return value: an identification key to the object.
See also: AddStatusField, AddTextBox, Direction commands for object positioning.
int AddEditBox(int x, int y, int width, const char *label, int conversion_code, int string_buffer_size, void *data);

This function creates an edit box, which lets the user edit the text "data", and is formatted according to "format".
Return value: id number of the edit box.
Parameters: Return value: an identification code to the object.
See also: AddHandler, GetEditData, SetEditData, TabOnCR, SetFocusOn, AddStatusField, AddTextBox, Direction commands for object positioning, Labels.
int TabOnCR(int id);

Makes the carriage returns work like tabs in an edit-box, i.e. focus moves to next object in the tab-chain. Useful if you have a number of edit-boxes in a dialogue window, and the user are supposed to enter a large amout of data. Returns 0 if it fails (i.e. id is invalid) else non-0.
See also: AddEditBox.
void GetEditData(int *scan, int *ascii, int *offset);

If you adds an optional callback to an edit-box (with a call to AddHandler) you may be interested in the current keypress, or maybe of the current position in the string. Maybe you are also interested in changing these values. Use GetEditData and SetEditData functions for this.
See also: AddEditBox, SetEditData, AddHandler.
void SetEditData(int scan, int ascii, int offset);

If you adds an optional callback to an edit-box (with a call to AddHandler) you may be interested in the current keypress, or maybe of the current position in the string. Maybe you are also interested in changing these values. Use GetEditData and SetEditData functions for this. Note! You are only allowed to call these function from within the callback function. If not, the calls will be ignored.
See also: AddEditBox, GetEditData, AddHandler.
void CguiEditBoxSetSelectionMode(int mode);

If `mode' is 1 then the current selection in edit boxes will be replaced with the letter corresponding to the pressed key or with the clipboard text in an paste operation. If `mode' is 0 the current selection will remain unchanged. The default is 0. The setting is global.
See also: AddEditBox.
int AddStatusField(int x, int y, int width, void (*FormatFunc)(void *data, char *string), void *data);

This function creates an object in which a single row-text may be displayed. The field reserved for text is of fixed width and height (the height is enough to display one row of text) and is outlined by a frame. The text will be right aligned and clipped if necessary. The text will be produced by the function `FormatFunc', which is a function that you must write. `data' is a pointer to any of your data, and it will be passed to `FormatFunc' whenever called. The difference to `AddTag' is that the status-field may change the text from time to time. A typical use is to display some value or text that will change from time to time.
Save the id-number and when, for some reason data changes, just call Refresh(id);
The status field will be put into the current node. It may be a good idea to create a specific container using `StartContainer' e.g. at the bottom of a window, for this purpose.
Parameters: Return value: an identification key to the object.
See also: AddTextBox, AddEditBox, AddTag, Refresh, StartContainer, Direction commands for object positioning.
int AddProgressBar(int x, int y, int w, int h);

Adds a progress bar. The current value can be updated by a call to `UpdateProgressValue'.
Return value: an identification key to the object.
See also: UpdateProgressValue, MkProgressWindow.
int UpdateProgressValue(int id, int percent);

Updates the value of the progress bar `id'. The bar will updated on the screen
Returns 1 on sucess, 0 if `id' does not exist or does not refer to a progress object.
See also: AddProgressBar, MkProgressWindow.
int AddTextBox(int x, int y, const char *string, int width, int nrows, int options);

Creates a simple multi-row text-box. This can be used for various purposes, typically: The default behaviour (if `nrows' and `options' are set to 0) is to automatically control the line-feeds. The text will be broken into rows to fit the specified width. Sequences of more than one whitespace will be displayed as one single space. The line-feeds will be inserted at whitespace positions (if possible). The height of the box will be the height that is required to display the text. This behaviour can be overridden, see details below
A copy of the text pointed to by `string' is used. Parameters: Use `UpdateTextBoxText' if you need to change the displayed text.
Return value: an identification key to the object.
See also: AddStatusField, AddTag, AddEditBox, Direction commands for object positioning, MakeStretchable, UpdateTextBoxText.
void TextboxHighlighting(int id, int bgcolor, int textcolor, int row_index);

Makes a certain row in a textbox highlighted. This row does not follow the text if scrolled. It is a fixed row w.r.t. the textbox widget.
const char *TextboxGetHighlightedText(int id);

Returns a pointer to a string with the text of the row that is highlighted. The memory of string belongs to the textbox.
void TextboxScrollDownOneLine(int id);

Scrolls the text down one line. This will have no effect if the textbox has no scrollbar.
int UpdateTextBoxText(int id, const char *string);

Changes the current text of the textbox `id' to the string pointed to by `string'. A copy of the text is made. Returns 1 on sucess, 0 if `id' is not valid or does not refer to a text object.
See also: AddTextBox.
int HookSpinButtons(int id, int *var, int delta1, int delta2, int minv, int maxv);

Creates a pair of spin-buttons. These let the user change the value of the integer variable pointed to by `var'. The value will be increased by a mouse-press on the up-arrow, and decreased by a press on the down- arrow.
Return value is the id of the conainer that will be created for the spin-buttons.
Parameters: Return value: an identification key to the object.
See also: AddEditBox, AddStatusField.
void Refresh(int id);

Redraws a specific win-object. If the object contains (recursively) other object these will also be refreshed.
void Activate(int id);

This function activates an inactive object. An object must be active to take notice about events like mouse-clicks and hot-keys. Some object types reflects their `active state' by the colour of its text label.
To make a change visible it is necessary to call Refresh(id);
The default state of an object after its creation is active.
See also: Refresh, DeActivate.
void DeActivate(int id);

The function makes an object inactive, i.e. the object will not take notice about events like mouse-clicks and hot-keys. Some object types reflects their `active state' by the colour of its text label. To make a change visible it is necessary to call Refresh(id);
An inactive object may be re-activated by a call to the function `Activate'.
See also: Refresh, Activate.
void SetObjectGrippable(int id, void *(*Grip)(void *src, int id, int reason), int flags, int buttons, void *data);

Set the specified object as grip-able, which means that the user may grip the object by use of mouse-button (with the intention to later on drop it somewhere else).
NOTE! An object can't be both "slidable" and "grippable".
This means that objects that by default has the slidable propery set, will loose that when beeing set to "grippable". For the moment this will probably only affect edit-boxes, which may loose the ability to get text marked by use of the mouse if they are set "grippable" with use of left mouse button (i.e. mouse down and moving will be interpreted as a drag-drop in stead of as marking text in that case, since there are obviously no way to ditinguish between the two operations).
You must be aware that the drag-drop mechanism can be used very dynamically, and carefully handle your pointers. Several disjunct or overlapping drag-drop channels may be used in parallel (use the flags to distinguish the data objects dropped). The hot-key handler is in work during the drag-drop operation, so the user can e.g. close the window from where the object was gripped, implying that the object returned by grip must not rely on its window being open.
See also: SetObjectDroppable, SetObjectSlidable, SetListDroppable, RegisterDragFlag, UnRegisterDragFlag.
void SetObjectDroppable(int id, int (*Drop)(void *dest, int id, void *src, int reason, int flags), int flags, void *data);

Set the specified object as drop-able by installing the call-back function `Drop'. "Drop-able" means that the user may drop an object (previously gripped by use of the mouse) on it.
`Drop' will always be called by CGUI at least 3 times for each drag-and-drop action that is completed by the user. The parameter reason in the call-back informs which type of call that is concerned. The `Drop'-function will only be invoked if the following conditions are fulfilled: The interpretation of the reason parameter at call-back: Parameters to `SetObjectDroppable':
See also: Activate, DeActivate, SetObjectGrippable, SetObjectSlidable, SetListDroppable.
void SetObjectSlidable(int id, int (*Slider)(int x, int y, void *data, int id, int reason), int buttons, void *data);

This function is used by CGUI internally and is exported just for completeness, for the moment I can't see any use for it in an application program.
NOTE! An object can't be both "slidable" and "grippable".
`SetObjectSlidable' set the specified object as slidable, which means that the user may grip the "hot" area of the object by use of mouse-button (with the intention to slide the hot area (or maybe a part of it like a handle) to another part of the object, within the visible area).
Parameters to SetObjectSlidable:
See also: SetObjectDroppable, SetObjectGrippable.
void SetObjectDouble(int id, void (*DoubleCall)(void *), void *data, int button);

Makes an object being double-clickable. "DoubleCall" will be called after a successful double-click. Assigning double-click e.g. to the left button allows the left button to be used for single clicks to on the same object (the single click is not issued until the "doubleclick" delay has expired). In addition the same object may be either possible to slide or to grip with the same button (the click and double-click events will not be launched until "slidedelay" or "gripdelay" respectively time has expired)
int ToolTipText(int id, const char *text);

Applies the text `text' to the object `id' to be used as a tool-tip text. If `text' contains `_' characters these will be interpreted as new lines.

About tool tips: These are messages popping up to the user when moving the cursor over an object. This can be needed for 2 purposes

Return value: 1 on sucess else 0 (i.e. `id' is not valid).
int SetView(int id, int flags);

Specifies how the object `id' will be viewed. If you switch any of the two first flags you need to call `DisplayWin' ance again if that has already been done. Also the tool tip viewing can be controlled by 'SetView'.
Parameters: If an object has both a label and an icon and none of the flags SV_HIDE_LABEL and SV_HIDE_ICON are specified (the default case) then both of them will be drawn as a part of the object.
Only one of the flags SV_PREFERE_BRIEF, SV_PREFERE_LONG, SV_ONLY_BRIEF and SV_ONLY_LONG can be specified. The default setting is SV_PREFERE_LONG.
If `id' is some container rather than a simple object this command will affect also all the descendants of `id'.
Return value: 1 on sucess else 0 (i.e. `id' is not valid).
void CguiSetToolTipDelay(int delay);

This function sets a start delay that cgui will wait until a tooltip is displayed. The setting is global. The default value is 0.
void CguiSetToolTipAnimation(int step, int delay);

This function sets tool tip animation. The tool tip will slide in from left moving `step' pixels with `delay' milliseconds between each move. A step of 0 disables the animation of tooltips. The setting is global. The default value is 0 for both step and delay.
void Remove(int id);

This function will call `Destroy' but it will also clean up the screen from the object(s), i.e. the background of the containing node will be drawn on the area of the former object. The containing node will however not be rebuild, i.e. all the remaining objects will keep their positions.
You don't need to call `Destroy' when you want to close a window, `CloseWin' will take care of all objects in it.
In general the userinterface will be better if you avoid to remove single objects. If your program goes into a state such that some object(s) will be redundat or constitue illegal selecteion(s), then it is better to deactivate them.
See also: Destroy, CloseWin, DeActivate, Activate.
void Destroy(int id);

This function frees all memory associated with the specified object `id'. If the object contains other objects, like e.g. containers and tab-windows do, all the sub-objects will be removed too (recursively). The screen will remain unchanged.
See also: Remove, DisplayWin.
int GetPressedButton(int id);

Returns the mouse button (left or right) that was latest pressed on the specified win-object. Return value: 1 on sucess else 0 (i.e. `id' is not valid).
void PointerOn(int id);

Places the mouse pointer above the object.
void ModifyHeader(int id, char *newlabel);

Modifies the window-header text with the text of "newlabel". An additional call to refresh is necessary to make the changes visible.
int AddHandler(int id, void (*Handler)(void *data), void *data);

Installs the application call-back function "Handler" and "data" into a window object.
Objects like check-boxes, radio-buttons etc. normally doesn't need any call-back, so when creating these you don't need to specify any call-back function. In some cases it may however be convenient to get a call-back for user events to these object types. E.g. if your program needs to activate/deactivate other objects directly when the state of an check-box is changed. In these case "AddHandler" may be used for installing such an optional handler.
Not all type of objects support this facility. Return value 0 tells that the installation failed. Currently the following object types supports the optional Callback to be installed: edit-boxes, radio-buttons, check-boxes, drop-down boxes, sliders and flip-objects.
In case of an edit-box, you are probably interested in getting some information about the editing that is in progress (maybe you want to distinguish between a letter-key-press and a carriage-return key-press). Call for GetEditData to get available info. For edit-boxes your call-back will be invoked before handling the event (the pressed key), in case of other object types the event will be processed first.
Parameters: Return value: 1 on sucess else 0 (i.e. `id' is not valid).
See also: GetEditData.
int SetMouseButtons(int id, int buttons);

Mouse button alternatives: LEFT_MOUSE, RIGHT_MOUSE
Thid function changes the specified objects sensibility for clicks to the specified mouse button(s). (default is the left mouse button)
Return value: 1 on sucess else 0 (i.e. `id' is not valid).
int RegisterDragFlag(int flag);

This is for the "drag-and-drop" facility. Some part of your application may use some flag(s) for some object(s). If there is a risk that the same flags may used for different purposes (e.g. the printer-monitoring function uses bit 31), you should register the flags before using them.
Return value: 0 if none of the bits was already registered, else the occupied bits.
Use the return value to determine if it is safe to activate the drag-and-drop.
NOTE! Dropping of unexpected objects will _in best case!!_ crash your program!
int UnRegisterDragFlag(int flag);

This function unregister the flag(s). Return value: 0 if none of the bits was already registered, else the occupied bits.
void RegisterRefresh(int id, void (*AppUpd)(int id, void *regdata, void *calldata, int reason), void *regdata);

Will register a callback-function for the widget `id'. This function will be called, whenever your program calls `ConditionalRefresh'
Since the registration is associated with a widget it there will be an automatic unregistration when that widget is removed.
The name indicates that the purpose of the call-back is to make some kind of screen update, which was also the original purpose. However, the functionality may be used for arbitrary purposes.
If you register several "refreshers" and not all of them needs to be involved each time, you can let the function calling `ConditionalRefresh' make a directed "message" by passing different `reason' parameters and let the AppUpd functions examine it when called.
If several AppUpd functions will call `Refresh' for different or maybe even the same object, that would have lead to a sequence of blits to screen. However during the `ConditionalRefresh' call the blitting is temporary tyrned off, and a final blit is issued at end of the call (a minimal area will then be blitted)
See also: Refresh, ConditionalRefresh.
void ConditionalRefresh(void *calldata, int reason);

Will call all `AppUpd' functions registered by `RegisterRefresh'. The calls will be performed in a top-down manner over the widget tree, starting at the root window. If an `AppUpd' function removes the widget that it is registered for, the refresh will stop.
Even if several of the called `AppUpd' calls `Refresh' for one or several widgets, there will be a single screen update at the end.
See also: Refresh, RegisterRefresh.
void Click(int id);

This function simulates a single mouse click (left) on the object `id'
int MakeStretchable(int id, void (*Notify)(void*), void *data, int options);

This function creates a "handle" on the right and bottom edges of the object, and a "handle" at the right bottom corner of it. This makes it possible for the user to adjust the width and height of the object. The handle in the corner makes it possible to stretch both width and height at the same time. The "handles" are invisible, but the mouse cursor will change its shape when moving it over them.
All objects are allowed to be stretchable, but not all will notify the stretching, e.g. a container that have an ADAPTIVE size, will after the re-sizing operation immediately return to its previous size calculated as the minimum to show all its contents (i.e. ADAPTIVE overrides stretching).
Parameters: Return value: 1 on sucess else 0.
See also: GetSizeOffset, SetSizeOffset, continous_update_resize.
int GetSizeOffset(int id, int *x, int *y);

This function may be used to get the changes in size of an object. A change of the size may only occur if it is stretchable (or if the size has been adjusted with SetSizeOffset). Return value: 1 on sucess else 0 (i.e. `id' is not valid).
See also: SetSizeOffset, MakeStretchable.
int SetSizeOffset(int id, int x, int y);

This function may be used to adjust the size of an object. A default size of an object is always calculated at creation time (normally this is the size enough to carry its label or icon). This size may be changed by this function. Typically it is used in conjunction with GetSizeOffset to restore the size of objects modified by user after a window has been closed and re-opened.
Note: If justification commands like FILLSPACE are used in conjunction with the relative positioning of an object (like DOWNLEFT etc) this may override the offset setting. The function must be called before the call to 'DisplayWin' to have effect.
Return value: 1 on sucess else 0 (i.e. `id' is not valid).
See also: DisplayWin, GetSizeOffset, MakeStretchable.
int InsertPoint(int id);

Moves the "logical insertion point" where new objects will be added to after the `id' object. Any new objects that you add after calling this function will be positioned as if they were added right after `id' was added.
This can sometimes be meaningful when you make changes in a container that already has object positioned with "direction commands".
The new "logical insertion point" is local to the container where `id' lives.
Changes that are made in a window after it has been made visible (by a call to `DisplayWin') will not be visible until `Refresh' is called for appropriate part of the window. If "direction commands" are used, the appropriate parts, which is normallay the entire window, of the window also needs to be re-built (by a call to `ReBuildContainer') before the refresh. Both will be done for the entire window if you call `DisplyWin' again.
Returns 1 if id referes to an existing object, otherwise 0.
See also: Objects, SetOperatingWindow, SelectContainer, Direction commands for object positioning.
int MkVerticalBrowser(int x, int y, void (*CallBack) (void *data), void *data, int *viewpos);

Creates a vertical "browsing object" consisting of one bar with a slider handle for browsing and scrolling, and two scroll buttons.
The usage is quite staight forward, and the easiest way to unserstand is to look into the browse example in the `examples' directory of CGUI.
For a detailed description the following naming convention is introduced: The "browsing object" performs all calculations needed and call a function of yours (see below) when the user interacts with the "browsing object". At some point your program may want "scrolled area" to move within the "view port". It can then inform the "browsing object" about the new state, see `NotifyBrowser'.
The size of the "scrolled area" may for some reason change during the program execution. This will be the case e.g. if the thing to display is an image and you provide the user with a tool to zoom the image or to change to some (different sized) image. Also in such cases you need to use `NotifyBrowser' to tell the "browsing object" about the new size.
During program execution the size of the "view port" may change (as well as the prefered size of the "browsing object") in which case you can use `SetBrowserSize' to inform the "browsing object" about it. (A change of the "view port" size typically can occure if the "browsed object" is possible to re-size by the user.
Parameters: If the current "scrolled area" is smaller than the size of the "view port" (set by `SetBrowserSize') then the "browsing object" will deactivate itself.
The sliding handle will change its length as expected if the the "scrolled area", "view port" or "browsing object" changes its size.
Return value: 1 on sucess else 0.
See also: NotifyBrowser, SetBrowserSize, Direction commands for object positioning.
int MkHorizontalBrowser(int x, int y, void (*CallBack) (void *data), void *data, int *viewpos);

Creates a horizontal "browsing object". See `MkVerticalBrowser' for details.
See also: MkVerticalBrowser.
int NotifyBrowser(int id, int step, int scrolled_area_length);

Forces the "browsing object" `id' to update its status according to the parameters. NOTE! You also need to call `NotifyBrowser' if you change the value of the variable pointed to by `viewpos' (see `MkVerticalBrowser') so the "browsing object" can make necessary re-calculations according to the new position.
Parameters: Return value: 1 on sucess else 0.
This function makes no update of the screen.
See also: MkVerticalBrowser, SetBrowserSize.
int SetBrowserSize(int id, int view_port_length, int browsing_length);

Specifies the dimensions for a browsing object.
Parameters: Returns 1 if sucess else 0.
This function makes no update of the screen. It can be useful if the browsed object is re-sized (see `MakeStretchable').
See also: MkVerticalBrowser, NotifyBrowser, MakeStretchable.
extern int continous_update_resize;

This is a global variable that controls the updating behaviour of an object when stretched by the user.
If continous_update_resize is set to 0 (default), then the object that is stretched by the user will not show its new size until the user releases the mouse button that gripped the stretch-handle.
If continous_update_resize is set to 1, then the object that is stretched by the user will continously show the current size.
See also: MakeStretchable.

Direction commands for object positioning

In CGUI you can specify the position of object using co-ordinates explicitly, like

   AddButton(13, 132, "Cancel", my_func, my_dataptr);
However, you will probably re-design your window a number of times during development, and each time you will probably need to re-calculate the position of the "Cancel".
In order to make the development process more convenient for you, CGUI provides the "Direction command" facility. This means that you just need to tell the direction of the object related to the recent ones. The call will instead look like e.g.:
   AddButton(DOWNLEFT, "Cancel", my_func, my_dataptr);
The position fo the "Cancel" button will be calculated in run-time and it will adapt to the contents above as well as the run-time calculated size of other objects. It's highly recommended that you use the "direction commands" instead of explicit co-ordinates. It's also highly recommended that you combine this with the 'ADAPTIVE' feature of windows and containers to make your life easier.
The following 3 "direction commands" are the most "easy to use" ones, when using them think of adding object like when typing text (from left to right, from top to bottom): The below ones are used by CGUI itself, and may occasionally be useful for other purposes. The following additional fill flags may be combined with a direction command. The main point is create rows or columns with nice looking object groups. Normally you should set the same flag to all objects in such an "object row" or "object column". You are allowed to use the flags above to fill the space around any sequence of objects, including other sub containers. However the result will not always be as expected if their sizes are 'ADAPTIVE' since the size of such containers are calculated after the positions of the entire object tree has been calculated.

The "align"-flags will align the object to an edge of the container (or window).
Both flags may be applied to the same object.
If you use ALIGNRIGHT for more than one object on the same "object row", these will overlap (there is an analogous problem with ALIGNBOTTOM).

The "insertion point" of a new object will normally be after the previously added one in the same container. You can modify the insertion point using the function `InsertPoint'.

Id-numbers of objects

Functions that creates visible objects returns an id-number. This number is unique.
For simple usage of the GUI you don't need this id. For advanced usage there may sometimes be necessary to later on (when the window creation has already been finished by a DisplayWin-call) refer to an object. In these cases you have to save the id-number returned by the object-creating function, and make use of it when you are about to call the CGUI-function that reqiures the id-number.
Typical CGUI-functions that needs the id-number are Activate, DeActivate, Refresh, Remove, Destroy.
Since the id-number is unique for the entire application you can as well access objects in an "old" window (not the top one). Specially the `Refresh' may be useful in this case.
Some of the CGUI-functions will apply to an entire group of objects if you refer to a node object like a container, a list, a window etc.
If the specified id-number is not found the operation is ignored.
Note! Removing a single object will not give you any problem (i.e. CGUI will not give you any), but it is not intuitive for the user - deactivation is better than removing. Adding objects to an already existing ADAPTIVE window may raise the problem for your program to determine where it may be free space in the window to avoid overlapping (remember that the direction command will refer to the "previous object" object).
Some objects are of "container type". That is an object that contains other objects. Examples of containers:

The functions that create containers will also return an id-number.


A menu bar has to be "opened" first. The menu bar serves as a container for the different menus. It is required one call for each menu. Each of them will establish a call-back function. It is necessary to terminate the sequence of created menus by "closing" the container. Each menu is connected to a call-back function which is a part of the application. This call-back function will be activated when the user wants to drop down the menu. The only thing it shall do is to create the items in the dropped down menu. Each of these are in the same manner connected to a call-back function, which may either drop yet another (sub-)menu or perform a direct action.
See also: Objects, Containers, Windows, Listboxes, Tabwindows.
int MakeMenuBar(void);

Creates a container specially designed for entering menus-items in a window. The point is to issue subsequent calls to MkMenuBarItem. NB! The sequence of calls to MkMenuBarItem must be terminated by a call to EndMenuBar. If you forget this other objects will be placed together with the menu-items, and it will all look junky.
MakeMenuBar returns an id-number.
See also: EndMenuBar, MkMenuBarItem.
void EndMenuBar(void);

Closes a container opened by MakeMenuBar.
See also: MkMenuBarItem, MakeMenuBar.
int MkMenuBarItem(const char *text, void (*CallBack) (void *), void *data);

Creates one menu-item within an opened menu bar (opened by MakeMenuBar).
Return value: the id of the menu item (non-zero) Parameters:
See also: MakeMenuBar, MkMenuItem, MkMenuRadio, MkMenuCheck.
int MkScratchMenu(int id, void (*CallBack)(void*), void *data);

`MkScratchMenu' will immediately drop down a menu and invoke `CallBack'. The position of the menu will be at the mouse cursor position. Return value: the id of the drop-menu (non-zero) Parameters:
See also: MkMenuBarItem, MkMenuItem, MkSingleMenu.
int MkSingleMenu(int x, int y, char *label, void (*CallBack) (void *), void *data);

`MkSingleMenu' does the same work as `MakeMenuBar' + `MkMenuBarItem' + `EndMenuBar' with one call to `MkMenuBarItem'. I.e. it creates amenu-bar containing one menu-item. It looks slightly different (it is indicated that it is a menu by a "down-arrow".
Return value: the id of the menu (non-zero) Parameters:
See also: MkMenuBarItem, MkMenuItem, MkScratchMenu, Direction commands for object positioning, Labels.
int MkMenuItem(int sub, const char *text, const char *shortcut, void (*CallBack) (void *), void *data);

Creates one menu-item within a dropped down menu. There is actually two different types that can be created by this function: (1) A menu-item that is the selection point for a sub-menu, and (2)a menu-item that is just a simple selection (that closes all menus).
Return value: the id of the menu item (non-zero) Parameters:
See also: MkMenuBarItem, MkMenuRadio, MkMenuCheck, MkGroove, Labels.
int MkMenuRadio(int *selvar, int n, ...);

Works similar to AddRadioButton, but is intended only for menus. Return value: the id of the menu item (non-zero) Parameters:
See also: AddRadioButton, MkMenuCheck, MkMenuItem.
int MkMenuCheck(int *checkvar, const char *text);

Works similar to AddCheck-button, but is intended only for menus. Return value: the id of the menu item (non-zero) Parameters:
See also: MkMenuRadio, MkMenuItem, AddCheck.
int HookMenuClose(void (*CloseHook)(void*), void *data);

This function installs CloseHook. This is a pointer to a function written by you. It will be called when the menu is closed. HookMenuClose will do nothing if it is not called from a "menu drop-down" -function like the call-back passed to `MkMenuItem'. Actually it will do the same thing as `HookExit', with the difference that you don't need to now the id-number (which you normally don't know). The benefit of installing the CloseHook may be e.g. to get the chance to free memory allocated by the drop-down function. If the menu is closed because the user made a selection of an item (or some item in a sub-menu) the call-back of that item will be called prior to CloseHook. Returns non-zero on sucess.
See also: MkMenuItem.
int MkGroove(void);

A horizontal groove will be put into any node as a delimiter. The purpose is to visually group objects into logical groups. This may be specially useful in menus.
Return value: the id of the groove
See also: Menus, Objects.


About Container objects: "Container" is a recursive (or "nested") construct. This means that a container may contain an arbitrary number of objects that themselves may be containers or "simple" objects like push-buttons etc.
The nesting may be done in arbitrary number of levels.
A container is just a rectangular fraction of its parent window (or container), normally used to group together some objects to make the window more attractive for the user.
Sometimes you may want it simply for grouping objects without seeing the container itself. Another time it may be used to make a more distinct group of objects with a frame and a label informing user about its content. Yet another time it may be used just to force a sequence of objects to be of the same size.
See also: Objects, Windows, Menus, Listboxes, Tabwindows.
int StartContainer(int x, int y, int width, int height, char *label, int options);

The objects in a window may be grouped into containers. Objects created between StartContainer and EndContainer will refer to the co-ordinates of the container. This also applies to direction commands (like TOPLEFT, DOWNLEFT, RIGHT..) as well as explicit x,y-co-ordinates. The objects will "belong" to the container. This means that if the container later on is deleted (by a call to `Destroy') all the objects in the container will also be destroyed. After `EndContainer' has been called, all subsequently added objects will be put into the same window or sub-window as where the container is (it works like "closing" the container for input).
Return value is the id of the container.
See also: EndContainer, JoinTabChain, Direction commands for object positioning, Containers.
void EndContainer(void);

Closes a contaioner created by `StartContainer'.
See also: StartContainer.
void SelectContainer(int id);

This function will select the container (node) `id' as input for subsequently created objects. If the node `id' is not in the currently operating window, the window of `id' will be set to operating.
See also: StartContainer, SetOperatingWindow.
void SetDistance(int hdist, int vdist);

This function sets the space used by CGUI when deciding positions for objects that has been added with the "direction commands" like `RIGHT', `DOWN' etc. and when deciding the size of a container or window that is created with the `ADAPTIVE' size.
You can do the same, but specify measurments more detailed, by using `SetSpacing'.
See also: SetSpacing.
int SetSpacing(int id, int left, int h, int right, int top, int v, int bottom);

This function sets the space used by CGUI when deciding positions for objects that has been added with the "direction commands" like `RIGHT', `DOWN' etc. and when deciding the size of a container or window that is created with the `ADAPTIVE' size.
The settings will affect the container or window specified by `id'. The changes will be visible the next time you call `DisplayWin' or `ReBuildContainer'.
Parameters: The return value is 1 if `id' is a valid id of a container, else 0.
See also: MkDialogue, StartContainer, Direction commands for object positioning, ReBuildContainer, DisplayWin, SetDistance.
void ReBuildContainer(int id);

This function will re-build a container. If you add objects into a container when the window has already been displayed (with a call to DisplayWin) you can use this function make up the container only. Calling DisplayWin once again will also work fine, but will update the entire window.
See also: StartContainer, DisplayWin, EmptyContainer.
void EmptyContainer(int id);

This function will destroy all objects within the specified container. The image of the objects will not be removed (the pixels will remain unchanged in the bitmap of the node). To remove their appearance from the window you must also re-build the node, e.g. by a call to DisplayWin();. This is preferably done after inserting new objects into the node (the need to insert new objects is probably the reason why 'EmptyContainer' was called). May be useful if minor changes needs to be made to a window (typically extending or shrinking the window).
See also: StartContainer, ReBuildContainer, DisplayWin.


A list-box is a node that contains a number of row-objects. If necessary there will be a "browse-handle" and two scroll-buttons beside the listbox (they will appear when the list contains more objects than there are rows). You must write at least 2 functions (normally 3). You must make 2 function calls (e.g. `AddList' and `SetIndexedList'). The functions you have to write is: This maybe sounds more tricky than it really is, here is an example:
   int row_text(void *rowdata, char *s)
      int *row=rowdata;
      sprintf(s, "Data is %d", *row);
      return 0;

   void *index_creater(void *listdata, int i)
        int *arr=listdata;
        return &arr[i];

   void foo(int id, void *rowdata)
      /* Do something */

   void make_dialog_with_list(void)
        /*array and n must be static or dynamic memory, not normal local
        static int array[100]={1,2,3,4,5}, n=5, id;
        MkDialogue(ADAPTIVE, "Test-window", 0);
         /* add more objects here ... */
        AddList(TOPLEFT, array, &n, 60, LEFT_MOUSE, row_text, foo, 10);
        SetIndexedList(id, index_creater);
         /* ...or here if you need */
The list properties in CGUI is controlled by the following global variables: It works like this: Each time a list-box is created, CGUI will use the values of these variables. If you use several list-boxes in your application and for instance want one of these to use a fix font you have to set CGUI_list_font to the fix font you have loaded, and then restore the origin font after the list was created.
The meaning of the variables: CGUI_list_font, CGUI_list_column_delimiter_color and CGUI_list_rowdelimitercolor will be reset next time calling InitCgui.
See also: Windows, Menus, Containers, Tabwindows, Objects, CguiSetColor.
int AddList(int x, int y, void *listdata, int *n, int width, int mousebt, int (*RowTextCreater)(void *rowdata, char *s), void (*Action)(int id, void *rowdata), int norows);

Creates a list box. NOTE! The list-box is not finished until you have also called either `SetLinkedList' or `SetIndexedList' (which both requires a pointer to a function that you have written). To make a list box work you will need to write a least one more small function (yet more may be needed, depending on how you configure the list). This second "small function" is one that calculates which string that shall be drawn provided some data element.
Parameters: There are lots of options to configure a list box to fit your taste, here are some global variables that affect the apperance of lists. Their usage are as follows: See also the links for functions to configure list boxes.
The return value is the id of the list box.
See also: ListTreeView, Refresh, BrowseTo, RefreshListRow, SetIndexedList, SetListGrippable, NotifyFocusMove, SetDeleteHandler, SetInsertHandler, HookList, Listboxes, SetListColumns, CguiLoadImage.
int SetIndexedList(int listid, void *(*ApplicationDataAtIndex)(void *listdata, int i));

int SetLinkedList(int listid, void *(*IterateLinkedListOfApplication)(void *listdata, void *prev));

You have to use one (and only one) of these functions to tell the list box which function to call when a data item for a row is needed. (this will happen e.g. when drawing a row or when the user clicks or drags a list row or some other event that the list box is responsible for). If the data that you want to display in the list box is organized as a linked list, then the function `SetLinkedList' is to prefer. If your list-data is an array then the function `SetIndexedList' might be more convenient for you.
Parameters to these functions: A typical function for array data may look something like:
   void *my_index_creater(void *listdata, int i)
      struct MYDATA *d=listdata;
      return < d[i];
A typical function for linked lists may look something like below. Note that if prev is set to NULL then the function is supposed to extract a pointer to the first element using the listdata pointer.
   void *my_next_creater(void *listdata, void *prev)
     /* Here we assume that a pointer to the list head was passed to AddList */
     struct MYDATA **m=listdata;
     struct MYDATA *p=prev;
     if (p==NULL)
       return *m;
       return p->next;
Both functions may of course use whatever methods to calculate the data to return (e.g. the "data" pointer may be a pointer to any structure which contains a pointer to the head/array, the array may be an array of pointers etc.). Just another example for linked lists:
   void *my_next_creater(void *listdata, void *prev)
     /* Here we assume that a pointer to the an empty head record was passed to AddList */
     struct MYDATA *m=listdata;
     struct MYDATA *p=prev;
     if (p==NULL)
       return m->next;
       return p->next;
And yet a (maybe more practical) example:
   void *my_next_creater(void *listdata, void *prev)
     /* Here we assume that a pointer to some other struct was passed to AddList */
     struct MYDATA_MAIN *m=listdata;
     struct MYLINK *p=prev;
     if (p==NULL)
       return m->list_head;
       return p->next;
The return value from SetIndexedList is 1 if a listid is a valid id of a list, else 0.
See also: MkDialogue, DisplayWin, AddList.
int ListTreeView(int listid, int level_width, int (*IsLeaf)(void *rowobject), int options);

This function will turn a normal list box into a tree viewer. In most respects it is just an ordinary list, however special list facilites like list columns and "hooked lists" are not supposed to work.
Your tree implementation may be whatever you like, you can use either an iterator function for arrays (using `SetIndexedList' to install it) or for linked lists (using `SetLinkedList' to install it). The return value (if not NULL) will always turn up later as the first parameter of your iterator function as the root data of that level in the tree.
Note however, if you use the array style iterator, then it should be prepared to be called with any size of the 'index' parameter and return NULL in case the index is too big (the list box will use that to draw some conclusions about the number of nodes at that level).
Notable is also that the 4:th parameter, 'n', passed to `AddList' (i.e. the "number of list items") has no meaning for a tree viewer, so it will be fine if you just pass NULL to AddList.
The tree view section of the list box is a part of the rows in the list so if you want to let the user expand and collaps nodes in the tree you need to at least pass LEFT_MOUSE for the 'mousebuttons' parameter to AddList.
The list box itself will manage the expanding and collapsing of tree nodes. Your call-back function handling row click will only be called when the row is clicked, not when the node is expanded or collapsed.
Parameters: The return value is 1 if a listid is a valid id of a list, else 0.
See also: AddList, ListTreeSetNodesExpandedState.
int ListTreeSetNodesExpandedState(int listid, int (*IsExpanded)(void *data));

This function will set the expanded or collapsed state of all nodes that are not leafs in the tree. To see the change you need to also call `Refresh'. Normally the expanded/collapsed state is changed by the user. This function can however be useful in case you want to pre-set some initial state of the nodes.
Parameters: The return value is 1 if `listid' is valid id of a list, else 0.
See also: ListTreeView, AddList, ListTreeSetNodeExpandedState.
int ListTreeSetNodeExpandedState(int listid, int new_expanded_state, void *data);

This function will set the expanded or collapsed state of the specific node that holds the application data `data'. Normally the expanded/collapsed state is changed by the user. This function will however override the users choice.
Parameters: The return value is 1 if `listid' is valid id of a list and a node pointing to `data' was found, else 0.
See also: ListTreeView, AddList, ListTreeSetNodesExpandedState.
int InstallBelowListEndCallBack(int listid, void (*CallBack)(int id, void *data), void *data);

This function will install the call-back `CallBack' that will be called with `data' whenever the user clicks below the last current list item (i.e. on an empty row).
Parameters: The return value is 1 if a listid is a valid id of a list, else 0.
See also: AddList.
int CguiListBoxSetToolTip(int listid, int mode, int options);

This function alters the tool tips viewing mode of a list box.
Tool tips for the list box rows can be useful in listboxes with possibly long text or if there are several resizeable columns so the text on rows may be hidden. The text of the tool tips will be the text of all columns concatenated with double spaces between the columns or just the single text of the row if there are no columns.
Parameters: The return value is 1 if a listid is a valid id of a list, else 0.
void CguiListBoxRowSetBar(int color, double percentage);

This function may be useful in case you want to use a list-box to show the rows like in a bar diagram.
Parameters: This function has only affect when called from a list-box row drawing function, and it will only affect the currently drawn row. If the list-box uses columns, the function only have effect when the call-back is called for the first column.
int CguiListBoxRowGetClickedColumn(int rowid);

Returns the column that a certain listbox column was clicked on last time, or -1 in case the information can not be obtained.
See also: CguiListBoxSetColumnSelection, SetListColumns.
void CguiListBoxSetColumnSelection(int listid, int state);

Sets or resets the property "column selection" of a list-box. "Column selection property" This means that when the user clicks on a row then only the clicked column will be highlighted. This may be useful in combination with CguiListBoxRowGetClickedColumn. If state is 0 it is turned off, else on. By default it is turned off.
See also: CguiListBoxRowGetClickedColumn, SetListColumns.
int SetListColumns(int listid, int (*RowTextCreater)(void *rowdata, char *s, int colnr), int *widths, int n, int options, char **labels, void (*CallBack)(void *data, int id, int i), void *data);

This function partitions the list into `n' columns. Note that this `RowTextCreater' will replace the one previously passed in the call to AddList, so you may as well just pass NULL when adding the list to the window. Texts longer than specified column will be clipped.
See also: AddList.
int RefreshListRow(int id, int i);

If you only need to update one row of a list, and know the index of your data, a call to "RefreshListRow" will do that for you. UpdateListRow will not update the scroll-buttons or the browse-bar. Returns 0 if id is not a list reference otherwise 1 Parameters:
See also: Refresh.
int BrowseToF(int id, int i);

The data with the index 'i' will be selected (highlighted) and viewed as the first (top) row of the list-box. If 'i' is out of range then either index 0 or the highest possible index will be chosen instead. If the list exists returns 1 else returns 0. If `id' refers to list within a chain of lists, the browsing will affect all the lists in chain where "listid" exists.
See also: AddList, RefreshListRow, BrowseTo, BrowseToL, Refresh.
int BrowseToL(int id, int i);

The data with the index 'i' will be selected (highlighted) and viewed as the last (bottom) row of the list-box (or as the last row of the list if the list contains less data items than there are rows in the list). If 'i' is out of range then either index 0 or the highest possible index will be chosen instead. If the list exists returns 1 else returns 0. If `id' refers to list within a chain of lists, the browsing will affect all the lists in chain where "listid" exists.
See also: AddList, RefreshListRow, BrowseTo, BrowseToF, Refresh.
int BrowseTo(int id, int i, int uncond);

The data with the index 'i' will be selected (highlighted) and the list will, if necessary, be browsed to make i come in view. If 'i' was "above the top" of the list-box prior to the call then it will be the top row after. If 'i' was "below the bottom" of the list-box prior to the call then it will be the bottom row after. If 'i' is already viewed in the list-box, then it will just be focused. In this case you maybe want the entire list-box to be unconditionally re-drawn (e.g. to make sure that some of your re-sorting or other updates are correctly reflected), then set 'uncond' to true. If the list exists returns 1 else returns 0. This function may be used not only for browsing, but also for re-selecting or pre-selecting a specific row in a list that you want to set focus on. If 'id' refers to list within a chain of lists, the browsing will affect all the lists in chain where "listid" exists.
See also: AddList, BrowseToL, BrowseToF, RefreshListRow, Refresh.
int SetListGrippable(int listid, int (*Grip)(void *srcobj, int reason, void *srclist, int i), int flags, int buttons);

Defines the list-rows in a list to be Grippable. Parameters:
See also: SetListDroppable, SetObjectGrippable, AddList.
int SetListDroppable(int listid, int (*Drop)(void *destobj, int reason, void *srcobj, void *destlist, int i, int flags), int flags);

Defines the list-rows in a list-box to be drop-able. The "button" parameter specifies if left or right button is allowed for dropping. The parameter "flags" see: SetObjectGrippable. The specified call-back function "Drop" will be called in the following cases: Drop will always be called when the mouse cursor goes over the row with a gripped object, the "reason" will then be DD_OVER_DROP. Drop must at this call determine if it accepts to be dropped on, and in that case return 1 otherwise 0. If returned 0 there will be no more call until next time the mouse goes over the edge of the object. If the object from the latest grip has been successfully dropped, Drop will be called a second time and the "reason" will now be DD_SUCCESS. The return value will be ignored this time. The gripped object will be notified later on about the successful drop. The parameter "destlist" passed to Drop will be the same address as "list" (the pointer previously passed to the list-creation function), "i" will be the index in the list and reason will be either of DD_SUCCESS or DD_OVER_DROP. The parameter "srcobj" is the source (the gripped) object, just transferred from a Grip-function. This must not necessarily be an object in another list. The parameter "flags" passed to Drop is the "and"-ed result of the flags for the gripped and dropped object. This has already been examined and will always be non-0, i.e. the drag-drop operation is legal according to your specification. The flag-variable is only passed as an extra info. The parameter "destobj" is the object pointer of the dropped row, i.e. the pointer created by the `ApplicationDataAtIndex' of the list dropped on.
See also: SetObjectDroppable, SetListGrippable.
int SetListDoubleClick(int listid, void (*CallBack)(int id, void *data, int button), int button);

Sets a list to be double-clickable by installing yet one call back. This `CallBack' is analogous to the `Action' that you passed to `AddList' for single click call backs. See also `SetObjectDouble' for details.
Returns 1 if listid refers to a list, otherwise 0.
See also: SetObjectDouble, AddList.
int HookList(int listid, void *listdata, int *n, int width, int events, int (*RowTextCreater)(void *data, char *s), void (*Action)(int,void*));

Lists may be chained together. This means that they are controlled by one common browse-bar and common scroll-buttons. This is useful when displaying lists containing records with different items and the different items need to be individually selectable.
This function hooks a new list to the right of another list. The first list must be created with a call to AddList.
The creation of list is not finished until a call to either `IterateLinkedListOfApplication' or `ApplicationDataAtIndex' is done, see AddList for info about these functions.
Returns the id of the new listbox if listid is valid otherwise 0.
See also: AddList.
int SetDeleteHandler(int listid, void (*CallBack)(int rowid, void *object));

Associates DELETE-key presses to the list "listid". The list will only recognise the key-press if is active (in focus).
Returns 1 if listid refers to a list, otherwise 0.
See also: AddList, GetMarkedRows.
int SetInsertHandler(int listid, void (*CallBack)(void *list, int index));

Associates INSERT-key presses to the list "listid". The list will only recognise the key-press if is active (in focus). Returns 1 if listid refers to a list, otherwise 0. Parameters:
See also: AddList.
void **GetMarkedRows(int listid, int *n);

This function returns a pointer to an array of list-object pointer, those that for the moment are marked (blue).
This may typically be of interest in e.g. a callback installed by `SetDeleteHandler'. If the user has made a multi-row selection and wants to have them all removed it may be nicer to give a message like "Remove all this 17 ...?" rather than 17 requests like "Remove this..." .
If it fails or if there are no selected items the return value will be NULL and the value pointed to by `n' will be set to 0. The returned pointer points to dynamic allocated memory, which the caller has the responsibility to free when no longer used.
See also: AddList, SetDeleteHandler.
int GetListIndex(int rowid);

This function returns the index of a certain row in a list. 'id' must refer to an row-object of a list-box (and will be passed to the callback- function of the list-box). If id do not refer to a list-row it will fail and return -1
See also: AddList.
int NotifyFocusMove(int listid, void (*CallBack)(int id, void *rowobject));

This functions makes an initialisation so that your program will be notified by a call to `CallBack' when a row in a list gets focus. Return value: 1 if successful else 0 (no good listid) Parameters:
See also: AddList.


A tab-window is a node within a regular window. It consists of the tab-bar (a row of tab-selectors) at the top, and the rest of the node which will display different sets of object depending on which tab that is currently selected.
The tab-bar is limited to one row of tabs (or "selectors"). These actually works similar to radio-buttons, but looks like "tabs". There must be at least one tab. Each tab has a text-label.
When the user clicks on a tab, your call-back function associated with that tab will be invoked (see AddTab). The point is that the call-back function shall create all the objects corresponding to the tab. The regular functions for creating objects may be used, which implies the possibility of nested tab-windows.
If there is not space enough for all the tabs the excess ones will be clipped, which is not as bad as it seems. However: The main point with tabs-windows is to make quick access to the different controls, and this is not not fulfilled anyway if you add too many tabs.
See also: Windows, Objects, Menus, Containers, Listboxes.
int CreateTabWindow(int x, int y, int width, int height, int *status);

Creates the node object of the entire tab-selector. Returns object-id.
Return value is the identification key for the entire tab-window (including the tab bar at the top).
See also: AddTab.
int AddTab(int id, void (*callback)(void *data, int id), void *data, const char *label);

Adds one tab into the bar of tabs in a tab-window. The callback, which is a function you must code, will be called when the tab is clicked by the user or initially by DisplayWindow(). The callback is not supposed to open a new window. The only thing it shall bother about is to create the objects for the tab-subwindow. This has always been cleaned before callback is invoked (i.e the objects created by a previous selection has been removed before call). The callback shall not refresh the objects in the tab-window, this will also be done automatically after return.
All objects created by the callback will be but in the tab-window. If absolute co-ordinates are used for such objects (x,y) these shall refer to the upper left corner of the free area in the tab-window.
Like other objects tabs may be added also after the window has been built with a call to DisplayWin. The same applies to removal of tabs.
See also: DisplayWin, CreateTabWindow.
void HookLeaveTab(void (*callback)(void *data), void *data);

This function registers 'callback' to be a function that will be called with 'data' when a tab in a tab-window is left. The tab will be left either because the user selects some other tab in the same tab-window or because the entire window is closed.
HookLeaveTab must be called when generating the tab-window (i.e. by the function installed by 'AddTab'), only at this stage the tab-window is prepared to receive such a call.
The purpose is to give your program the possibility to release memory that you needed to allocate for the objects in the tab-window.
See also: AddTab.


A "hot-key" means that a key pressed by the user invokes a function call. Creating hot-keys may be done in following four ways: Hot-keys associated with an existing object will be automatically removed when the object is removed (which normally will be done when closing the window).
Hot-keys created with SetHotKey will be removed when the node which it is associated with, are removed. Such hot-keys may also be removed selectively by just calling Remove and pass the id received from `SetHotKey'.
When assigning hot-keys explicitly there is no check if the key is already used. If the same hot-key is assigned to multiple objects, it is not defined which one will be selected when the user presses the key. You may use the function IsHotKey to avoid ambiguous hot-keys.
The scope of hot-keys is normally a window. An exception from this are menus which have their own scope...or to be correct: this is no exception since menus are implemented as windows... Tab windows are not independent windows, and the objects in "hidden tab-windows" does not exist, so there will be no conflict if same keys are used in different tab-windows.
A special hot-key feature is the tab-chain. Any number of objects may be linked together in the tab-chain. There is one tab-chain in each window (possibly empty). Selectable objects (i.e. such objects that are used for user input) will automatically join the tab-chain when they are created.
The tab and back-tab keys are reserved for the tab-chain. One of the objects within the chain are pre-set to be in "tab-focus" when the window is created (by default this will be set to the first one in the chain). When the user presses the tab or back-tab key the "tab-focus" will move to the next or previous object in the chain.
The "tab-focus" means that the object is highlighted, and that it will catch subsequent ENTER and/or CRTL-ENTER key presses. The ENTER-key matches left mouse-button and CTRL-ENTER right mouse-button, so the later requires the object to be pre-set to receive right mouse clicks.
The chain is circular. An object in the tab-chain that is currently deactivated will not get the tab-focus, it will be by-passed if reached by a tab key-press.
The order in which the object joins the tab-chain controls their position in the chain. By default the joining is their creation order.
Containers may also join the tab-chain (optionally). The effect is that the container itself will take one position in the chain. While the container is in "tab-focus" any object within it may be in "sub-focus", which in this case is the real focus notified by the user and sensible for enter/ctrl-enter. The user can move the sub-focus only by using the arrow-keys. This requires that the objects within the container are grouped and positioned in a tabular manner (the sub-focus will go the object next to left/right/below/above following the x/y-coordinate of the current sub-focused object. This implies that it will not work properly if there are containers nested within the one joining the chain, only one level is possible.
If an object within the tab-chain is selected by use of the mouse (e.g. if it is clicked), then the focus is moved to it.
There are functions to re-arrange the default order in the tab-chain, to force the focus to some object and to achieve info about which object that is currently in focus.
void AutoHotKeys(int mode);

Possible modes: 0 (turn off) or 1 (turn on)
In default mode CGUI will automatically try to generate short-cuts for text-labelled visual objects. With this function you can alter that mode. You may need this e.g. when you use text chosen by the user for labels and the number of labels can be quite large. In such case the time to calculate which letters that are unique can be quite long, or in worst case infinite.
int JoinTabChain(int id);

When objects like buttons, check-boxes, list-boxes etc are created they will automatically be linked into a `tab-chain' (strict sequential and flat in the tree-formed window). The tab-chain defines which objects that may be set in focus by the user (using the tab/backtab keys) and it also defines the order between these objects. The order of the automatic joining will be the order in which the objects were created.
You can use `JoinTabChain' to add objects that do not join the chain automatically (e.g. canvas-objects) or to customise the order between them by re-joining.
Not only simple objects like buttons can join the tab chain, but also containers (e.g. radio-containers, list-boxes etc.). If the user tabs to a container the selection of a certain object within the container can be done by use of the arrow-keys. It is not meaningful to join a container in which there are more containers (i.e. recursive constructs), since there is no way for the user to control the focus movement within the sub-sub-container.
`JoinTabChain' will first remove the object `id' from the chain if it is already there, and then insert it after the currently focused object. The focus is not changed.
Returns 1 on success and 0 if it fails. The parameter `id' shall be the id-key of an object (returned by the creating function).
See also: SetFocusOn.
int SetFocusOn(int id);

When a window is created the first created object within the window that joins the tab-chain will be in focus. The meaning of "beeing in focus" is that it will be drawn highlighted in some manner and it is ready for input. For simple objects like buttons, check-boxes etc. this means that a subsequent enter key-press will have the same effect as a click. For edit-boxes it means that it is ready to let the user type in text (the text-cursor is blinking). For nodes like menu-bars, radio-containers, list-boxes etc it means that the user may make a sub-selection of an object with use of the arrow-keys.
This function explicitly sets the focus on the object `id'. It must be a selectable object (i.e. it must be in the tab-chain). You can call `SetFocusOn' immediately after you finnished the window building process by a call to `DisplayWin', or later to e.g. highlight a newly performed action by the user.
`SetFocusOn' updates the view of both the previus and new focus.
There are some different cases of the object `id': Returns 1 on success and 0 if it fails.
The parameter `id' can be the id-key of any type of object (returned by the creating function).
See also: JoinTabChain, BrowseTo.
int GetCurrentFocus(int id);

Returns the id-key of the object that is currently in focus.
If `id' is 0 the id-key of the window currently beeing in focus will be returned.
If `id' referes to a window then the focused object within the tab-chain of that window will be returned.
If `id' referes to a container that has joined the tab-chain, the focused (simple) object within that container will be returned.
See also: SetFocusOn, JoinTabChain.
int SetHotKey(int id, void (*CallBack)(void*), void *data, int scan, int ascii);

Installs an application-specific handler which will be called with "data" when the user presses the "hot-key".
This "hot-key" will be hooked to any container, and it will be removed when the container is removed.
See also: IsHotKey.
int IsHotKey(int scan, int ascii);

Checks if the specified scan/ascii already has been used in the operating window.
Returns 0 if not, otherwise 1
See also: SetHotKey.
void SimulateHotKeys(int scan, int ascii);

This function calls for the system's handler of hot-keys, which is by default the receiver of keys (if no editbox is in focus), and does not normally need to be called by the application program.
SimulateHotKeys will have the same effect as if the user pressed the specified keys. This function may possibly be useful to call in special cases in some other keyboard-handler (to bypass the let the key-presses bypass the current keyboard- handler (and all other) and go directly to the hot-key handler. Another way of doing this is to call Allegro's `simulate_keypress'. This will however lead to a new entry in the event queue.
void UseHotKeys(char *hkset);

Specifies which characters in the labeltexts that shall be used by the system when the automatic generation of hot-keys is in progress. Default is the english alphabet. If you wants national characters or special keys like %-/ etc to be candidates for hotkeys then use this function. `hkset' will replace the previous set.
See also: Labels.


The event processing in CGUI will be started by a call to ProcessEvents stopped by a call to StopProcessEvents. Typically ProcessEvents is called at beginning of your program (after InitCgui and after making it possible for the user to generate some events by e.g. creating a window).
A typical external event is a mouse event. A mouse event may serve as an explanation to what actions are taken when an event occures It works in a similar manner with hot-keys. Sometimes you may want things to happen later on. For that purpose you may explicitly generate an event with some delay (this may be used in animation). The call GenEvent(foo, bar, 0); is equivalent to the call foo(bar); at end of the function that calls GenEvent (provided that the event queue is empty).
void ProcessEvents(void);

Start event processing. This function will not return until StopProcessEvents has been called.
See also: StopProcessEvents.
void StopProcessEvents(void);

Stop event processing. You shall call this function in the call-back function where you want CGUI to stop the event handling, e.g. in the call-back for a button "Exit". In a typical gui-program you don't need to call for StopProcessEvents, if you prefere you can call exit(), instead.
See also: ProcessEvents.
unsigned GenEvent(void (*Handler)(void*), void *data, unsigned delay, int objid);

Generates an event, i.e. adds one messages to the event queue. The effect of calling
   GenEvent(my_function, mydata, 0, 0);
if the event queue happens to be empty. The purpose is to serialize the work to be done (i.e. let some processing be finished before invoking the function in concern), or to ensure that some events that may be in the queue will be processed prior to your function. Another purpose is to achieve that the function will be called after a certain amount of time.
Return value: An event id. Event ids are not the same as the ids of window objects. There can never be two events with the same id, and there can never be two window objects with the same id, but a window object may occasionally have the same id as an event id.
Parameters: Return value: an id that identifies the event, greater than zero, or 0 if it fails (that is: if the event queue has been stopped because of a call to `StopProcessEvents').
See also: ProcessEvents, StopProcessEvents.
int KillEvent(unsigned eventid);

Removes specified event from the event queues. Returns the true if the message was there.
Only events generated by your program can be killed. Events generated bu CGUI itself are protected.
Returns 0 if the event was not found, else non-0.
void FlushGenEvents(void);

Removes all events generated by previous calls to the function GenEvent from the event queue. Events generated bu CGUI itself are protected.
See also: GenEvent.
void CguiEventIterateFunction(int (*Function) (void *data), void *data);

Will iterate `Function' (using the event queue) until it returns 0. This can be used e.g. if you want to run a game on top of CGUI, for example in a window so that mouse and key events of CGUI are still processed.
See also: GenEvent.
void CguiYieldTimeslice(int state);

By default the event loop of CGUI will yield a timeslice to the system between each two checks for new events. This is to avoid that you CGUI program takes almost all available CPU power. This may slow down your program in some context. If you want to turn off the yielding of timeslices then call this function with 0, to turn it on again call it with non-0.
void InstallKBHandler(int (*Handler)(void *data, int scan, int key), void *data);

Installs a key-board handler. This handler will be called for each key pressed by the user.
For "normal" programming of an application this is not needed. By default the hot-key handler will be installed by InitCgui. When an edit-box will be selected for input by the user it will install a keyboard handler for the edit-box - this one overrides the hot-key handler. I.e. all subsequent key-presses will go to the key-board handler of the edit-box instead of the key-board handler of the hot-keys.
The call-back function "Handler" should return a non-zero value if the key is accepted. A rejected key will be passed to next keyboard-handler on the stack of keyboard handlers.
The pointer "data" will be transparently passed to the handler when invoked, together with scan-code and ascii-code.
See also: InitCgui.
void *UnInstallKBHandler(int (*Handler)(void *, int , int ));

Removes the a keyboard-handler previously installed by InstallKBHandler. Also handlers not on top of the stack may be removed. Return 0 if the specified handler is not present.
See also: InstallKBHandler.
int Invite(int mask, void *data, char *text);

Meetings is a mechanism that makes a kind of "hand-shaking" possible. It will make it possible to simulate "process-like" objects, which may be used in communication protocols.
About meetings: Any of your functions may invite to a meeting, which means that its execution will be held (within "Invite"). The only way for the function to continue is that an event occurs and the callback of that event calls for "Attend" with a matching mask. Until Attend has been called, other events will be properly processed. Invitations are stack-based, which means:
If, while one invitation is open, another call-back "invites" to a new meeting, then that later of the invitations has to be attended (by anyone) before the event system will try to match any attendings to the first of the invitations.
   | 0x8  | last invite
   | 0x80 |
   | 0x2  |  first invite
In the figure above all "attendings" with mask 0x80 and 0x2 will fail until the meeting with mask 0x8 has been finished.
Return value: always 1
Parameters: Return value is 1 (it will always succeed).
See also: Attend.
void *Attend(int mask);

Will attend a meeting invited to by function `Invite' if parameter `mask' matches the meeting. Return value: Attend returns the pointer "data" passed by `Invite' if successful meeting, otherwise NULL.
See also: Invite.


Various functions that may be of interest.
char const*const*LoadTexts(const char *fn, const char *section);

Loads a section of text from a file. Intended to be used in conjunction with the `mktext' tool to make executables language independent in an simple way. See readme.txt for `mktext'. The "text module" doesn't really do very much, but it does it the right way... LoadTexts will search for the language specified in the current environment (i.e. allegro.cfg if no other specified). It will first search for the language in the CGUI-section, if not found it will look in the global section, and if not found there (or if config is not present) it will take english.
If the language determined this way is not found in the specified file it will look for the english language, and if that is not found it will take a random (first).
The language name specified in the text-source may be any text (in legal identifier form), strings will just be compared. To make use of the error handling you it is necessary to follow the convention used in allegros cfg-file (i.e. "en" for english, "de" for german etc). `LoadTexts' returns a pointer to an array of strings. That array must be indexed with the macros that you specified in the source-file, and available in the header-file (`*.ht'), generated by `mktext'.
Calling `LoadTexts' requesting an already loaded section, will not consume memory (the same pointer as the first time will be returned). Calling `LoadTexts' requesting an already loaded section, but with a new language found in the current environment, will re-load the text. All previously returned pointers to sections within the same file will then be corrupt, and must be re-loaded.
See also: DestroyTexts, PrintFloatingConversion, RegisterConversionHandler.
void DestroyTexts(void);

Will release memory allocated for all texts loaded by LoadTexts. You don't need to call it - it will be called automatically at program exit.
See also: LoadTexts.
void RegisterConversionHandler(void (*Handler)(void *, char *), void *data, const char *name);

Registers `Handler' and `data' as the converter for conversion-code `name'. `Handler' will be assicated with the text string `name' and called with `data' and a string pointer when needed. Its only task is to put some text into the string called with, possibly with use of the pointer `data'. The `name' shall include the <> like: "<person>".
See also: LoadTexts, PrintFloatingConversion.
void PrintFloatingConversion(char *dest, const char *src);

A text specified in the source text-file, processed by `mktext' may contain conversion codes of an extended format. These codes look like %<text> (where `text' may be any text) and may be embedded in the source-string like the C-standard conversion codes. The difference is that since the conversion is name-referenced multiple occurances of conversion codes in the same string may be put permutated order in different languages.
`PrintFloatingConversion' does not recognise the C standard conversion codes.
If a no handler is associated with the "<xx>" in "%<xx>" (which may be the case if you accidently misspell the text), the text "<xx>" will be printed instead.
Example: Suppose that the row is in you source-text-file:
    SIZE_ERROR_TEXT "%<name> has to many (%<nr_things>) things|OK"
Suppose the following fuctions beeing registered for "<name>" and "<nr_things>":
   void name_handler(void *data, char *s)
      /* suppose data points to a string containing the desired name */
      strcpy(s, data);

   void thing_handler(void *data, char *s)
      int *i = data;
      /* suppose data points to an integer containing the desired value */
      sprintf(s, "%d", *i);
The above functions will be called whith a pointer to proper location into the destination string when needed while `PrintFloatingConversion' is executing in the below statement:
   char string[1000];
    . . .
   PrintFloatingConversion(string, txt[SIZE_ERROR_TEXT]);
This call to `PrintFloatingConversion' will result in the following string printed by `Req' (imagine the name to be "John Smith" and value to be 13):
   John Smith has to many (13) things
See also: LoadTexts, RegisterConversionHandler.
char *msprintf(const char *format, ...)

This function works as sprintf, except that the print buffer is not an input parameter, but instead a return value. The returned pointer is allocated dymanically and the caller is responsible for freeing the memory.
void CguiUseIcons(const char *filename);

Use this function if you want to use other than the default icons for the built in dialogues in CGUI. 'filename' must be a dat-file, and the datafile objects (i.e. the icons) must be named exactely as in the default icons which you can find in the resource directory.
void NameCase(char *text);

This function converts one string to lowercase, except from the initial letter of each word. A word is a sub-string that follows a space, a tab, or a minus-sign '-'.
void CguiSetMouseInput(void (*MouseInput)(int *x, int *y, int *z, int *buttons), void (*ForcePos)(int x, int y), void (*SetRange)(int x, int y, int w, int h));

This function changes the default mouse input, which is the Allegro mouse driver, to whatever source you like. This can be useful e.g. in an embedded system where a mouse is not present, and you may want to provide mouse control anyway, e.g. whith the help of a joystick. If MouseInput is NULL the default input handlers will be re-installed.
int AddClock(int x, int y, int options);

Creates a clock at desired position. The time is shown as HH:MM:SS or HH:MM. Which one to use is checked in the config-file. If the value can not be retrieved from the config file the default is HH:MM. The user can start a dialogue (if not suppressed by flag, see below) to adjust the clock settings (minute or second based showing and, in case the platform supports it, modifying the time). User modifications are always stored into the current config file.
The `options' parameter can be either of: The config file to store and read from is the "current config", so if you adds multiple clocks they will all get the same setting.
The return value is the id of the clock object.
void Sound(int freq, int duration);

This function is deprecated, use Allegro's functions.
void ScrMode(void (*CallBack)(void));

This function will make a dialogue that lets the user select new screen settings of resolution and colour depth.
If the changed are done by the user all images that has been pre-loaded by `CguiLoadImage', will be re-loaded to make it possible for CGUI to display them properly.
After a selection the new settings will be stored into the current configuration file. To make CGUI using these stored settings automatically, you should pass 0 for the settings when calling InitCgui.
See also: CguiLoadImage, InitCgui.
int SaveDatafileObject(const char *path, void *data, int type);

Saves a data file object into an existing datafile.
Parameters: Return-value: 0 if error, 1 if ok.
int CreateNewDataFile(const char *path, const char *filename, int pack, const char *pwd);

Creates a new empty datafile.
Parameters: Return-value: 0 if error, 1 if ok.
int CguiSetColor(int color_name, int r, int g, int b);

You can use this function if you wish to customize the colors in CGUI. The function will only have effect if you call it after the initialization of CGUI.
Parameters: If you are using a palette mode (8 bit color depth) the result of the color setting depends on Allegro's makecol() ability to find a suitable palette index in the palette that you are using.
The default colors in CGUI are set up at init by loading the values from the current config file (i.e. allegro.cfg). If the file is not present or does not contain color specifications then internal default values will be used. These are the same as those in the config file, meaning that you do actually not need to include the allegro.cfg in your distribution package.
The config file loading of start color values provides an alternative way to define custom colors, that also let the user control it. The names of the config variables are the same as the symbolic names to be used for the `color_name'. The values in the file should be given as RGB triples (comma separated, no space, decimal notation like e.g. 0,255,255 for green). Return-value: the previous value of the specified color name, or -1 if the color name is out of range.


void SetCguiFont(FONT *f);

The CGUI lib contains a font that is used when various CGUI-objects are created. You can make CGUI start using your favourite font instead. You just need to call `SetCguiFont'. The current set font is assigned to objects when they are created, so you can create object with different fonts in the same view. Note however that mixing fonts with different heights will cause most objects to get different heights, since most objcet types use the font height in the height calculation.
CGUI will not make a copy of the font pointed to by `f', so your program is responsible for managing the memory of the font.
To restore the original built-in font of the CGUI lib you can at any time call 'SetCguiFont(NULL)';
The rows in list-boxes uses fonts in a different manner, and will not be affecte by the call to `SetCguiFont', see details about that in the `Listboxes' section.
See also: Listboxes, GetCguiFont.
void FONT *GetCguiFont(void);

Returns the default font for objects.
See also: SetCguiFont.
void CguiSetBaseLine(int base_line);

When setting a new font using `SetCguiFont' CGUI will make a guess about where the base line of the font is. This will usually succeed for fonts conforming to the ususal shape of European letters. However, for odd looking fonts, or for non-European fonts it may find a base line that does not look good. In such a case you can set the base line explicitly after setting the font with `SetCguiFont'.
The base line is the first empty pixel line below the letters (except letters like p, q, g, etc. that breaks the base line). The base line is used by CGUI when underlining the letter to be used for short cut selection (used in labels of buttons, edit boxes etc. as an alternive to using mouse click).
See also: SetCguiFont.


A number of objects like buttons, edit-boxes, containers, etc. may have a text label. This label may primarly contain the text to be shown on the surface of the object in a manner that is useful (e.g. the edit-box will put it to the left of the input field, but the container will put it at top as a header). The label must not necessarily be static or constant memory, the object will make a copy of the text. Labelled objects will adapt thier size to the size of the text. The label may be extended with additional information. If you need to actually draw any of the above control-characters - just type them twice in the string.
See also: AddButton, MkMenuItem, AddIcon, Req.
int CguiParseLabels(int state);

By default CGUI scans labels for certain characters that controls some functionality (see above). This may be a problem e.g. if you use file names to label some menu items, and the file names occasionally contain characters like '~' this will be consumed and the subsequent character will be interpreted as a hot-key.
Therefore you may want to turn off this behaviour. If `state' is zero the scanning will stop (all characters will appear exactely as they are). If `state' is non-zero it will be turned on again.
Return value: The previous state of label parsing.
int CguiLoadImage(const char *filename, const char *imagename, int type, int id);

This function loads an image with name `imagename' from file `filename'.
Why? - The image as well as its name will be registered in the CGUI system which means: An image associated with a node may be referred from objects that are put into that node (at any depth). I.e. if `id' is a window, any object put into that window can use that image, or if `id' is a container, any object put into that container can use it. Also all objects of a sub-window can use the images of a parent window.
If you want to make an image `global' (i.e. it will remain in memory until CGUI is shut down), just pass 0 for `id'.
Loading images from 8-bit colour files to a screen mode of 8-bit colour will only work properly if all pictures uses one common palette. Loading 8-bit colour files into high colour or true colour modes will work properly only if transparent colour is not used. The same limitation applies to the reverse (high -> 8).
In short: to avoid problems use 24-bits files, and at least 15 bit colour-depth on the screen.
Parameters: Return value: The id of the node where the image is stored if sucessful othewise -1.
See also: RegisterImage, ScrMode, GetRegisteredImage, Labels.
int RegisterImage(void *data, const char *imagename, int type, int id);

Works analogous to `CguiLoadImage' but registers an image that is already in memory. `RegisterImage' will not make a copy of `bmp' so it must not be freed or reallocated as long as it is in use (i.e. as long as object id is not destroyed).
In contrary to images loaded from file the registered ones will not be automaticallay adjusted when CGUI dialogue for changeing the screen settings are used.
The `type' parameter shall be either of the IMAGE_* values meaning: Call `RegisterImage' with NULL for `data' if you want to unregister a previously registered image (the name is your handle). You can also replace a previous registration by subsequent calls to `RegisterImage' using the same name. This can be used to make simple animations on objects (which includes plain image objects like those made by `AddTag'), see also the examples.
Return value: 0 if it failed (i.e. unknown type, unknown id), else 1.
See also: CguiLoadImage, GetRegisteredImage.
const void *GetRegisteredImage(const char *imagename, int *type, int id);

Returns a pointer to an image with name `imagename' in node `id' that has previously been registered by `RegisterImage' or `CguiLoadImage'. The integer pointed to by `type' will be set to the type of the image, see IMAGE_* macros. The type of the returned pointer corresponds to the type value.
See also: RegisterImage, CguiLoadImage.

File bowsing

In CGUI there are two functions for browsing the file system. If you use the functions in your program you must link with the libaldat.a library located in the lib directory of you Allegro directory.
const char *FileSelect(const char *masks, const char *rpath, int flags, const char *winheader, const char *buttonlabel);

Opens a file selector dialogue. Simple usage:
   char *fn;
   FILE *filep;
   fn = FileSelect("*.txt", "", 0, "Select a file", "OK");
   /* fn points to a full path string, the memory will be deallocated by
      the file-browser - you must not do. */
   filep = fopen(fn, "r");
This function may be useful if your program needs to let the user specifiy a file to load, or maybe a filename and path to store things in or just to specify a path where the program shall put files or seach for files. The user will expect a file-browser to behave slightly different in each of these 3 cases. You can control its beaviour using the `flags' parameter.
The dialogue is modal (i.e. the parent window of the file selector is locked for mouse input until the file-selector has been closed).
The user may browse within Allegro datafiles.
The user closes the dialogue either by use of a cancel-button or a confirm-button. If cancel was pressed, the return value will be a pointer to an empty string.
Reuturn value:
The return value is a pointer to a string containing the full path to the seleceted file (or directory). If an object in a datafile was selected it is separated from name of the datafile with the '#' character. If the flag `FS_MULTIPLE_SELECTION' is set the user may possibly have selected more than one file. If so, each file will be enclosed in quotation marks, '"', and separated with semicolon,';' (e.g. like "highscore.txt";"readme.txt") and `UnPackSelection' can be used to extract single file names from the returned string.
The memory location of the string, is valid only directly after the return and belongs to the file-selector, so if you need to use the path later on you have to make a copy to save.
Parameters: Note! The implementation of the browser is a list, and by default lists get an event for SINGLE CLICK. In the browser the user can double-click to select a certain file or directory directly (this is a common behaviour of bowsers). However, what will happen if doubel-clicking on e.g. a directory for opening it? If the drag-drop is active it will in most cases be seen as a try to grip the object and therby it will be inserted into the copy-buffer.
See also: FileManager, UnPackSelection.
char *UnPackSelection(char **flist)

This function may be used to unpack individual filenames (including path) from the return string of `FileSelect'. The return value points to the first file of *flist and is dynamic memory and it is your responsibility to free it. *flist will be advanced to next file and will point to the string end when no more files.
See also: FileSelect.
void FileManager(const char *winheader, int flags);

Creates a dialogue that lets the user inspect and maintain the file system. Parameters:
See also: FileSelect.
int RegisterFileType(const char *ext, void (*Handler)(void *privatedata, char *path), void *privatedata, const char *actionname, const char *icon, const char *typetext, void (*Viewer)(void *privatedata, void *viewdata));

This function will register a file type so that the file-browser will identify it and give it some special handling. There are three things that can be done: If e.g. you only want to register an icon or name just pass NULL for the data and call-back parameters.
The registration will be reflected both in the file-selector and the file-manager concerning icon and info. The action registration will however only have effect in the file-manager.
All registering is global, i.e. if the browser is used in different contexts they will be present at all of them. You can disable a registration by calling with all parameters set to NULL.
Parameters: Pass an empty string for those parameters not used. Pass NULL-pointers for call-backs you don't need.
Returns 0 if fail (ext is empty) else non-zero.


You should not use the Allegro functions/variables for mouse-manipulations directly. CGUI will do some changes for certain events, that will override such changes. Instead use the functions listed below. There are some pre- defined cursors "installed" that you can selecet among (CGUI uses them itself). You may also extend this list of installed cursors. In addition to this you may create overlayed cursors, i.e. make a new cursor from the currently selected and some other sprite.
int cgui_mouse_draw_in_interrupt;

A global variable that tells the mouse cursor to be drawn inside the interrupt. The default is not. The reason why the mouse is drawn "polled" (or rather via the event queue), is that the interrupt drawing will not draw well if you use canvases. This is a weakness in CGUI, that may be removed in later versions. The reason why uou want to let the cursor to be drawn in the interrupt is that it otherwise will "freeze" if the program is busy for a long time without returning the control to the event queue processor (this is quite rare in most programs, e.g. disk accesses for 1M will not be affect the mouse moving).
void InstallCursor(int cursor_no, BITMAP *sprite, int x, int y);

Installs a sprite to be a predefined cursor. This cursor may replace an existing cursor, as well as extend the list of available. x,y is the hotspot point relative to the upper left corner of the sprite. InstallCursor will make a copy of the bitmap, so you are still responsible for the memory after the call, and may feel free to destroy it.
If your cursor replaces an existing one, the latter will be destroyed.
void SelectCursor(int cursor_no);

Selects a predefined cursor using the specified index. Available cursor alternatives are: The mouse event processing will occasionally switch between the above indexes. E.g. moving over a draggable object will set CURS_DRAGGABLE. If you select another index this will inhibit this automatic cursor switching.
Selecting another cursor than above requires that the cursor have been installed first.
See also: InstallCursor.
void PointerLocation(int id, int *x, int *y);

Returns the mouse pointer locataion related to the specified object.
See also: OverlayPointer.
BITMAP *ObjectApearance(int id);

Returns a pointer to a bitmap showing the current view of the specified object. The bitmap belongs to you, i.e. it's your responsibility to destroy it when you don't need it any longer.
See also: OverlayPointer.
void OverlayPointer(BITMAP *sprite, int x, int y);

Creates an overlayed mouse pointer. This means that a new pointer will be created by merging the shapes of `sprite' and the current selected pointer.
The current selected pointer will appear on top of `sprite'.
Overlayed mouse pointer may be useful e.g. during dragging operations showing the dragged object as a cursor and letting the current selected cursor still be left on top to point out the "hot spot".
The current selected cursor can later be restored as a single pointer by `RemoveOverlayPointer'.
Subsequent calls to `OverlayPointer' let you overlay multiple cursors.
If `SelectCursor' is called while an overlayed pointer is in use the requested change will be reflected in the overlayed pointer.
See also: InstallCursor, RemoveOverlayPointer, PointerLocation, ObjectApearance.
void RemoveOverlayPointer(void);

UnInstalles a secondary cursor previously installed by OverlayPointer.
See also: OverlayPointer.
void MkTextPointer(FONT *f, char *text);

Creates an overlayed cursor using the specified text and font Restore a plain pointer by a call to `RemoveOverlayPointer'.