XView-PC: Graphical User Interface for Pascal/C/C++ --------------------------------------------------- By: Antonio Carlos Moreirao de Queiroz Department of Electronic Engineering and COPPE Federal University of Rio de Janeiro, Brazil e-mail: acmq@coe.ufrj.br INTRODUCTION ------------ The XView-PC graphical user interface attempts to be similar to the XView toolkit used in Sun workstations, in a simplified form. The interface was initially developed as an intermediate step in porting programs from the PC to Sun workstations, by implementing a subset of the Sun XView toolkit in the PC. The work was not completed because it soon become clear that a total translation would be unnecessarily complex. Even so, the working of the two interfaces was kept similar when reasonable. What can be done with the interface in its present form can be repeated with the Sun XView without significant structural changes, although with differences due to the various simplifications made. The porting of an application to Windows is also not complex. The archive file "xv_pc*.zip" contains the versions: - Borland Pascal 7.0, Real mode. Files "mickey.tpu", "xview.tpu" - Borland Pascal 7.0, Protected mode. Files "mickey.tpp", "xview.tpp" - Borland C/C++, Real mode. Files "mickey.h", "mickey.obj", "xview.h", "xview.obj" - GNU C (djgpp), Protected mode. Files "mickey,h", "mickey.o", "xview.h", "xview.o" The file contains also several examples and utilities in Pascal and C. The interface is the same in any of the versions. The interface code is of simple use and adds only about 25 k to the executable program doing all the user interface functions. It works with any PC compatible computer, in any graphics mode supported by the BGI drivers and installed mouse driver. If a mouse is not installed, a mouse emulator using the keyboard is automatically used. To simplify the interface code generation, an interface editor program, "x_make", is included. It allows the edition of a complete user interface, and the automatic generation of an skeleton program in Pascal or C, that is a fully functional program that the user can edit and complete. TYPICAL PROGRAM STRUCTURE ------------------------- Below is the structure of a typical program using the interface: - Program header: - Declaration of global variables and interface "objects". - Normal subroutines. - Subroutines called from the interface objects ("callbacks"). - Main program: - Normal initialization. - Interface initialization: call to "xv_init". - Creation and initialization of the interface objects: calls to "xv_create" followed by direct initialization of the object parameters. - Passing of control to the interface "notifier": call to "xv_main_loop". - Normal termination. INTERFACE OBJECTS ----------------- The user interface is composed of "objects". Note that the interface was not programmed with "object-oriented" specific techniques, but some ideas are used. There are eight types of predefined objects, listed below. Their names are the parameters to be passed to the "xv_create" procedure. - "frame": Base windows, where the other objects are. - "button": Command buttons. - "textfield": Input fields for text and numerical values, with edition. - "setting": Input fields for logical values (choices). - "message": Messages or icons in the windows. - "canvas": Graphical output subwindows. - "tty": Text output subwindows. - "menu": Pop-up menus. Other types of objects can be programmed, if necessary, by adding the desired functionality to "canvas" objects through their "callback" routines. See the example program "rotor.pas". EVENT-ORIENTED PROGRAMMING -------------------------- The interface is intended to be used in an event-oriented program. The basic ideas are: The program does not follow a predefined fluxogram, but is commanded by the user, that generates "events" by acting on the objects in the windows, what causes calls to the "callback" routines, where the program functional code is located. Any "callback" subroutine can be called at any moment. In its initial code, it can be necessary for the routine to check the program status to determine what is to be done. The program status can be maintained in a set of global logical variables, and/or in the "textfield", "setting", and "menu" objects. The "callback" routines have complete control of the machine while active. They can open or close windows using "open_window" and "close_window", draw in "canvas" objects using the normal graphical functions, print messages in "tty" (using "ttysw_output") or "message" objects (using "xv_set"), or anything else that does not corrupt the interface structures. The user is never prompted for information in a way that blocks the program execution (it is possible, if necessary, through windows with exclusive access (see the file "exclusiv.inc"), but not recommended). The procedure for getting information from the user is to open a window with items to filled. "Callback" routines associated with the window objects update the program status and continue the execution, when and if the user commands. The program never reads the keyboard or mouse directly (it is possible, using the normal functions and the "mickey" module functions, but also not recommended). All the inputs from the user are received as events and actions on the objects. The objects call "callback" routines by three mechanisms, associated with the object attributes: "notify_handler": A "callback" routine, called when: - "frame": The window is closed. - "texfield": The return key is pressed, at the end of an edition. - "canvas": The window is redrawn, on the opening and resizing of the window. - Other objects: The left mouse button is pressed over the object. "event_handler": A "callback" routine, called when the state of the mouse changes over the object, or when a key is pressed, with the mouse pointer over the object. "menu_name": Name of a "menu", opened with the right mouse button pressed over the object. The menus normally have an associated "notify handler", called when a selection is done. It is also possible to open a menu programatically, using the "menu_show" procedure. The items of a menu can have an associated "item_submenu" (name of another menu),also opened with the right mouse button. The same is valid for submenus of any order. The left mouse button always cause the selection of the present item, even if there are submenus. The central mouse button (or both right and left buttons simultaneously) cause the dismiss of menus without a call to the menu "notify_handler". The "callback" routines have always the same structure. They are far procedures receiving a single argument, that is the calling object pointer. Using this pointer, the parameters of the calling object can be accessed. EVENTS ------ The "event_handler" routines can read the event that caused the call in the global variable "ie_code". Its meanings are: - Mouse events: "ie_code" contains: LOC_MOVE: Movement. LOC_DRAG: Movement with some button pressed. MS_LEFT: Left button pressed. MS_MIDDLE: Central button pressed. MS_RIGHT: Right button pressed. The state of the mouse buttons (as returned by the DOS interrupt 33) is in the global variable "ie_shiftcode". The event names above are predefined constants. In the general case for button events, "ie_code"=1000+10*+. The mouse position, relative to the object upper left corner, is in the global variables "ie_locx" and "ie_locy". The absolute mouse position is also available in the variables "mousex" and "mousey", defined in the "mickey" module. - Keyboard events: "ie_code" contains the ASCII code of the pressed key. In the case of keys with extended codes, "ie_code" contains 2000+2nd code. With the mouse emulator in operation (see the MOUSE DRIVER section), events that are used by the emulator are not generated, unless the ScrollLock key is active, what returns the keyboard to normal operation. Some events interpreted by the interface are not passed to the "event_handlers". Only the "canvas" objects receive all the events. In any way, there is no much sense in detecting events over other objects. WINDOWS ------- There is always an active window, which "frame" pointer is equal to the global variable "active_w". The active window is the last opened by the program, or where a button mouse was pressed most recently. To press a mouse key over a window partially covered causes its movement to the foreground before the processing of the event. The procedures "open_window", "close_window", "xv_set", "ttysw_output", and "xv_main_loop" also move their parameter window to the foreground and turn them into the active window. Windows are closed with the procedure "close_window", or by pressing the central mouse button in the header or an empty area of the window. The "frame" parameter "adjust_exit" controls if the window can be closed by the central mouse button. To press simultaneously the right and left mouse buttons has the same effect. Windows are always movable and resizable. Their minimum sizes are controlled by the "frame" parameters "dxmin" and "dymin". If the window contains objects with bitmaps or "tty" and "canvas" objects, these values shall be set to a value high enough to impede the window to be reduced below the size needed for these objects. The default minimum sizes are dxmin=99 and dymin=99 (100x100 pixels). Objects of type "canvas" and "tty" can change in size to accommodate changes in their window sizes. This behavior can be controlled by the parameters "canvas_xext", "canvas_yext", "tty_xext", and "tty_yext", that control if the objects extend to the window right and bottom edges. As default, they do it. GRAPHICAL OUTPUT ---------------- Usually, graphical output is created with the normal Pascal and C procedures and functions, called from the "callback" routines. When the "callbacks" are called, the "viewport" is set to the last "canvas" of the active window, or by the active area of the active window if there is no "canvas" on it. It is possible to change the "viewport" to draw in other areas, but usually it is not necessary. The present "viewport" is contained in the parameter "gr_out" of the active window. When it points to a "canvas" area, there is a 1 pixel margin for the "canvas" border, so the usable area is from (0,0) to (dx-2,dy-2), where "dx" and "dy" are the canvas width and height parameters. The mouse support is totally transparent. It is not necessary to turn off the mouse cursor to draw, as the "callbacks" are always called with the cursor off. The simplest way of generating drawings correctly is from the "canvas" notify and event handlers. The "notify_handler" is called when the window is opened or resized. The code in it shall be able to reproduce the entire drawing, usually scaled to the window dimensions. The "event_handler" can cause editing functions in a drawing, provide cursor functions, etc. Frequently it is desirable to draw in a "canvas" from other "callbacks". It is possible if the window containing the "canvas" is first turned into the active window. There is no problem when the owner of the "callback" belongs to the same window, or to a menu called from a window object. If it is not the case, the "canvas" window can be activated with a call to "open_window". The operation can be impossible due to memory limitations, and so after the call the global boolean variable "xv_ok" shall be tested before any drawing operation. It is frequently useful also to call a "canvas" "notify_handler" from another "callback" to cause a complete redrawing. The "canvas" window must be the active window for correct results. Note that a call to "open_window" when the window is not in the screen causes a call to the "canvas" "notify_handler". So, if the "canvas" window is not in the screen, the call to the "notify_handler" after the call to "open_window" is not necessary (it would cause two redrawings). If the canvas window is on the screen (the "frame" attribute "mapped" contains this information), a safe procedure is to close all the windows that are above it before drawing. In Pascal, the code for this is: WHILE not active_w = DO close_window(active_w); If a "callback" routine changes the graphical configuration (LineStyle, TextStyle, etc.) and calls a procedure that draws interface objects, as "open_window" or "ttysw_output" (not recommended), it must replace the configuration as it was before the call (the initial defaults). Only one "canvas" shall be put in each window, or only the last defined one will be automatically accessible. See the "rotor.pas" example to see how multiple "canvas" objects can be used in the same window. TEXT OUTPUT ----------- The procedure "ttysw_output" draws text in "tty" objects. The "tty" window is opened automatically. The procedure can be called from anywhere in the program. All the written text is stored in a buffer, and can be reviewed using the "tty" scrollbar. To read the buffer: The text starts at "bstart" and ends at "tend"-1. The buffer is circular, with the position "0" coming after the position "bsize". BITMAP IMAGES ------------- Objects of types "button" and "message" can display a bitmap image instead of a text label. If the parameter "icon_label" or "icon_msg" is set, the parameter "xv_label" is interpreted as the name of a file containing the image, that is loaded and plotted when the object is drawn. The supported format is the Windows BMP format, in 16 colors. If the global variable "use_palette" is set (default), the palette in the VGA screen is set to the palette in the bitmap. Note that the default Windows palette is not the same used in Turbo Pascal and C. The gray shade is darker, for example, so it may be necessary to change some of the default colors of the interface objects if Windows bitmaps are used. Bitmaps cannot have more than 640 pixels horizontally, and a "frame" containing bitmap objects must be big enough to contain the complete images. The bitmap plotting routine used internally, "drawbitmap", is available for other uses. INTERPOSITION ------------- It is possible to install an "interposer" procedure, called after each event, before the determination of the mouse cursor location. It is a special "callback" routine without parameters, and that is called with the cursor on. The interposer routine can modify the event and the mouse position, open and close windows, open a menu, etc. It is necessary to turn off the cursor before calls to "open_window" or "ttysw_output", calling "cursor_off" ("mickey" module). It is not necessary to turn on the cursor on exit. The "interposer" can implement utilities as "accelerator keys" (see modules hotkeys.int and tabkeys.int), help, event filtering, etc. To activate: insert "interposer:=;" somewhere after "xv_init". To inactivate: "interposer:=nointerpose;" Events generated in internal operations, as while a "textfield" is in edition, are not passed to the "interposer". MEMORY USAGE ------------ In the normal usage, the objects are allocated at the beginning of the program execution, and are kept until the end. Dynamic allocation is also possible. All the memory used for the interface objects is allocated in the heap. In the protected mode versions, the heap can use all the available extended (XMS) memory, and with an appropriate driver (as in GNU C), all the disk as virtual memory. Window movement and reordering use additional memory, freed at the end of the operation. Window operations that need more memory than the available are refused, and a "beep" sounds. The global variable "xv_ok" turns into false or 0 when this occur. Programs shall avoid to put big windows above other windows, to minimize memory use. Large windows shall be put directly over the background. The objects allocate the amounts of heap memory listed below (Pascal version): - "SizeOf(xv_widget)" bytes (262). - The size of the strings used in the "menu" and "setting" items (Pascal only). - The size of the buffer used in "tty" objects ("bsize"+1 bytes). - The bitmap area in a "button" or "message" with a bitmap. - For a window that is in the screen and covering others, an area storing the image covered. Images of window backgrounds and bitmaps are saved in "figstruct" records or structures. Programs that use dynamic allocation of objects shall contain object "destructors". A "destructor" is a procedure that deallocates the four first items listed above when the corresponding objects are "destroyed". The most usual procedure is to use a "destructor" as the "notify_handler" of a window "frame". In this way, the "destructor" is automatically called when the window is closed, and deallocates all its objects. The window area is automatically freed when the window is closed. New windows are created normally with calls to "xv_create". Note that the procedures "xv_create" and "item_create" allocate memory, and so can fail if there is not enough heap memory. See the example program "xbitmap.pas" for an example of how to use dynamic allocation. Heap memory for the program can be allocated or deallocated at any moment. The Pascal "Mark" and "Release" functions cannot be used. COLORS AND GRAPHICS MODES ------------------------- All the graphics boards and modes supported by the BGI drivers are accepted. The default colors are used in the EGA and VGA boards. In modes with two colors, a pattern of black and white dots is used in place of the gray color in the objects. The colors can be changed changing some global constants, or changing the palette. SOME RECOMMENDATIONS -------------------- Use the "x_make" program to generate the initial version of an interface, editting it as needed after to fill the "callbacks" and other alterations. Keep the structure that "x_make" generates. Note that some objects that are never referenced, as buttons, must not be declared separately. "x_make" declares all the objects for clarity. Do not use dynamic object allocation, windows with exclusive access, or interposition unnecessarily. Keep rigorously the philosophy that the commands in the windows can be acessed at any instant. The most that the program shall do to impede access to an object is to close the window that contains it. Verify carefully the effects of commands given by the user out of the expected order. Make the program warn the user in these cases and recommend the correct action. Warnings of possibly incorrect or dangerous operations, asking for immediate confirmation, are valid uses for windows with exclusive access. Make a window as the main window, putting it over the background and impeding its closing with the mouse (^.adjust_exit:=FALSE). Use smaller windows for dialog with the user. At least one window shall contain a "tty", used for messages to the user, listings, etc. Create a menu, always accesible, that opens any of the program windows. It is the simplest mean to avoid possible "deadlocks" in a complex program. FILES, COMPILATION, AND DIRECTORIES ----------------------------------- For compilation with Turbo Pascal (Version 7.0), the files "xview.tpu" and "mickey.tpu" (or the equivalent .tpp files for protected mode programs) must be accessible. For execution, the BGI driver and the font "litt.chr" must be in the local directory, or in a path pointed by the DOS environment variable "TPBGI". Bitmaps used in buttons or messages, or drawn by the "drawbitmap" routine, must be in the local directory, or in a path pointed by the DOS environment variable "BMP". For compilation in C/C++, see instructions in the file "xview.h". LICENSING AND USE OF THE XVIEW-PC INTERFACE ------------------------------------------- The use of the interface is free for educational and academic purposes, not commercial. The compressed file XV_PC*.ZIP can be distributed freely, respected these restrictions, and that it cannot be changed in any way without the consent of the author. The code is offered "as is". The author believes that everything is working correctly, but cannot be responsible for eventual losses caused by imperfections or bugs in the code. For commercial use, the author is requiring a registration fee of US$ 50. Registered users have the right to receive the source code of the interface. For the clarifying of doubts, information about detected problems, etc., the interested shall contact the author: Dr. Antonio Carlos Moreirao de Queiroz COPPE/UFRJ - Programa de Engenharia Eletrica CP 68504 21945-970 Rio de Janeiro, RJ, Brasil e-mail: acmq@coe.ufrj.br CONSTANTS AND VARIABLES DEFINED IN THE XVIEW UNIT ------------------------------------------------- This is a translation of the unit header "xview.int", that is commented in Portuguese. The variables below marked with "#" are object parameters that usually are changed immediately after the object creation. All have safe default values. The variables marked with "*" are reserved for internal use, and shall not be modified in the normal interface operation. The others can be changed at any moment. For more information about the C/C++ version, see the file "xview.h". The variables and functions of are mostly a direct translation of the Pascal versions. CONST LOC_MOVE=256; {event: mouse moved} LOC_DRAG=257; {event: mouse moved with pressed button(s)} MS_LEFT=1001; {event: left mouse button pressed} MS_MIDDLE=1004; {event: middle mouse button pressed} MS_RIGHT=1002; {event: right mouse button pressed} m_itens=20; {maximum number of items in menus and setting (only 16 in these)} m_chars=60; {characters in strings} mrgx=5; {lateral and bottom window margins} mrgy=22; {upper window margin} CONST normal_bsize:WORD=1000; {"bsize" (tty) attributed by "xv_create"} normal_length:INTEGER=16; {"value_length" (textfield) attributed by "xv_create"} wallpaper:BOOLEAN=FALSE; {if the screen background is retained} c_normal:INTEGER=lightgray; {color of object background} c_active:INTEGER=green; {color of pressed buttons} c_light:INTEGER=white; {color of lighted corners} c_shadow:INTEGER=black; {color of shadowed corners} c_white:INTEGER=white; {default "back_color"} c_black:INTEGER=black; {default "fore_color"} c_overwrite:INTEGER=lightred; {edition color for "textfields"} c_edit:INTEGER=blue; {selection color for "textfields"} c_insert:INTEGER=yellow; {insertion color for "textfields"} c_hatch:INTEGER=cyan; {color of the background pattern} type_hatch:INTEGER=XHatchFill; {type of the background pattern} use_palette:BOOLEAN=TRUE; {if the bitmap palettes are used} normal_client_data:POINTER=nil;{"client_data" attributed by "xv_create"} nlines:INTEGER=60; {* number of lines in each image block} TYPE figstruct=RECORD {structure for images} blocks:INTEGER; {number of image blocks-1} blocksize,lastblocksize:WORD; {size of the allocated image blocks} v:ARRAY[0..2000] of POINTER; {only allocated until "blocks"} END; ptrfig=^figstruct; {image pointer} Xv_opaque=^xv_widget; {generic object} xv_handler=PROCEDURE(pt:Xv_opaque); {"callback" procedure} xv_label_type=STRING[m_chars]; {all strings} tty_buffer=ARRAY[0..65534] OF CHAR; {"tty" buffer. Only "bsize"+1 bytes are allocated and used} xv_package=(frame,button,textfield,setting,message,canvas,tty,menu); xv_widget=RECORD {Parameters used in all the objects} xv_label:xv_label_type; {# title} x,y,dx,dy:INTEGER; {# position and size} fore_color,back_color:INTEGER; {# colors} owner:Xv_opaque; {* owner "frame"} next:Xv_opaque; {* next object} menu_name:Xv_opaque; {# associated menu} notify_handler:xv_handler; {# associated notify handler} event_handler:xv_handler; {# associated event handler} client_data:POINTER; {# pointer to other parameters} {Specific parameters for each object} CASE o_type:xv_package OF {* object type} frame:(over,under:Xv_opaque; {* neighbor windows} Pw:ptrfig; {* covered image} areaw:LONGINT; {* window area size} dxmin,dymin:INTEGER; {# minimum dimensions} interfere:BOOLEAN; {* internal use} mapped:BOOLEAN; {* if it is on the screen} adjust_exit:BOOLEAN; {# if central button can close} mouse_obj:Xv_opaque; {# object pointed by the mouse when the window is opened. nil if none (default)} gr_out:ViewPortType); {* associated "ViewPort"} button:(icon_label:BOOLEAN; {# if "xv_label" is a file name} Pimageb:ptrfig); {* button bitmap} message:(icon_msg:BOOLEAN; {# if "xv_label" is a file name} Pimagem:ptrfig); {* message bitmap} textfield:(panel_value:xv_label_type; {# text value} panel_real:REAL; {# real value} panel_int:INTEGER; {# integer value} min_value,max_value:INTEGER;{# limits for integers} value_length:INTEGER; {# edition field length} field_type:(text_field,real_field,int_field)); {# type} setting:(itens_setting:INTEGER; {* number of itens} sel_setting:INTEGER; {# selection} item_setting:array[1..m_itens] OF ^xv_label_type;{* item names} exclusive:BOOLEAN); {# if the selection is exclusive} canvas:(can_xext,can_yext:BOOLEAN); {# if the "canvas" extends to the window borders} tty:(tty_xext,tty_yext:BOOLEAN; {# if the "tty" extends to the window borders} xc,yc:INTEGER; {* graphical cursors} bsize:WORD; {* buffer size} bstart:WORD; {* buffer start} tstart:WORD; {* visible text start} bcsr:WORD; {* visible text end} tend:WORD; {* text end+1} dxtty:INTEGER; {* panel width} Pb:^tty_buffer); {* buffer pointer} menu:(itens_menu:INTEGER; {* number of items} sel_menu:INTEGER; {# selected item} item_menu:ARRAY[1..m_itens] OF ^xv_label_type; {* item names} item_submenu:ARRAY[1..m_itens] OF Xv_opaque); {# submenus} END; VAR insert:BOOLEAN; {if text is inserted in "textfields"} xv_end:BOOLEAN; {ends "xv_main_loop"} ulttxt:xv_label_type; {last text entered in "textfields"} xv_ok:BOOLEAN; {* result of the last window operation} ie_locx,ie_locy:INTEGER; {* mouse position relative to active object or window} ie_code:INTEGER; {* event code} ie_shiftcode:INTEGER; {* mouse buttons state} active_w:Xv_opaque; {* the active window "frame"} active_o:Xv_opaque; {* active object} w_base:Xv_opaque; {* base window for "xv_create"} o_base:Xv_opaque; {* base object for"item_create"} redrawing_frame:BOOLEAN; {* if a window is being redrawn} interposer:PROCEDURE; {routine called after each event} {Public subroutines. Only the first four are of essential use} PROCEDURE xv_init(board,mode:INTEGER); {General initialization. Enters the specified graphics mode, initializes colors and mouse, and sets "active_w" to "nil"} FUNCTION xv_create(obj_type:xv_package):Xv_opaque; {Allocates and initializes with default values an object. Returns its "handle" pointer. Allocates the buffer "tty_buffer" of "tty" objects, with "GetMem(Pb,bsize+1)". Must be called once for each object, beginning by the window "frame". Does not test possible "heap overflow"} PROCEDURE item_create(txt:xv_label_type); {Creates "menu" or "setting" items. Call once for each item, immediately after "xv_create". The items are enumerated from 1. In the Pascal version, the texts are allocated with GetMem(,Length(txt)+1). Does not test "heap overflow".} PROCEDURE xv_main_loop(w:Xv_opaque); {Opens a window and starts the cycle wait for event - process event. Ends when all the windows are closed or when "xv_end" is true. Does not deallocates the objects at exit. Can be called more than once to create a special window. See the files "exclusiv.inc" and "notice.h" for examples.} PROCEDURE open_window(w:Xv_opaque); {Opens a window, turning it the active one. The selected window is opened and/or put in the foreground. Causes calls to "canvas" "notify_handlers" if the window is not in the screen. Can be called at any time after "xv_init". Calls before "xv_main_loop" can be used to start a program with several open windows} PROCEDURE close_window(w:Xv_opaque); {Closes a window. Causes a call to the "frame" "notify_handler", if installed. Can also be called at any moment after "xv_init". The window is moved to the foreground and erased. The window objects are kept allocated} PROCEDURE ttysw_output(terminal:Xv_opaque; text:STRING); {Writes a text in a "tty" terminal. The "tty" window is opened and turned the active window} PROCEDURE back; {Circulates back the windows, moving the present active window to the background. Useful in window menus} PROCEDURE xv_set(obj:Xv_opaque; new_label:xv_label_type); {Changes the "xv_label" of an object. The window object is turned the active window. Mainly used to change "messages". Can be used to update also other parameters, as "textfield" values, directly set before the call} PROCEDURE menu_show(obj:Xv_opaque); {Opens a menu at the mouse location (mousex, mousey). It is better to associate menus to the objects. This is the routine used internally to open menus. A typical use is to make a button open a menu, by calling "menu_show" from the button "notify_handler"} PROCEDURE draw_object(obj:Xv_opaque; active:BOOLEAN); {Draws an object. Can be used causing the fast redraw of a window (use the "frame" as parameter), as a more powerful version of "xv_set". "active" affects only buttons. For objects that are not "frames", the background is not erased, and labels are only drawn if the global variable "redrawing_frame" is true. This routine is used internally. Its use is not recommended} PROCEDURE Nothing(obj:Xv_opaque); {Default "notify_handler" and "event_handler". No action. Can be used to inactivate "callbacks"(unusual)} PROCEDURE nointerpose; {Default "interposer". No action. Can be used to inactivate the "interposer"} PROCEDURE wait_button; {Waits until the mouse buttons are released (unusual).} FUNCTION Cpct(x:REAL):STRING; {Returns a more compact form of a real number (Pascal version only)} PROCEDURE DrawBitmap(x,y:INTEGER; VAR dw,dh:INTEGER; VAR Pimg:POINTER; filename:xv_label_type); {Draws a Windows 16 colors bitmap at (x, y). If "Pmgi=nil", loads the bitmap from disk (BMP format) and, if possible, allocates memory and saves it in "Pimg^" as a "figstruct" structure. Posterior calls cause a faster drawing. The used memory is "FigureSize(0,0,dw,dh)" bytes. The dimensions "dw" and "dh" are returned (width-1 and height-1). It is used internally to draw "buttons" and "messages" with images. "Pimg" can be the address of another "figstruct" variable. Note that, as "PutImage" does not clips at the "viewport" limits, the window that contains bitmaps must be always of enough size to contain them} {The routines below are used internally in operations involving images. They are also available for other uses} FUNCTION FigureSize(x1,y1,x2,y2:INTEGER):LONGINT; {Memory needed for an image. Size of the "figstruct" structure} PROCEDURE GetFigureMem(VAR p:ptrfig; dw,dh:INTEGER); {Allocates memory for an image. "dw" and "dh" are width-1 and height-1} PROCEDURE FreeFigureMem(p:ptrfig); {Frees memory allocated previously with "GetFigureMem"} PROCEDURE GetFigure(x1,y1,x2,y2:INTEGER; p:ptrfig); {Captures an image from the screen. "ptrfig" must be allocated with "GetFigureMem" before the call} PROCEDURE PutFigure(x,y:INTEGER; p:ptrfig; bitblt:WORD); {Draws an image captured with "GetFigure" at (x, y) in the screen} THE MOUSE DRIVER (MICKEY MODULE) -------------------------------- The "mickey" unit or object file implements the mouse functions of the interface. Normally it is not necessary for a program to use the mouse functions directly, but they are available. If the mouse is not installed, the keyboard emulates it. The cursor moves the arrow, and the buttons are substituted by: left: Return central: Escape right: Space The keys Home, PgDn, and PgUp change the cursor step. With CapsLock or Shift (in the Pascal version) active, the buttons work in toggle mode. ScrollLock suspends the emulation when active, allowing normal use of the keyboard. The unit can be used alone. For the correct working of the emulator, the function "mouse_read" must be called regularly. CONSTANTS AND VARIABLES DEFINED IN THE MICKEY UNIT -------------------------------------------------- This is a translation of the file "mickey.int". See the file "mickey.h" for informations about the C/C++ version, that implements the same functions. VAR mousex,mousey,mouseb,x_factor:INTEGER; {mouse state} cursor_active:BOOLEAN; PROCEDURE mouse_init; {Initialization} PROCEDURE cursor_on; {Cursor on} PROCEDURE cursor_off; {Cursor off} PROCEDURE mouse_read; {Reads current state} PROCEDURE mouse_move(x,y:INTEGER); {Moves cursor} FUNCTION mkbhit:BOOLEAN; {Identical to KeyPressed (of kbhit), but do not report keys used by the mouse emulator, when active. Internal use} WHAT IS NEW ----------- Version 1.7: August 1994 - The GNU C version was added. - Events used by the interface are not passed to the event handlers. - Some changes were made in the examples and documentation. Version 1.6b: May 1994 (updated in July 1994). Restricted distribution. - The C version works with C or C++ with the same object files. - Small bugs in the include files were corrected. - The C example was modified. - Added comments about the GNU C (djgpp) version. Version 1.6a: April 1994. - Keys with extended codes generate only one event (2000+2nd code). This is the only change that may cause some changes in programs written for the previous version. - A version of the C object files compatible with C++ was added. - The C versions were compiled with the "huge" model. - The functions "kbhit()" (C), and "KeyPressed" (Pascal) now function normally. The function "mkbhit" shall be used instead of them. - When the mouse emulator is active, only the events used by it are not generated (arrows, home, pgup, pgdn, cr, space, and esc). - The documentation of the C version and all examples was translated to English. - Small bugs in the "textfield" editor (C version), in menu operations, and in the "tty" were corrected. - Word alignment is not necessary anymore. - The "interposer" was included. - The "textfield" editor and the Cpct function (Pascal) were modified. - Source files with some utilities and examples were added (extkeys, notice, exclusiv, hotkeys, tabkeys, rotor). Version 1.6: First version distributed to the Internet, December 1993. ACMQ - 03/08/94