Panther's Slick Interface Library (PSILib)

This library is a display layer which handles window frames, and has many classes of controls ready. There are some caveats to using this library, and I will try my best to cover them all.

Some terminology/philosophy...

FRAME - this is a window frame control. It contains controls and perhaps other frames. This is the backdrop on which other objects are hung. A frame has a caption, perhaps some control icons like Close, Max, Min, Resize. It handles shadow and highlight attributes, may be aligned to match the color mapping on a Windows system. Otherwise, There are standard colors which all controls reference in order to draw shadow, highlight, shade, normal, text, titlebars active and inactive, etc.

CONTROL - This is a generic control class. It has the ability to display a border without caption. All content of a specific type of control must be constructed by the control itself. Controls have a couple callbacks to handle mouse and keyboard inputs, and to draw their content.

Some Liscensing issues have been mentioned. Ownership of code, perhaps, some ego that there is monitary value in the code itself and not the service it provides. That is, in this library, a control, provides an interface between the.... Lisenscing on this library, the core (all of PSILib) is LGPL, as expressed near the root on this collection. The following exception applies:

If you make modifications, and do not remit to the core library for inclusion within the LGPL distribution of this library, then you may not share the source of this library either. Updates to the core from the common LGPL sources are permitted, but if additions to this library, control extensions for example, are not released in source for public use, then no other part of this library may be shared.

A Divergant thread

Windows systems use a WindowProc( WINDOW HANDLE, MESSAGE, PARAMS )... some other systems like SDL provide these as an EVENT structure with message ID content, and perhaps a union of structures based on the message type, this is similar to the method used by X to get events. QNX Photon uses a callback system, where if you want a specific type of message, you register a specific routine to handle the message. The difference between the two methods - the first has a dispatch like this...

The first two (Windows, SDL/X )

switch(message id) { 
	case DRAW: 
		DrawProc(); break;
	case MOUSE: 
		MouseProc(); break;
	case KEYBOARD: 
		KeyboardProc(); break;

The other

RegisterDraw( DrawProc );
RegisterMouse( MouseProc );
RegisterKeyboard( KeyboardProc):

In the first case, everything is jammed together into a single message and the application must dispatch to the appropriate method, in the latter when that event happens it goes directly to the appropriate method handler. If the event goes directly to the handler, there is no code to format a message in a general format, to queue that message, and to then disect the message.

So what do I do with this thing?

Well to use these methods you need to....

And of course once you've compiled you'll want to link the code in.... Link with psi (psis.lib, psi.lib, libpsis.a,

This library may require other libraries if linked statically. Required Libraries: procreg, or video/display

This library is actually able to utilize multiple interfaces dynamically. It uses the image interface described in , and also the active image interface in .

Well - you've included the header? Ready to code a dialog?

Let's declare a frame...

	PCOMMON pFrame;  

Well okay we NEVER declare a FRAME type. It's always a pointer(handle/reference) to the FRAME object we create.

	pFrame = CreateFrame( "My First Frame", 0, 0, 0, 0, 0, NULL );
        CreateFrame( caption, x, y, w, h, Border Flags, Frame which this is over );

Okay so we get a frame, but didn't specify any special position or size, or relation to any other frame. That's okay - it'll work. What you'll get is a frame (somewhere, maybe where your mouse is) and it will be 256 by 256 containable space. The boarder and caption on this (by the way, the caption will of course read "My First Frame" ) will make the actual area larger than this.

	AddCommonButtons( pFrame, NULL, NULL );

And we add an okay and a cancel button to the dialog. These are biased from the lower right hand corner, and are a fixed size. There is an extended version of this function which allows you to specify more detail. Either NULL may be replace by the address of an integer. The first pointer will be non-zero if the Okay button was pressed. The second pointer will be non-zero if the Cancel button was pressed. Otherwise, they will be 0. (Perhaps if the close icon is pressed, the result will be neither true).

   DisplayFrame( pFrame );

And - until JUST now, the frame we made was invisible. This finally shows the frame. It's kinda a good idea to create all your controls on the frame and THEN display it. Otherwise, ya know you get to see each control drawn.

   CommonWait( pFrame );

CommonWait will wait for the buttons okay/cancel to be invoked.

   DestroyFrame( pFrame );

And now we're done with that frame, destroy it. It will also destroy any of the controls and other frames it contains. If you have a pointer to a control, it is NOT valid after a destroy frame.

And that's the code of void main(void) - for a hello world program PSI style.

well now, that was fun, but I want ...

Oh? You think you'd maybe like to have some other controls? Well, I might suggest that you skip down a bit, and browse through the library docs.

Oh my - where to start? This could easily EASY have a C++ wrapper. If it ain't object oriented it ain't worth keeping.


#include <controls.h>

Project Location


Required Libraries

image or cimage, display or video or cdisplay, memlib, syslog msgclient


PFRAMEA container for controls. It is like a master level window, with a frame and title bar (usually).
PCONTROLA control, a widget, an object which may be mounted within a frame.
PCOMMONThis is a generic reference and may be either a frame or a control, at this level they are identical.
PMENUThis is a popup menu. CreateMenu, TrackPopup.
PMENUITEMThis is an item on a popup menu.
PDRAWPOPUPITEMAn application which has created a custom drawn menu item will receive this when the control library needs to draw a control.
PLISTITEMAn item which has been inserted into a listbox
PCONTROL_INTERFACEThis will be the function inferface table to the control library so that this library may be mounted either as a service of the message service, or various other configurations.


Color Indexes

HIGHLIGHTHighlight on existing controls.
NORMALNormal background/face color
SHADEA darker color than normal
SHADOWA darker color than shade
TEXTCOLORThe default color of text (non edit)
CAPTIONCaption backgorund color when active
CAPTIONTEXTCOLORCaption text color when active
INACTIVECAPTIONCaption background when not active
INACTIVECAPTIONTEXTCOLORCaption text when not active
SELECT_BACKSelected text background
SELECT_TEXTSelected text foreground
EDIT_BACKGROUNDEdit field background color
EDIT_TEXTEdit field text color
SCROLLBAR_BACKColor of the background of scrollbars.

Border Definitions

BORDER_NORMAL Default border on a frame, this is thick, with caption.
BORDER_NONE No border is shown, which also implies no caption.
BORDER_THIN A thin (2 pixel) border is drawn.
BORDER_THINNER A thinner (1 pixel) border is drawn.
BORDER_INVERT Instead of being bright on the top/left, which commonly represents a raised contained area, the bottopm/right are highlighted indicating a depressed region within the border.
BORDER_CAPTION Think that this will turn on caption even if there is no border?
BORDER_NOCAPTIONDoes not draw the caption, just the bounding frame.
BORDER_DENTThis is a inverted thin border, with a normal thin border within it, This is then the same thickness as a normal border, but the border appears as a grooved boundry.
BORDER_THIN_DENTSimilar to dent, but is thinner, based off of thinner frames, resulting frame is the same size as a thin frame.
BORDER_THICK_DENTUses thick frames to provide a really thick dent.
BORDER_BUMPThis is essentially a inverted dent, that is the boundry appears as a raised bead around the region.
BORDER_TYPEThis is a mask of bits which defines the field of bits which determine border appearance.
BORDER_NOMOVEFrame is not allowed to move by default mouse click and drag.
BORDER_CLOSETo be Implemented - draw a close icon in the caption (if present)
BORDER_RESIZABLEBorder on the frame is allowed to be grabbed and do resizing motions by moving just the border.
BORDER_WITHINThis indicates that the frame being created is within the parent specified, instead of above.
BORDER_WANTMOUSEIndicates that the frame wants all mouse event notifications. Otherwise only button changes are passed through.


PRENDER_INTERFACE SetControlInterface( PRENDER_INTERFACE DisplayInterface );

Override the renderer interface that is used to show stuff... otherwise the default render interface specified in interface.conf is used.

PIMAGE_INTERFACE SetControlImageInterface( PIMAGE_INTERFACE DisplayInterface );

Override the image interface that is used to show stuff... otherwise the default image interface specified in interface.conf is used.

void AlignBaseToWindows)( void )

If under windows, this queries the current windows environemnt for its colors, and attempts to use a consistant color scheme as defined by the user.

void SetBaseColor( INDEX idx, CDATA c )

Redefine a color index. Does not cause an immediate change, and frames will have to be redrawn/refreshed. // see indexes above.

CDATA GetBaseColor( INDEX idx )

Get the current color of a common interface color...

PFRAME CreateFrame( CTEXTSTR caption, int x, int y, int w, int h, uint32_t Border Flags, PFRAME pAbove )

Creates a dialog frame. This is a container for other controls. This may be used as a surface to operate directly, there is no need to create any controls. Border flags are defined above as BORDER_; these flags may be or'ed together.

void DisplayFrame( PCOMMON pf )

Show a control. If there is no previously defined renderer for this control, this is orphaned from any container control, and displayed on a renderer.

PCOMMON GetControl( PCOMMON pf, uint32_t ID )

Get a control from a container control (such as a frame). The first control that has the ID matching the ID specified will be the result. All children of contained controls are also checked. If no control is found NULL is returned.


Results in the top level frame container of the control passed. The result may be the control itself.

void SetCommonText( PCOMMON pc, CTEXTSTR text )

Set the caption field of a control. This may invoke a method on the control which allows the control to automatically update as a result of this change. All controls have a caption, but must controls do not use it, such as a listbox or scrollbar which have no location for a caption to be displayed.

PCOMMON MakeControl

( PCOMMON pContainer

, uint32_t nType

, int x, int y

, int w, int h

, uint32_t nID

, ... )

PCOMMON VMakeControl

( PCOMMON pContainer

, uint32_t nType

, int x, int y

, int w, int h

, uint32_t nID

, va_list args )

Make a control, using a numeric ID. These type IDs are from the CONTROL_REGISTRATION structure or one of the predefined control IDs listed above: CONTROL_ symbols. Certain controls take extra parameters on their creation. These extra parameters are defined per control type.
VMakeControl takes a variable argument pointer rather than having the parameters passed in-line.

PCOMMON MakeCaptionedControl

( PCOMMON pContainer

, uint32_t nType

, int x, int y

, int w, int h

, uint32_t nID

, CTEXTSTR caption

, ... )

PCOMMON VMakeCaptionedControl

( PCOMMON pContainer

, uint32_t nType

, int x, int y

, int w, int h

, uint32_t nID

, CTEXTSTR caption

, va_list args )

Make a control, using a numeric ID. These type IDs are from the CONTROL_REGISTRATION structure or one of the predefined control IDs listed above: CONTROL_ symbols. Certain controls take extra parameters on their creation. These extra parameters are defined per control type.
Additionally, a default caption is specified for the control.
VMakeCationedControl takes a variable argument pointer rather than having the parameters passed in-line.

PCOMMON MakeNamedControl

( PCOMMON pContainer


, int x, int y

, int w, int h

, uint32_t nID

, CTEXTSTR caption

, ... )

PCOMMON MakeNamedCaptionedControl

( PCOMMON pContainer


, int x, int y

, int w, int h

, uint32_t nID

, CTEXTSTR caption

, ... )

These functions work like the above functions, however instead of specifying the ID of a control to build these use the text name of the control to make. Again these are defined above for those built within PSI... CONTROL_..._NAME symbols.

New Control Creation

And then there comes a time when the default controls available are not enough. Or you want a newer, fancier control, and need to implement custom control stuff.


Define a CONTROL_REGISTRATION structure, and call DoRegisterControl( &Resgistration Structure );

CONTROL_REGISTRATION sample_control = {{ control name
, { { default_width, default_height }
, extra space to allocate (size of structure this control needs)
, default border flags.
int (*init)(PCOMMON va_list args );
init function, invoked with the control being created, and the arguments passed extra to Make__Control function defined above. return FALSE to abort creation of the control. Return non-zero to allow control creation.
int (*load)(PCOMMON, ... );
Undefined Yet. Invoked when a frame is loaded from a file.
int (*draw)(PCOMMON);
Invoked when the control needs to be refreshed. Multiple draw methods may be associated with a control. Return 0 to allow further draw routines to be invoked. Return 1 to end drawing dispatch.
int (*mouse)(PCOMMON, int32_t x, int32_t y, uint32_t b );
This is invoked when the control receives a mouse event. By default only button changes are snet to the control, moving the mouse is filtered. A special value of 0xFFFFFFFF is passed as the buttons when the mouse leaves the control while a mouse button is down.
int (*key)(PCOMMON, uint32_t key );
A key has been pressed while this control has the focus. Key interpretation is done using methods in the Renderer. (video display library)
... more ....
... and more....

PRELOAD( RegisterSampleControl )
	DoRegisterControl( &sample_control );

By using the declarator PRELOAD() this function will be invoked before any code in main() is run.

Quick coverage of basic functions.

Libray Setup/Configuration
void SetControlInterface( PACTIMGINTERFACE DisplayInterface )
	This sets the active image interface which the library will use.  If there
is no interface described, the library may, and probably will, attempt to load
a dynamic library for this function.  There are multiple libraries on some
platforms which will work, and this should not be left for the library to 

void SetControlImageInterface ( PIMAGEINTERFACE DisplayInterface );
   Sets the image interface which the library will use.  As with 
SetControlInterface, if not set, the library will try to load a library
to attempt to use.  

void AlignBaseToWindows( void );
	In a windows system, this aligns the standard colors used for the frames
and controls.  Other systems may not have the ability to share that information.

void SetBaseColor( INDEX idx, CDATA c );
	From an external source, one may define the colors to be used for 
Standard controls.  See the color indexes defined above for valid identifiers
to use for 'idx', the use/meaning of the color is also described above.  
Also, See colordef.(h/doc).

//-------- Frame and generic control functions --------------

PSI_PROC( PFRAME, CreateFrame)( char *caption, int x, int y
   						, int w, int h
     						, uint32_t BorderFlags
    						, PFRAME hAbove );

Creates a frame, a window if you will, it has a title bar, and someday icons to 
close, iconize, maximize.  The (w)idth and (h)eight paremaeters define the
drawable surface of the frame, and do not include the border or caption which will
be extended beyond this.

Frames may be optioned with BORDER_RESIZABLE to make
the border stretchable.  BORDER_WANTMOUSE will give the frame itself all mouse
events, otherwise the events are very reducded. 

A sub-frame may be created by specifying BORDER_WITHIN, and hAbove as the parent
frame.  This will provide a titleless, (borderless? border invert, thinner, etc should
apply to these boxes, but then do be aware that the width and height define the 
usable surface and any border extends beyond that.

PSI_PROC( void, DestroyFrame)( PFRAME pf );

Destroys a created frame.  All controls which exist within the frame are also
destroyed.  Some controls may have an event callback so that they may do custom
destruction code.

PSI_PROC( void, DisplayFrame)( PFRAME pf );

Enable a frame on the display.  When a frame is first created it is in a non-display
mode.  This allows one to create controls on its surface without cascading updates.
After DisplayFrame is called, the window is enabled and visible.  There is no way
to undo this.

PSI_PROC( void, SizeFrame)( PFRAME pf, int w, int h );

A frame might be resized using this routine.  All controls are instructed to redraw
after the sizing is done.

PSI_PROC( void, MoveFrame)( PFRAME pf, int x, int y );

This moves a frame on the presumed larger display.  A window may be moved with this
even if BORDER_NOMOVE is optioned when the frame is created.

PSI_PROC( PCONTROL, GetControl)( PFRAME pf, int ID );

Get a control handle by searching for and ID within a frame.

//PSI_PROC void SetDefaultOkayID( PFRAME pFrame, int nID );
//PSI_PROC void SetDefaultCancelID( PFRAME pFrame, int nID );

//-------- Generic control functions --------------

Gets top level parent of a control.  (This may return the first parent frame?)

PSI_PROC( PCONTROL, GetNearControl)( PCONTROL pc, int ID );

Gets a control handle from a frame which has the unique control identifier ID.  (See CreateControl)
This however searches near another control, and only within the frame immediatly containing
the control specified.

PSI_PROC( void, GetControlTextEx)( PCONTROL pc, char *buffer, int buflen, int bCString );

Gets text from a control.  The extended option bCString will process \n within 
the buffer and replace with the binary newline character.  \r, and some others 
may also be interpreted.

#define GetControlText( pc, buffer, buflen ) GetControlTextEx( pc, buffer, buflen, FALSE )

By default text retrieved from a control is literal and does not perform any interpretations.

PSI_PROC( void, SetControlText)( PCONTROL pc, char *text );

Set the text of a control.  The usage of this field is control specific.  For a frame,
this will modify the caption bar if present.  For text fields, the text shown is modified,
buttons, changes the text on the button, Edit fields will set the text which is in the 
box.  Probably some other options such as combo boxes may also make use of this.  All
controls have a text field.  It is a duplicate of the text passed in, and the pointer
is not retained.

PSI_PROC( void, SetControlFocus)( PCONTROL pc );

Sets the active focus to a control.  The keyboard input when the frame is focused on the
display goes to this control.

PSI_PROC( void, EnableControl)( PCONTROL pc, int bEnable );

This serves as a disable control also.  !bEnable = disable.  (enable FALSE is disable, 
enable TRUE is enable ).  A disabled control has a status flag changed in its control 
structure, and its draw method is invoked.

PSI_PROC( int, IsControlEnabled)( PCONTROL pc );

Query a control for its current enabled status.

PSI_PROC( PCONTROL, CreateControl)( PFRAME pFrame
                      , int nID
                      , int x, int y
                      , int w, int h
                      , int BorderType
                      , int extra );
Creates a control within the frame specified.
nID is a unique control ID for searching using GetControl.
x, y, w, h are positional and size coordinates.
BorderType uses the same options as frames.
extra is the amount of extra space to allocate at the end of 
the control... Why?  Well it's kinda crazy really....
Controls really require intimite knowledge of the library.  This 
is acheived by including  from the psilib directory
itself.  It is not a publicly shared interface.  As provided by 
licensing controls may be added directly to this project.  Since
linking within the library is required on some platforms, this has
been allowed.... hwoever...

#include <../src/psilib/controlstruc.h>

typedef struct mycontrol_tag { 
   // depending on the compiler, one may include as an anonymous 
   // structure the control structure. 
   // but since there are some compilers which object to this
   // the controls within this library are declared with
   // CONTROL common;
   /* Add your own needed structures/members here */

Then to create one of these controls the size of extra would be

sizeof( MYCONTROL ) - sizeof( CONTROL )

PSI_PROC( ImageFile *,GetControlSurface)( PCONTROL pc );

This works to get the frame surface also, actually I think this 
is obslete and there is now a more general GetCommonSurface(PCOMMON) which
has alias macros GetFrameSurface and GetControlSurface which cast their
members to a PCOMMON.  

PSI_PROC( void, SetControlDraw)( PCONTROL pc, void (*Draw)(PTRSZVAL pc ) );

Set the routine to be called when the control needs to be updated.  There are 
few events which cause a control to update.

PSI_PROC( void, SetControlMouse)( PCONTROL pc, void (*MouseMethod)(PTRSZVAL pc, int x, int y, int b ) );

Set the mouse handling method for the control.  See /* insert link here */ Render/Display libraries about mouse
method callbacks for more information. 

//PSI_PROC void SetControlKey( PCONTROL pc, void (*KeyMethod)( PCONTROL pc, int key ) );

PSI_PROC( void, UpdateControl)( PCONTROL pc );

Cause a control to update. 

PSI_PROC( int, GetControlID)( PCONTROL pc );

Returns the unique ID which the control was created with or that it
was assigned.
PSI_PROC( void, DestroyControl)( PCONTROL pc );

Destroys a control.

PSI_PROC( void, SetNoFocus)( PCONTROL pc );

Disallow a control from getting focus either by clicking on it, or by tabbing to it.

PSI_PROC( void, *ControlExtraData)( PCONTROL pc );

Returns the base pointer of the additional data of a control.
Perhaps a better design of controls would be to define a structure
which contains everything unique to a new control, however, it 
has been often the case that both elements in the base common control
structure as well as private members are updated at the same time...
that it it would often be difficult to write routines which worked purely
on a control's private members.

//------ General Utilities ------------
// adds OK and Cancel buttons based off the 
// bottom right of the frame, and when pressed set
// either done (cancel) or okay(OK) ... 
// could do done&ok or just done - but we're bein cheesey
PSI_PROC( void, AddCommonButtonsEx)( PFRAME pf
                                , int *done, char *donetext
                                , int *okay, char *okaytext );
Add a done and and done with success button to a frame.  These buttons
are located in the lower right hand corner, offset approcimately 5 units
from the frame's edge, and are approcimately 18 x 55.  The text passed will 
be shown on the buttons, and the integer pointers are to reference integer values
which are initially 0, and will be set with status of the button pressed.
PSI_PROC( void, AddCommonButtons)( PFRAME pf, int *done, int *okay );

Simple AddCommonButtons( pf, done, "Cancel", okay "Okay" );

PSI_PROC( void, CommonLoop)( int *done, int *okay ); // perhaps give a callback for within the loop?

A wait for positive status return based on the two pointers passed to 
add common buttons.  One may use this loop with other method, but it 
works best with the common buttons.

PSI_PROC( void, ProcessControlMessages)(void);

When idling, within a callback invoked from the PSI library, this needs to be called.
The preferred method is actually to use idle(); from the idle library, within
which PSI sets this routine to be called as a set of idle calls.  This allows the
thread which may be needed for serviceing events to service its events.  This
can also cause recursion...  In general it is best to not wait within a draw callback,
mouse update, or any other callback which has been set.  They are meant to be short,
and to always return before any further event is processed.


All controls have the following arguments

PFRAME pContainer - the container to put the control into.
, uint32_t attr - attributes - custom per control. see LIST_OPT for instance.
, int32_t x, y - the x,y position within the frame to create the control at.
, uint32_t width, height - the size of the control surface, including the border.
, uint32_t ID - the ID of the control, for reference by GetControl() for instance.

//------ BUTTONS ------------


( PFRAME pFrame, uint32_t attr, int x, int y, int w, int h

, int nID

, char *caption

, void (CPROC *PushMethod)(PTRSZVAL psv, PCONTROL pc )

, PTRSZVAL Data );

This makes a normal, default, button. Text on the button is the caption. The PushMethod callback is invoked when the button is fully pressed and then released, a false press (click on button, move off button, release is NOT a press).
PSI_PROC( PCONTROL, MakeImageButton)( PFRAME pFrame, int x, int y, int w, int h
                  , ImageFile *pImage
                  , int nID
                  , void (CPROC *PushMethod)(PTRSZVAL psv, PCONTROL pc)
                  , PTRSZVAL Data );
PSI_PROC( PCONTROL, MakeCustomDrawnButton)( PFRAME pFrame, int x, int y, int w, int h
                  , void (CPROC *DrawMethod)(PCONTROL pc)
                  , int nID
                  , void (CPROC *PushMethod)(PTRSZVAL psv, PCONTROL pc), PTRSZVAL Data );
PSI_PROC( void, PressButton)( PCONTROL pc, int bPressed );
PSI_PROC( int, IsButtonPressed)( PCONTROL pc );

PSI_PROC( PCONTROL, MakeCheckButton)( PFRAME pFrame, int x, int y, int w, int h
                        , int nID, char *text
                        , void (CPROC *CheckProc)(PTRSZVAL psv, PCONTROL pc )
                        , PTRSZVAL psv );
PSI_PROC( int, GetCheckState)( PCONTROL pc );
PSI_PROC( void, SetCheckState)( PCONTROL pc, int nState );

//------ Static Text -----------
#define TEXT_NORMAL 0
PSI_PROC( PCONTROL, MakeTextControl)( PFRAME pf, int flags, int x, int y, int w, int h
                        , int nID, char *text );

//------- Edit Control ---------
PSI_PROC( PCONTROL, MakeEditControl)( PFRAME pf, int options, int x, int y, int w, int h
                        , int nID, char *text );
// Use GetControlText/SetControlText

//------- Slider Control --------
#define SLIDER_HORIZ 1
#define SLIDER_VERT  0
PSI_PROC( PCONTROL, MakeSlider)( PFRAME pf, int flags, int x, int y, int w, int h, int nID, void (CPROC *SliderUpdated)(PCONTROL pc, int val) );
PSI_PROC( void, SetSliderValues)( PCONTROL pc, int min, int current, int max );

//------- Color Control --------
// common dialog to get a color... returns TRUE if *result is set
// if result is NULL color is not returned, but still can set presets...
PSI_PROC( int, PickColor)( CDATA *result, CDATA original, PFRAME pAbove );

//------- ListBox Control --------
PSI_PROC( PCONTROL, MakeListBox)( PFRAME pf, int options, int x, int y, int w, int h, int nID );
#define LISTOPT_SORT   1

PSI_PROC( void, ResetList)( PCONTROL pc );
PSI_PROC( HLISTITEM, AddListItem)( PCONTROL pc, char *text );
PSI_PROC( void, DeleteListItem)( PCONTROL pc, HLISTITEM hli );
PSI_PROC( void, SetItemData)( HLISTITEM hli, PTRSZVAL psv );
PSI_PROC( void, GetItemText)( HLISTITEM hli, int bufsize, char *buffer );
PSI_PROC( void, SetSelectedItem)( PCONTROL pc, HLISTITEM hli );
PSI_PROC( void, SetCurrentItem)( PCONTROL pc, HLISTITEM hli );
PSI_PROC( HLISTITEM, FindListItem)( PCONTROL pc, char *text );

typedef void (CPROC *DoubleClicker)( PTRSZVAL psvUser, PCONTROL pc, HLISTITEM hli );
PSI_PROC( void, SetDoubleClickHandler)( PCONTROL pc, DoubleClicker proc, PTRSZVAL psvUser );

//------- Popup Menus ------------
// popup interface.... these are mimics of windows... 
// and at some point should internally alias to popup code - 
//    if I ever get it back

PSI_PROC( PMENU, CreatePopup)( void );
PSI_PROC( void, DestroyPopup)( PMENU pm );
// get sub-menu data...
PSI_PROC( void ,*GetPopupData)( PMENU pm, int item );
PSI_PROC( PMENUITEM, AppendPopupItem)( PMENU pm, int type, PTRSZVAL dwID, POINTER pData );
PSI_PROC( PMENUITEM, CheckPopupItem)( PMENU pm, uint32_t dwID, uint32_t state );
PSI_PROC( PMENUITEM, DeletePopupItem)( PMENU pm, uint32_t dwID, uint32_t state );
PSI_PROC( int, TrackPopup)( PMENU hMenuSub );

//------- File Control --------
// these are basic basic file selection dialogs... 
// the concept is valid, and they should be common like controls...
PSI_PROC( int, PSI_OpenFile)( char *basepath, char *types, char *result );
// this may be used for save I think....
PSI_PROC( int, PSI_OpenFileEx)( char *basepath, char *types, char *result, int Create );

//------- Scroll Control --------
PSI_PROC( void, SetScrollParams)( PCONTROL pc, int min, int cur, int range, int max );
PSI_PROC( PCONTROL, MakeScrollBar)( PFRAME pf, int flags, int x, int y, int w, int h, int nID  );
PSI_PROC( void, SetScrollUpdateMethod)( PCONTROL pc
					, void (CPROC *UpdateProc)(PTRSZVAL psv, int type, int current)
					, PTRSZVAL data );