campo-sirio/xi/xiport.c
guy 88cfa4d4cb Patch level : 10.0
Files correlati     : xi.dll
Ricompilazione Demo : [ ]
Commento            :
Aggiunto supporto per group box con spigoli smussati


git-svn-id: svn://10.65.10.50/trunk@18129 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-01-28 08:55:42 +00:00

5848 lines
149 KiB
C
Executable File

/*******************************************************************************
* Copyright 1991-1996 by ORCA Software, Inc. *
* *
* All rights reserved. May not be reproduced or distributed, in printed or *
* electronic form, without permission of ORCA Software, Inc. May not be *
* distributed as object code, separately or linked with other object modules, *
* without permission. *
*******************************************************************************/
#define XIN_INTERNAL_WINDOW
#define XIN_INTERNAL_FONT
#define XIN_INTERNAL_BITMAP
#define XIN_INTERNAL_PRINT_RECORD
#define XVT_INCL_NATIVE
#include "xvt.h"
#include "xi.h"
#include "xiport2.h"
#include "stdarg.h"
#if XIWS == XIWS_WIN
#include <commdlg.h>
#include <direct.h>
#endif
#if XIWS == XIWS_PM
#include <direct.h>
#endif
#if XIWS == XIWS_WM || XIWS == XIWS_XM || XIWS == XIWS_WXGTK
#define COALESCE_UPDATES
#endif
#define XIN_CARET_WIDTH 1
#define MEMCLEAR( x ) memset(( char* )&( x ), '\0', ( size_t )sizeof( x ))
/* We are forced to cast for XVT windows */
struct s_XinWindow
{
int dummy;
};
struct s_XinFont
{
/* Set in the XVT font convert, checked in compare since other values won't
* be set, just the xvt_fntid */
BOOLEAN from_xvt_font;
BOOLEAN bold;
BOOLEAN italic;
XinFontFamily family;
int size;
XVT_FNTID xvt_fntid;
};
struct s_XinBitmap
{
XVT_IMAGE image;
};
/* We are forced to cast for XVT print record */
struct s_XinPrintRecord
{
int dummy;
};
#ifdef COALESCE_UPDATES
typedef struct
{
int coalescing;
BOOLEAN invalidated;
XinRect inv_rct;
} XinCoalesceData;
#endif
typedef struct s_window_info
{
WINDOW win;
XinWindowEventHandler event_handler;
XinWindow prev_modal;
#ifdef COALESCE_UPDATES
XinCoalesceData coalesce;
#endif
} WindowInfo;
static WindowInfo *window_list;
static int nbr_windows;
static EVENT *cur_xvt_event;
static XinWindow xin_modal_win;
static XinWindow xin_autoclose_win;
static BOOLEAN app_terminating;
static XinMenu *xin_finish_create_menu = NULL;
static XinWindowDef *xin_finish_create_def = NULL;
XVT_PALETTE xin_palette = NULL;
XinWindowEventHandler xin_teh;
char *xin_buffer = NULL;
BOOLEAN xin_xvt_initialized = FALSE;
void XinWindowCreateFinish( XinWindow win );
static void
realloc_array( void **ptr, int nbr, size_t sz )
{
BOOLEAN is_zero = ( nbr * sz ) == 0;
if ( !*ptr )
{
if ( is_zero )
*ptr = NULL;
else
*ptr = ( void * ) XinMemoryAlloc( nbr * sz );
}
else
{
if ( is_zero )
{
XinMemoryFree( *ptr );
*ptr = NULL;
}
else
*ptr = ( void * ) XinMemoryRealloc( *ptr, nbr * sz );
}
}
void
XinXvtWindowRegister( XinWindow win, XinWindowEventHandler EventHandler )
{
WindowInfo *info;
++nbr_windows;
realloc_array( ( void ** ) &window_list, nbr_windows, sizeof( WindowInfo ) );
info = window_list + ( nbr_windows - 1 );
info->win = ( WINDOW ) win;
info->event_handler = EventHandler;
info->prev_modal = XI_NULL_WINDOW;
#ifdef COALESCE_UPDATES
info->coalesce.coalescing = 0;
#endif
}
static WindowInfo *
find_window_info( WINDOW win )
{
int cnt;
WindowInfo *info = window_list;
for ( cnt = 0; cnt < nbr_windows && info->win != win; cnt++, info++ )
;
if ( cnt == nbr_windows )
return NULL;
return info;
}
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
static WindowInfo *
find_window_info_from_HWND( HWND win )
{
int cnt;
WindowInfo *info = window_list;
for ( cnt = 0; cnt < nbr_windows
&& ( HWND ) xvt_vobj_get_attr( info->win, ATTR_NATIVE_WINDOW ) != win;
cnt++, info++ )
;
if ( cnt == nbr_windows )
return NULL;
return info;
}
#endif
static void
deregister_window( WINDOW win )
{
WindowInfo *info;
info = find_window_info( win );
if ( info != NULL )
{
int cnt = ( int ) ( info - window_list );
--nbr_windows;
if ( nbr_windows > cnt )
memmove( window_list + cnt, window_list + cnt + 1,
( nbr_windows - cnt ) * sizeof( WindowInfo ) );
}
}
#if XIWS == XIWS_WM
static void
xi_fix_color( COLOR * color )
{
if ( *color == XI_COLOR_BLACK )
*color = XI_COLOR_WHITE;
else if ( *color == XI_COLOR_WHITE )
*color = XI_COLOR_BLACK;
}
#endif
#if XIWS == XIWS_PM
/* This function is required to fix a scrolling problem on PM. */
/**** RGM: This is a mess - there is only one "old_pm_proc" for all windows */
PFNWP old_pm_proc = NULL;
static MRESULT EXPENTRY
pm_proc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
switch ( msg )
{
case WM_HSCROLL:
case WM_VSCROLL:
{
if ( SHORT2FROMMP( mp2 ) == SB_ENDSCROLL )
{
WinSetFocus( HWND_DESKTOP, hwnd );
return ( ( MRESULT ) 0 );
}
}
break;
}
return ( old_pm_proc( hwnd, msg, mp1, mp2 ) );
}
#endif
/*START*/
/*
Abstractions:
Abstractions in this module encapsulate and contain state information for
certain entities that are necessary for the proper operation of this module.
The structures or classes that coorespond to these abstractions are defined
locally in this module. Code outside of this module only sees an opaque
data type, and *must* use functions in this module to manipulate the
abstractions. The developer of this module is free to put data members into
the locally defined structure or class, so that this module has the correct
state information to function properly.
XinWindow
this abstraction encapsulates the state and information for a created
window. also, we use an XinWindow to encapsulate the state and information
for horizontal and vertical scroll bars. scroll bars are the only controls
that Xin implements. XinWindow is also used for print windows.
examples are:
- the handle to the native window
- a pointer to the XinWindowEventHandler
- a pointer to the previous modal window, for proper implementation of modals
- a long integer for storing application data upon request of the module that
uses Xin
when creating an XinWindow, we pass in an XinWindowDef as an argument to
XinWindowCreate. an XinWindowDef contains all of the information necessary
to properly create either the scroll bar or the window. XinWindowType is an
enum that specifies whether to create a window or a scroll bar, and what kind
of window or scroll bar to create. The XinWindowMode determines "modality" of
the window. XinModeless is a normal window. XinModalReturn will create a window
that is the only window that can get focus and the XinWindowCreate function
will return as soon as the window is created. XinModalWait will create a window
that is the only window that can get focus and the XinWindowCreate function
will return when that window is destroyed. XinModalAutoclose will create a window
that will close automatically as soon as it loses focus. Note that XinModalReturn
and XinModalWait windows can be nested to open new modals windows. Creating
a modeless window while a modal window is open should create it without focus.
Autoclose windows can also be created "on top" of modal windows.
one of the more difficult things to handle is our concept of a modal window.
if MFC has a modal window, we should use it. however, if we need to implement
modal windows by disabling and re-enabling windows, we will wait until later
on in this project to implement them.
for historical reasons, in the XVT implementation, an XinWindow is, in fact,
the XVT window. this complicates the implementation because we then need to
keep state information on the window in a separate structure, and look up the
window information in a list whenever we need to access it. in the MFC
implementation, we will define a class that holds the state information on the
window, and the XinWindow should be a pointer to that class.
windows can be enabled or disabled. a disabled window still responds to
paint events, but can't be raised, and doesn't receive character or mouse
events.
windows can be visible or invisible. an invisible window does not generate
any paint events, nor receive character or mouse events.
Xin does not implement child windows.
the client area of a window is the area in which the module using Xin can draw.
the actual visible size of the window includes the border, title and menu which
are not part of the client area of the window. sometimes the
associated controls on the border are called the window decorations.
there are two XinWindows that are automatically created before
XinAppSystemSetupInit is called. the first is the task window. this allows
the module using Xin to manipulate the task window. the second is the screen
window. This allows Xin to draw directly onto the screen.
XinFont
this abstraction encapsulates the data necessary to specify a font. the
font can then be passed as an argument to XinWindowTextDraw, specifying
the font that the text is drawn in.
The XinFont can be created and set using a basic set of 'family' values, or
it can be the result of a font selection dialog. In either case, the
properties of 'bold', 'italic' and 'family' must be retrievable from the
XinFont. If the family does not match the basic set, then XinFontFamilyOther
will be used.
fonts can be mapped or unmapped.
after a font is mapped to a window, then the module using Xin can call
functions that use the font for drawing, or to get pixel metrics of the font.
if a font is mapped to a screen window, then the pixel metrics will be very
different than if the font is mapped to a printer window.
XinPrinterRec
This abstraction encapsulates the data for a selected printer.
It is used for printing operations and it should be possible to
save this structure in a file and load it later. (The size of
the structure is returned by XinPrintRecordCreate.)
XinBitmap
this abstraction encapsulates a bitmap that can be drawn into an XinWindow.
the internal format of an XinBitmap is the BMP format. this simplifies the
process of reading bitmaps from files or dlls, then subsequently drawing the
bitmap in a window.
XinRect
this structure contains the four points of a rectangle (top, left, bottom, right).
it is used in calls to many Xin functions.
XinPoint
this structure contains the horizontal and vertical components of a point (h, v)
Application
the Xin module contains the main (or win_main) or whatever function is
automatically executed when an MFC application starts. the module using Xin
needs to write two things for the minimal application. a function called
XinAppSystemSetupInit is written. this function initializes a data structure that
is passed in as an argument. this data structure defines certain application
wide characteristics such as the task window title, the task window event handler,
etc. in addition, the argc and argv variables are passed to this function for
processing if the user of Xin desires.
the sequence of actions when an application written using Xin starts is as follows:
1) win_main (or whatever in MFC) is called by the system.
2) win_main does any initial setup, puts argc and argv into the SystemSetup structure
3) win_main calls XinAppSystemSetupInit
4) data structures are set up so that when the system sends events to the MFC task
window handler, the events can be translated and sent to the Xin task window
event handler.
5) win_main returns.
6) windows starts sending event through to the task window event handler.
The "use_mdi" member of XinSystemSetup indicates if MDI should be enabled. The
Window menu will be specified with the tag XI_MENU_WIN. If that tag does not
exist, the Window menu will be created at the end of the existing menu.
The Window menu should contain Cascade, Tile Horizontally, Tile Vertically,
Close All, a separator(if any windows are open), and then the list of open windows,
including a "Windows..." item to open a separate dialog if there are too many
windows for the menu. Even if the XI_MENU_WIN tag exists, the window list will need
to be added to that existing menu. Of course, MDI will also handle iconizing of
top-level windows, etc.
Menus
Xin implements functions to manipulate menus. the functionality includes the
ability to set up an entire menu hierarchy with one call, replace a branch of
the menu hierarchy, replace a single item, change the enabled/disabled state of
any menu item, and change the checked state af a menu item.
there are no facilities to load menus from resources. the entire functionality
of the menu is available only through the api.
immediately after the application starts, the user of the Xin module will
call the function that sets up the entire menu. in the MFC implementation, we
may need to define a small "stub" menu in the windows resources. this stub
menu will not have anything in it other than a file menu with an exit item.
this stub menu will be replaced before the user has any oportunity to do any
menu selections.
there are two data structures associated with menus. an XinMenu is an array and
a count of child XinMenuItems an XinMenuItem is a branch on an XinMenu tree. it
may be the tip of a branch (a menu item that a user can select) or it may be the
parent of multiple child XinMenuItems, in which case, there is a submenu.
The text of menus can contain a '~' to indicate the shortcut key. For example,
"~File", "~Edit", and "E~xit".
Timers
this allows a module using Xin to set a timer
and get an event a specified number of miliseconds in the future. upon creation
of a timer, Xin returns a timer identifier (a long
integer) that identifies the timer. the timer id is part of the data for a timer
event, so that the module using Xin can set up multiple timers, and know which
timer an event is for. the timer identifier is also used when killing the timer.
Clipboard
Xin abstracts operations on the clipboard. the clipboard as implemented by Xin
can have two kinds of formats on it (text, and bitmap). any module using Xin can
query the clipboard, finding whether the desired format of data is on the clipboard,
then the module can get the contents of the clipboard.
Printing
printing has much in common with displayed windows. before printing, a print window
needs to be created. after the print window is created, fonts can be mapped to
the print window, rectangles, lines, and text can be drawn in the window, etc.
there is one fundimental difference. after the print window is created, the module
using Xin must call XinPrintPageStart. then, the module using Xin calls
XinPrintBandNext until it returns NULL. if it is necessary to paint a band at a
time, then XinPrintBandNext will return a rectangle several times. After each return,
the area within the returned rectangle should be drawn by the module using Xin. After
XinPrintBandNext returns NULL, then the module using Xin should call XinPrintPageEnd.
This will cause the page to be printed. If the printer and the printer driver are
capable of printing the entire page at once, then XinPrintBandNext will only return
a rectangle once.
Bob, according to a comment written by John Lilley in the report writer, banding is
no longer used for any XVT implementation. Do we really need to continue to support
banding?
If that's true, then no. But is it true? - Bob
*/
/*
Events
Xin is an event based system. When Xin is informed of certain events in the
underlying system, then Xin should send an event to the module using Xin. the
method of sending an event to the module using Xin is as follows:
1) declare an automatic variable of type XinEvent
2) set every byte in the XinEvent structure to '\0'
3) fill in the XinEvent structure. information that needs to be specified is
the event type, and information specific to that type of event.
4) call the event handler that the module using Xin specified when the application
was created, or when the window was created.
Below is the set of events that Xin needs to generate:
XinEventCreate
This event is sent when a window is created. When the application is starting,
then this event is sent to the task window event handler, which was specified
in the function XinAppSystemSetupInit. This will be the first event for any
window.
XinEventDestroy
This event is sent when a window is destroyed. When the application is
terminating, then this event is sent to the task window event handler. The
window will still be valid during this event, but no other event will occur
for the window after this event.
XinEventFocus
This event is sent when a window is gaining or loosing keyboard focus. A
boolean variable
in the XinEvent structure indicates whether the window is gaining or losing
focus.
XinEventResize
This event is sent when a window is re-sized or minimized.
XinEventPaint
This event is sent when the windowing system needs to have the module using
Xin paint a certain region of a window.
XinEventCloseButton
This event is sent when the user either clicks on the close button in the
upper right corner of the window, double clicks on the window menu at the
upper left corner of the window, or selects close on the window menu. the
window should not be closed when the above actions happen. rather, Xin
lets the module using Xin close the window if it desires.
XinEventMouseDown
This event is sent when the user presses the mouse button within the
bounderies of a window.
Xin reports the pressed state of the shift, control, and alt keys when
generating this event.
XinEventMouseUp
This event is sent when the user releases the mouse button within the
bounderies of a window. If the mouse is trapped to a window, then this
event is sent to the window in which the mouse is trapped, regardless of
whether the mouse is over that window or not.
Xin reports the pressed state of the shift, control, and alt keys when
generating this event.
XinEventMouseMove
This event is sent when the user moves the mouse within the bounderies
of a window. If the mouse is trapped to a window, then this
event is sent to the window in which the mouse is trapped, regardless of
whether the mouse is over that window or not. If the mouse is trapped to
a window, and the mouse is held down, then mouse move events are continually
generated, whether the mouse is moving or not.
Xin reports the pressed state of the shift, control, and alt keys when
generating this event.
XinEventMouseDouble
This event is sent when the user double clicks the mouse within the
bounderies of a window. The sequence of events when the user double clicks
and releases the mouse is:
XinEventMouseDown
XinEventMouseUp
XinEventMouseDouble
XinEventMouseUp
Xin reports the pressed state of the shift, control, and alt keys when
generating this event.
XinEventCharacter
This event is sent to a window when the window has keyboard focus, and the
user presses a key in the window. Character events are translated to
Xin virtual characters. The list of virtual characters is:
XI_KEY_DEL delete key
XI_KEY_UP up arrow key
XI_KEY_DOWN down arrow key
XI_KEY_RIGHT right arrow key
XI_KEY_LEFT left arrow key
XI_KEY_PREV page up key
XI_KEY_NEXT page down key
XI_KEY_LHOME home key
XI_KEY_LEND end key
XI_KEY_WLEFT control left arrow key
XI_KEY_WRIGHT control right arrow key
XI_KEY_BTAB shift tab key
XI_KEY_F1 function keys
XI_KEY_F2
XI_KEY_F3
XI_KEY_F4
XI_KEY_F5
XI_KEY_F6
XI_KEY_F7
XI_KEY_F8
XI_KEY_F9
XI_KEY_F10
XI_KEY_F11
XI_KEY_F12
Xin reports the pressed state of the shift, control, and alt keys when
generating this event.
XinEventMenuCommand
This event is sent when the user selects a menu item. The event reports the
menu tag of the selected menu item. There are no events for navigating menus.
Xin reports the pressed state of the shift and control keys when generating
this event.
XinEventControl
This event is sent when the user operates a scroll bar that was set up by
Xin. The control_id in the XinEvent structure is the control id specified
when the scroll bar was created.
In XinControlInformation, the following fields are set:
type is set to either XinWindowTypeHorizontalScrollBar or
XinWindowTypeVerticalScrollBar
win is set to the scroll bar window
v.scroll.action is set to one of XinScrollBarActionLineUp
XinScrollBarActionLineDown
XinScrollBarActionPageUp
XinScrollBarActionPageDown
XinScrollBarActionThumb
XinScrollBarActionThumbTrack
v.scroll.position is set to the current position of the thumb of the
scroll bar.
XinEventTimer
This event is sent when a timer expires. The module using Xin can set or
kill timers. See the discussion on timers for more details.
XinEventQuit
This event is sent when something or someone requests that Xin terminate.
For instance, when someone shuts down Windows95, then this event is sent.
The application, based on its state, can query the user to see if the user
wants to save changed data, discard changed data, or cancel the shutdown
operation. If, after processing input from the user, and it is still OK
to shut down, then the module using Xin should call XinAppQuitOk. If
XinAppQuitOk is not called, then the shutdown operation is aborted.
XinEventFont
This event does not need to be implemented in MFC.
*/
/*
Drawing
this section details the semantics and behaviors of drawing in windows.
Mathmatical Rectangles
Many of the Xin functions work using 'Mathmatical Rectangles'. By this, we
mean that a rectangle refers to the lines between the pixels, not the pixels
themselves. For instance, when we draw a rectangle, we specify a mathmatical
rectangle, and the pixels that get drawn are those just inside the mathmatical
rectangle.
the following diagram needs to be viewed in a fixed font to appear correctly.
it represents a grid of pixels where the mathmatical lines between the pixels
are numbered, and the spaces represent pixels.
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| | | | | | | | |
2 -----------------
| | | | | | | | |
3 -----------------
| | | | | | | | |
4 -----------------
| | | | | | | | |
5 -----------------
| | | | | | | | |
6 -----------------
| | | | | | | | |
7 -----------------
| | | | | | | | |
-----------------
for instance, if we were to draw a hollow rectangle where:
top = 1
left = 1
right = 4
bottom = 4
then the following pixels would get drawn:
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| |X|X|X| | | | |
2 -----------------
| |X| |X| | | | |
3 -----------------
| |X|X|X| | | | |
4 -----------------
| | | | | | | | |
5 -----------------
| | | | | | | | |
6 -----------------
| | | | | | | | |
7 -----------------
| | | | | | | | |
-----------------
at various points in this module, we will refer to mathmatical rectangles,
and to properly identify the semantics of drawing functions, we will
use diagrams like the ones above.
Clipping
when clipping is set for a window, the drawing functions only draw within
the clipping rectangle. the rectangle for clipping is a mathmatical
rectangle.
the functions that clip to the clipping rectangle are:
- XinWindowRectDraw
- XinWindowLineDraw
- XinWindowTextDraw
- XinWindowBitmapDraw
- XinWindowIconDraw
note that carets do not clip to the clipping rectangle. there is a
rectangle passed in to the XinWindowCaretOn for clipping of the caret.
Text Drawing
The vertical metrics of a font have three components: ascent, descent,
and leading. these are pixel counts of the components of a font.
____
leading ____
xxxxxx
x x
ascent x x
x x
baseline ____ xxxxx
x
descent x
____ xxxx
the baseline is the mathmatical line upon which most text (without
descenders) is drawn. ascent is the number of pixels above the
baseline to the top of the font. descent is the number of pixels
available for the descenders. leading is the space between the lines
of drawn text.
There are two modes of text drawing, opaque, and not opaque. If opaque,
the background color is drawn in the entire leading/ascent/descent area.
The background color is specified by XinWindowColorTextBackSet or by
the drawing tools.
If opaque is set to false, then only the text itself is drawn, using the
foreground color.
XinDrawMode
when drawing, there are two modes of drawing: copy and xor. if the draw
mode is copy, then the pixels are simply copied to the window. if the draw
mode is xor, then, if drawn on pixels equalling the back_color of the window,
drawing will attempt to produce the fore_color of the tool (pen/brush/text).
Drawing on pixels of fore_color will attempt to produce back_color. The
operation is self-reversing. the only thing that xor mode is used for is
drawing rubber band rectangles when moving columns, moving rows, resizing
columns and resizing rows. drawing in xor mode assumes that the window is
on top, and will remain on top until the rubber banding operation is complete.
XinPen
A pen specifies what is drawn for lines or rectangle borders. The 'width'
determines the number of pixels for the line or border. The 'pattern' may
be hollow, solid or dashed. If hollow, then no border will be drawn for a
rectangle. Solid and dashed lines are drawn using the 'fore_color'. Dashed
lines will not draw in the space between the dashes.
XinBrush
a brush specifies what is drawn in the interior of a rectangle. there are
two fields in an XinBrush data structure: 'pattern', and 'color'. if
'pattern' is XinBrushHollow, then 'color' is ignored, and the interior of
the rectangle (the pixels other than those just inside the mathmatical
rectangle) are left alone.
if 'pattern' is XinBrushSolid, then the pixels in the interior of the
rectangle are drawn in the specified color.
XinDrawTools
drawing tools is a convenience feature of Xin. it allows the user of Xin
to set or get the state of drawing (draw mode, brush, pen, fore color,
back color, and text opaqueness) with one function call.
Drawing Rectangles
There are three cases to consider when drawing rectangles:
1) solid pen and solid brush
2) hollow pen and solid brush
3) solid pen and hollow brush
note that it does not make any sense to draw with a hollow pen and a hollow
brush. this would draw nothing.
Example 1: solid red pen and solid blue brush
top = 1
left = 1
bottom = 5
right = 5
this will draw a red one pixel wide rectangle just inside the
specified mathmatical rectangle. it will fill the area inside
the red rectangle of pixels with blue pixels.
the following would be the result, r is a red pixel, b is a blue pixel
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| |r|r|r|r| | | |
2 -----------------
| |r|b|b|r| | | |
3 -----------------
| |r|b|b|r| | | |
4 -----------------
| |r|r|r|r| | | |
5 -----------------
| | | | | | | | |
6 -----------------
| | | | | | | | |
7 -----------------
| | | | | | | | |
-----------------
Example 2: hollow pen and solid blue brush
top = 1
left = 1
bottom = 5
right = 5
this will fill the mathmatical rectangle with blue pixels.
the following would be the result, b is a blue pixel
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| |b|b|b|b| | | |
2 -----------------
| |b|b|b|b| | | |
3 -----------------
| |b|b|b|b| | | |
4 -----------------
| |b|b|b|b| | | |
5 -----------------
| | | | | | | | |
6 -----------------
| | | | | | | | |
7 -----------------
| | | | | | | | |
-----------------
Example 3: solid blue pen and hollow brush
top = 1
left = 1
bottom = 5
right = 5
this will draw a blue rectangle, one pixel wide, just inside
the mathmatical rectangle.
the following would be the result, b is a blue pixel
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| |b|b|b|b| | | |
2 -----------------
| |b| | |b| | | |
3 -----------------
| |b| | |b| | | |
4 -----------------
| |b|b|b|b| | | |
5 -----------------
| | | | | | | | |
6 -----------------
| | | | | | | | |
7 -----------------
| | | | | | | | |
-----------------
Drawing Lines
There are three cases to consider when drawing lines:
1) horizontal lines
2) vertical lines
3) diagonal lines
Example 1: a horizontal line
from
horizontal = 1
vertical = 1
to
horizontal = 6
vertical = 1
this will draw the row of pixels just below the mathmatical line.
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| |x|x|x|x|x| | |
2 -----------------
| | | | | | | | |
3 -----------------
| | | | | | | | |
4 -----------------
| | | | | | | | |
5 -----------------
| | | | | | | | |
6 -----------------
| | | | | | | | |
7 -----------------
| | | | | | | | |
-----------------
Example 2: a vertical line
from
horizontal = 1
vertical = 1
to
horizontal = 1
vertical = 7
this will draw the row of pixels just to the right of
the mathmatical line.
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| |x| | | | | | |
2 -----------------
| |x| | | | | | |
3 -----------------
| |x| | | | | | |
4 -----------------
| |x| | | | | | |
5 -----------------
| |x| | | | | | |
6 -----------------
| |x| | | | | | |
7 -----------------
| | | | | | | | |
-----------------
Example 3: a diagonal line
from
horizontal = 1
vertical = 1
to
horizontal = 4
vertical = 4
taking the mathmatical rectangle formed by placing the two points
at oposite corners, the two pixels just inside the corners of the
mathmatical rectangle are drawn, with some pixels in between. if
the absolute value of the rise and the run are equal, i.e. the line
is a diagonal line 45 degrees off of horizontal and vertical, then
a straight diagonal line is drawn.
0 1 2 3 4 5 6 7 8
0 -----------------
| | | | | | | | |
1 -----------------
| |x| | | | | | |
2 -----------------
| | |x| | | | | |
3 -----------------
| | | |x| | | | |
4 -----------------
| | | | | | | | |
5 -----------------
| | | | | | | | |
6 -----------------
| | | | | | | | |
7 -----------------
| | | | | | | | |
-----------------
Note: the adjustments that we need to make for MFC probably are the same as
the adjustments that are needed to be made for the Windows version of XVT.
*/
/*
Other Notes
Mouse Trapping
the mouse can be trapped to a window. when the mouse is trapped, all mouse
events until the mouse is released go to the window in which the mouse is
trapped. this ensures that if a window receives a mouse down event, it will
be guarenteed to receive the mouse up event.
while the mouse is trapped, if the mouse button is down, the window is
guarenteed to receive mouse move events even if the mouse is not moving. this
facilitates the behavior where the user is selecting text, drags the mouse
outside of the region where they are selecting text, and the text continually
scrolls until the user drags the mouse back into the region, or the user
releases the mouse button.
*/
/*
allocates memory on the heap. the size of the allocated block is indicated
by the argument 'size'. returns a pointer to the allocated memory.
*/
void *
XinMemoryAlloc( size_t size )
{
return malloc( size );
}
/*
frees memory previously allocated by XinMemoryAlloc. the pointer to the
memory is passed in as the argument 'ptr'.
*/
void
XinMemoryFree( void *ptr )
{
free( ptr );
}
/*
reallocates memory previously allocated by XinMemoryAlloc. the new size of
the allocated block is indicated by the argument 'size'. the pointer to be
reallocated is passed in as the argument 'ptr'. returns a pointer to the
allocated memory.
*/
void *
XinMemoryRealloc( void *ptr, size_t size )
{
return realloc( ptr, size );
}
/*
allocates and clears memory on the heap. the size of the allocated block
is indicated by the argument 'size'. returns a pointer to the allocated memory.
*/
void *
XinMemoryZeroAlloc( size_t size )
{
void *ptr = malloc( size );
memset( ptr, 0, size );
return ptr;
}
/*
puts up a modal dialog box with a message and up to three buttons. gets a
response from the user and returns XinResponse1 if button 1 is pressed.
returns XinResponse2 if button2 is pressed. returns XinResponse3 if button3
is pressed.
the argument 'Btn3' may be NULL, in which case only two buttons are put into
the dialog box.
the arguments 'Btn2' and 'Btn3' may be NULL, in which case only one button
is put into the dialog box.
the message is specified by a format and a variable number of arguments,
similar to the function printf
*/
XinResponse
XinDialogAsk( char *Btn1, char *Btn2, char *Btn3, char *format,... )
{
/*END*/
ASK_RESPONSE ask_response;
va_list argptr;
char button1[200], button2[200], button3[200];
XinInitBuffer( );
va_start( argptr, format );
vsprintf( xin_buffer, format, argptr );
va_end( argptr );
xin_buffer[200] = '\0';
if (Btn1 != NULL && strlen(Btn1) >= 200)
{
strncpy( button1, Btn1, 199 );
button1[199] = '\0';
Btn1 = button1;
}
if (Btn2 != NULL && strlen(Btn2) >= 200)
{
strncpy( button2, Btn2, 199 );
button2[199] = '\0';
Btn2 = button2;
}
if (Btn3 != NULL && strlen(Btn3) >= 200)
{
strncpy( button3, Btn3, 199 );
button3[199] = '\0';
Btn3 = button3;
}
ask_response = xvt_dm_post_ask( Btn1, Btn2, Btn3, xin_buffer );
switch ( ask_response )
{
case RESP_DEFAULT:
return XinResponse1;
case RESP_2:
return XinResponse2;
case RESP_3:
return XinResponse3;
}
return XinResponse1;
/*START*/
}
/*
puts up an error message modal dialog box.
the message is specified by a format and a variable number of arguments,
similar to the function printf
*/
void
XinDialogError( char *format,... )
{
/*END*/
va_list argptr;
XinInitBuffer( );
va_start( argptr, format );
vsprintf( xin_buffer, format, argptr );
va_end( argptr );
xin_buffer[200] = '\0';
xvt_dm_post_error( xin_buffer );
/*START*/
}
/*
puts up a fatal error message dialog box. this function should not return,
but should exit the application.
this function should not allocate any memory, as this function might have
been called because the heap is corrupted.
the message is specified by a format and a variable number of arguments,
similar to the function printf
*/
void
XinDialogFatal( char *format,... )
{
/*END*/
va_list argptr;
XinInitBuffer( );
va_start( argptr, format );
vsprintf( xin_buffer, format, argptr );
va_end( argptr );
xin_buffer[200] = '\0';
xvt_dm_post_fatal_exit( xin_buffer );
/*START*/
}
/*END*/
/* This is for a silly bug with openfile dialogs under windows. */
#if XIWS == XIWS_WIN
static void
open_file_hook( OPENFILENAME * lpofn )
{
lpofn->Flags |= OFN_PATHMUSTEXIST;
}
#endif
/*START*/
/*
this function puts up a file open or a file save modal dialog box.
the string in the argument 'message' is put into the dialog box as a prompt
for the user.
if the argument 'type' is XinOpenFileDialog then the open file dialog box is
put up. this allows the user to specify a name of a file to be opened for
reading. the user is supplied with a list of files to choose from. the
user also may change directories to search for the desired file. if a valid
filename is specifed by the user, then this function returns XinFileGood. if an
error occurs, then this function returns XinFileBad after an appropriate error
message is displayed.
if the user canceled the dialog box without specifying a file name, then this
function returns XinFileCancel. upon entry to the function, the argument 'spec'
specifies the file type (a three character extension for the MFC implementation),
the starting directory and the starting file name if desired. see the definition
of XinFileSpec for further details. when this function returns, if XinFileGood
is the returned status, then the argument 'spec' is filled in with the specified
file and directory.
if the argument type is XinSaveFileDialog then the save file dialog box is
put up. this allows the user to specify a name of a file to be created, or
opened for writing. the user is supplied with a list of files to choose from. the
user also may change directories to search for the desired file. if a valid
filename is specifed by the user, then this function returns XinFileGood. if an
error occurs, then this function returns XinFileBad after an appropriate message
is displayed.
if the user canceled the dialog box without specifying a file name, then this
function returns XinFileCancel. upon entry to the function, the argument 'spec'
specifies the file type (a three character extension for the MFC implementation),
the starting directory and the starting file name if desired. see the definition
of XinFileSpec for further details. when this function returns, if XinFileGood
is the returned status, then the argument 'spec' is filled in with the specified
file and directory.
the implementation for MFC should simply put up the standard open or save file
dialog.
*/
XinFileResult
XinDialogFile( char *message, XinFileSpec * spec, XinFileDialogType type )
{
/*END*/
FL_STATUS result;
FILE_SPEC xvt_spec;
#if XIWS == XIWS_WIN
long old_hook;
#endif
#if XIWS == XIWS_MAC
strncpy( xvt_spec.type, spec->type, sizeof( xvt_spec.type ) - 1 );
strncpy( xvt_spec.name, spec->file_name, SZ_FNAME );
xvt_spec.name[SZ_FNAME] = '\0';
#else
if ( type == XinOpenFileDialog )
{
char *dot_ptr = strchr( spec->file_name, '.' );
if ( dot_ptr != NULL )
strcpy( xvt_spec.type, dot_ptr + 1 );
else {
if (spec->type != NULL)
strcpy( xvt_spec.type, spec->type );
else
xvt_spec.type[0] = '\0';
}
}
else
{
strncpy( xvt_spec.type, spec->type, sizeof( xvt_spec.type ) - 1 );
strncpy( xvt_spec.name, spec->file_name, SZ_FNAME );
xvt_spec.name[SZ_FNAME] = '\0';
}
#endif
xvt_fsys_convert_str_to_dir( ( char * ) spec->directory, &xvt_spec.dir );
#if XIWS == XIWS_WIN
old_hook = xvt_vobj_get_attr( NULL_WIN, ATTR_WIN_OPENFILENAME_HOOK );
xvt_vobj_set_attr( NULL_WIN, ATTR_WIN_OPENFILENAME_HOOK,
( long ) open_file_hook );
#endif
if ( type == XinOpenFileDialog )
result = xvt_dm_post_file_open( &xvt_spec, message );
else
result = xvt_dm_post_file_save( &xvt_spec, message );
#if XIWS == XIWS_WIN
xvt_vobj_set_attr( NULL_WIN, ATTR_WIN_OPENFILENAME_HOOK, old_hook );
#endif
switch ( result )
{
case FL_OK:
xvt_fsys_convert_dir_to_str( &xvt_spec.dir, ( char * ) spec->directory,
sizeof( XinDirectory ) );
strncpy( spec->file_name, xvt_spec.name, XI_FILE_MAX );
spec->file_name[XI_FILE_MAX] = '\0';
return XinFileGood;
case FL_CANCEL:
return XinFileCancel;
case FL_BAD:
return XinFileBad;
}
return XinFileBad;
/*START*/
}
/*
this function puts up the standard font selection dialog box. upon selection of
a font by the user, the argument 'font' is set to the specified font.
if the user canceled, then this function returns FALSE. if the user specified
a font, then this function returns TRUE.
*/
BOOLEAN
XinDialogFont( XinFont * font )
{
/*END*/
if ( !xvt_dm_post_font_sel( NULL_WIN, font->xvt_fntid, NULL, 0L ) )
return FALSE;
font->from_xvt_font = TRUE;
XinFontNativeConvert( font );
return TRUE;
/*START*/
}
/*
puts up a modal dialog box that displays a note with a single "OK" button.
the message is specified by a format and a variable number of arguments,
similar to the function printf
*/
void
XinDialogNote( char *format,... )
{
/*END*/
va_list argptr;
XinInitBuffer( );
va_start( argptr, format );
vsprintf( xin_buffer, format, argptr );
va_end( argptr );
xin_buffer[200] = '\0';
xvt_dm_post_note( xin_buffer );
/*START*/
}
/*
this function puts up a printer setup dialog box. this allows the user to
select a printer and setup options for that printer.
this function should put up the standard printer setup dialog box in MFC.
this function fills in an XinPrintRecord, which is an abstraction implemented
locally in this module. see the abstraction discussion on XinPrintRecord above.
*/
BOOLEAN
XinDialogPrinterSetup( XinPrintRecord * rec )
{
/*END*/
return xvt_dm_post_page_setup( ( PRINT_RCD * ) rec );
/*START*/
}
/*
this function puts up a dialog box with a message, and gets a string response
from the user. the argument 'message' contains the prompt for the user.
the argument 'response' points to a character buffer, which is filled in
with the user's response. the argument 'response_len' contains the length
of the character array pointed to by 'response'. this function should never
copy more characters into 'response' than 'response_len' to avoid overwriting
memory and corrupting the heap.
this function returns the value in 'response' if the user typed a string and
pressed OK. if the user pressed cancel, then this function returns NULL.
*/
char *
XinDialogStringPrompt( char *message, char *response, int response_len )
{
/*END*/
return xvt_dm_post_string_prompt( message, response, response_len );
/*START*/
}
/*
each XinWindow can have an arbitrary long integer associated with it for
storing of state data with the window. typically, the module that uses
Xin will allocate memory for data, fill in the data structure, and pass
the allocated pointer to XinWindowAppDataSet, casting the pointer to a
long in the call.
this function simply sets the app data field in the XinWindow abstraction
to the argument 'AppData'.
*/
void
XinWindowAppDataSet( XinWindow Win, long AppData )
{
/*END*/
xvt_vobj_set_data( ( WINDOW ) Win, AppData );
/*START*/
}
/*
this function returns a value previously passed to XinWindowAppDataSet for
the specified window.
*/
long
XinWindowAppDataGet( XinWindow Win )
{
/*END*/
return xvt_vobj_get_data( ( WINDOW ) Win );
/*START*/
}
void
XinWindowArcDraw( XinWindow Win, XinRect* rctp, XinPoint* start, XinPoint* stop )
{
RCT r;
r.left = rctp->left;
r.top = rctp->top;
r.right = rctp->right;
r.bottom = rctp->bottom;
xvt_dwin_draw_arc( (WINDOW) Win, &r, start->h, start->v, stop->h, stop->v );
}
/*
this function draws the bitmap specified in the argument 'bitmap' into the
window specified by 'win'.
'source' specifies a mathmatical rectangle which may be a subsection of the
specified bitmap. if 'source' is the same size as the bitmap, then the entire
bitmap is drawn.
'dest' specifies the destination rectangle in the window.
if 'source' and 'dest' are not the same size, then this function scales the
bitmap to fit.
*/
void
XinWindowBitmapDraw( XinWindow win, XinBitmap * bitmap, XinRect * dest, XinRect * source )
{
/*END*/
xvt_dwin_draw_image( ( WINDOW ) win, bitmap->image, ( RCT * ) dest, ( RCT * ) source );
/*START*/
}
/*END*/
static PAT_STYLE
BrushPatternToPAT( XinBrushPattern Pattern )
{
switch ( Pattern )
{
case XinBrushSolid:
return PAT_SOLID;
case XinBrushHollow:
return PAT_HOLLOW;
default:
break;
}
return PAT_SOLID;
}
static PAT_STYLE
PenPatternToPAT( XinPenPattern Pattern )
{
switch ( Pattern )
{
case XinPenSolid:
return PAT_SOLID;
case XinPenHollow:
return PAT_HOLLOW;
case XinPenDashed:
return PAT_RUBBER;
default:
break;
}
return PAT_SOLID;
}
static XinBrushPattern
PATToBrushPattern( PAT_STYLE pat )
{
switch ( pat )
{
case PAT_SOLID:
return XinBrushSolid;
case PAT_HOLLOW:
return XinBrushHollow;
default:
break;
}
return XinBrushSolid;
}
static XinPenPattern
PATToPenPattern( PAT_STYLE pat )
{
switch ( pat )
{
case PAT_SOLID:
return XinPenSolid;
case PAT_HOLLOW:
return XinPenHollow;
case PAT_RUBBER:
return XinPenDashed;
default:
break;
}
return XinPenSolid;
}
/*START*/
/*
this function sets the brush for subsequent rectangle drawing operations.
see the drawing discussion above for details on drawing.
*/
void
XinWindowBrushSet( XinWindow win, XinBrush * brush )
{
/*END*/
CBRUSH cbrush;
#ifdef NEED_PATCH
/* Hack for OS2 */
/* The calls to XinWindowDrawToolsNormalGet and DrawToolsSet
cause a update problem in the link list edit window */
#if XIWS == XIWS_PM
if ( brush->fore_color == XI_COLOR_LTGRAY )
{
XinBrush hollow_cbrush;
XinRect rct;
/* Bad bug with XVT/PM, needs this before can draw COLOR_LTGRAY */
XinWindowDrawToolsNormalGet( &t );
win_set_draw_ctools( win, &t );
hollow_cbrush.color = XI_COLOR_WHITE;
hollow_cbrush.pat = XinPatternHollow;
win_set_cbrush( win, &hollow_cbrush );
rct.top = 0;
rct.left = 0;
rct.bottom = 0;
rct.right = 0;
xi_draw_rect( win, &rct );
}
#endif
#if XIWS == XIWS_XM || XIWS == XIWS_WXGTK
if ( brush->fore_color == XI_COLOR_LTGRAY )
{
/* X GRAY SCALE HACK */
XinWindowBackColorSet( win, XI_COLOR_WHITE );
{
XinDrawTools ct;
XinWindowDrawToolsGet( win, &ct );
ct.opaque_text = FALSE;
XinWindowDrawToolsSet( win, &ct );
xi_draw_text( win, 0, 0, " ", -1 );
}
}
#endif
#endif
cbrush.color = brush->fore_color;
cbrush.pat = BrushPatternToPAT( brush->pattern );
#if XIWS == XIWS_WM
xi_fix_color( &cbrush.color );
#endif
xvt_dwin_set_cbrush( ( WINDOW ) win, &cbrush );
/*START*/
}
/*END*/
static BOOLEAN caret_is_on = FALSE;
/*START*/
/*
the caret is the blinking vertical line that indicates the current insertion
point when editing text.
this function turns off the caret in the specified window.
*/
void
XinWindowCaretOff( XinWindow win )
{
/*END*/
#if XIWS == XIWS_WIN
PNT p;
if ( !caret_is_on )
return;
p.h = -100;
p.v = -100;
xvt_win_set_caret_pos( ( WINDOW ) win, p );
#endif
caret_is_on = FALSE;
xvt_win_set_caret_visible( ( WINDOW ) win, FALSE );
/*START*/
}
/*
this function turns on a caret in the specified window 'win'
'x' and 'y' specify the position of the bottom of the caret.
'height' specifies the height of the caret.
'assumed_back_color' is not used for the MFC implementation.
'clip_rct' specifies a clipping rectangle for the caret. If the caret is
totally outside of the clipping rectangle, then the caret is not turned on.
if the caret is completely inside of the clipping rectangle, then the caret
is turned on normally. if the caret is partially outside of the clipping
rectangle, then the actual height is reduced, and position of the caret is
modified so that it appears as if the caret is clipped by the clipping rectangle.
*/
void
XinWindowCaretOn( XinWindow win, int x, int y, int height, XinColor assumed_back_color,
XinRect * clip_rct )
{
/*END*/
PNT p;
int dist_from_top;
NOREF( assumed_back_color );
if ( caret_is_on )
return;
caret_is_on = TRUE;
p.h = x;
p.v = y;
/* If the caret base is outsde the bottom of the clip rectangle - set the
* caret base to the clip bottom and adjust the caret height */
if ( clip_rct )
{
if ( p.v > clip_rct->bottom )
{
int adjust = p.v - clip_rct->bottom;
height = height - adjust;
p.v = clip_rct->bottom;
}
/* If the caret height is taller than the clip rectangle adjust it */
dist_from_top = p.v - clip_rct->top;
if ( height > dist_from_top )
height = dist_from_top;
}
/* The calculations above could result in a height of 0 or less if that is
* the case there is no caret */
if ( height > 0 )
{
#if 0
{ /* This patches a bug in the caret position in
* XVT/WIN */
int leading,
ascent,
descent;
xvt_dwin_get_font_metrics( ( WINDOW ) win, &leading, &ascent, &descent );
p.v -= height - ( leading + ascent + descent );
}
#endif
xvt_win_set_caret_size( ( WINDOW ) win, XIN_CARET_WIDTH, height );
xvt_win_set_caret_pos( ( WINDOW ) win, p );
xvt_win_set_caret_visible( ( WINDOW ) win, TRUE );
}
/*START*/
}
/*END*/
/*
non-xvt versions do not need to support this function
*/
void
XinWindowCheckBox( XinWindow Win, BOOLEAN Check )
{
/*
#if XIWS != XIWS_XM
*/
xvt_ctl_set_checked( ( WINDOW ) Win, Check );
/*
#endif
*/
}
/*
non-xvt versions do not need to support this function
*/
void
XinWindowCheckRadioButton( XinWindow Win, XinWindow * Wins, int NbrWindows )
{
xvt_ctl_check_radio_button( ( WINDOW ) Win, ( WINDOW * ) Wins, NbrWindows );
}
/*START*/
/*
this function gets the current clipping rectangle for the specified window.
the caller of this function passes in a pointer to a rectangle for the argument
'rctp'. this rectangle is filled in with the clipping region.
this function always returns TRUE.
see the discussion on drawing for further details.
*/
BOOLEAN
XinWindowClipGet( XinWindow win, XinRect * rctp )
{
/*END*/
( XinRect * ) xvt_dwin_get_clip( ( WINDOW ) win, ( RCT * ) rctp );
/*** TODO: if rctp is very large, return FALSE ***/
return TRUE;
/*START*/
}
/*
this function sets the clipping rectangle for the specified window.
'rctp' points to the desired mathmatical clipping rectangle.
*/
void
XinWindowClipSet( XinWindow win, XinRect * rctp )
{
/*END*/
xvt_dwin_set_clip( ( WINDOW ) win, ( RCT * ) rctp );
/*START*/
}
/*
this function sets the background color to use when drawing text in
opaque mode.
see the drawing discussion above for additional details on opaque drawing
of text.
*/
void
XinWindowColorTextBackSet( XinWindow win, XinColor color )
{
/*END*/
#if XIWS == XIWS_WM
xi_fix_color( &color );
#endif
xvt_dwin_set_back_color( ( WINDOW ) win, color );
/*START*/
}
/*
this function sets the foreground color to use when drawing text in
both opaque and non-opaque mode.
see the drawing discussion above for details on drawing text.
*/
void
XinWindowColorTextForeSet( XinWindow win, XinColor color )
{
/*END*/
xvt_dwin_set_fore_color( ( WINDOW ) win, color );
/*START*/
}
/*END*/
static XinScrollBarAction
ConvertWhat( SCROLL_CONTROL scroll_control )
{
switch ( scroll_control )
{
case SC_LINE_UP:
return XinScrollBarActionLineUp;
case SC_LINE_DOWN:
return XinScrollBarActionLineDown;
case SC_PAGE_UP:
return XinScrollBarActionPageUp;
case SC_PAGE_DOWN:
return XinScrollBarActionPageDown;
case SC_THUMB:
return XinScrollBarActionThumb;
case SC_THUMBTRACK:
return XinScrollBarActionThumbTrack;
default:
break;
}
return XinScrollBarActionLineUp;
}
XinFont *
XinFontXvtConvert( void *font_id )
{
XinFont *font = XinMemoryZeroAlloc( sizeof( XinFont ) );
font->xvt_fntid = xvt_font_create( );
xvt_font_copy( font->xvt_fntid, ( XVT_FNTID ) font_id,
( unsigned long ) XVT_FA_ALL );
font->from_xvt_font = TRUE;
return font;
}
void *
XinFontXvtConvertBack( XinFont * font )
{
return font->xvt_fntid;
}
void
XinFontXvtDestroy( void *font_id )
{
xvt_font_destroy( ( XVT_FNTID ) font_id );
}
#define FONT_ATTR_SIZE 256 /* family or native_desc size */
/*
This function fills out a font based on its native fontid, perhaps one from a font dialog.
Afterwards, the font is guaranteed to respond correctly to family, size, bold, and italic
inquiries, except that family may be XinFontFamilyOther.
*/
static int xin_stricmp( const char* s1, const char* s2 )
{
while (*s1 && *s2 && toupper(*s1) == toupper(*s2))
{
s1++;
s2++;
}
return toupper(*s2) - toupper(*s1);
}
static char *xin_family_name_times = NULL;
static char *xin_family_name_fixed = NULL;
static char *xin_family_name_helvetica = NULL;
static char *xin_family_name_system = NULL;
static BOOLEAN xin_family_names_initialized = FALSE;
void
XinFontNativeConvert( XinFont * font )
{
if (font->from_xvt_font)
{
char buf1[FONT_ATTR_SIZE];
XinFontFamily family;
unsigned long attrib;
if (!xin_family_names_initialized)
{ /* We need to know what XVT is really mapping the fonts to. */
char buf[100];
XVT_FNTID font_id = xvt_font_create();
WINDOW font_win;
XinWindowDef Def;
XinRect rect = {-1000, -1000, -900, -900};
MEMCLEAR( Def );
Def.type = XinWindowTypeDocument;
Def.border_style = XinBorderFixed;
Def.p_rect = &rect;
Def.title = "";
font_win = (WINDOW)XinWindowCreate( &Def );
xvt_font_map( font_id, font_win );
if (xvt_font_get_family_mapped( font_id, buf, 99 ))
{
xin_family_name_system = (char*)XinMemoryAlloc( strlen( buf ) + 1 );
strcpy( xin_family_name_system, buf );
}
xvt_font_set_family( font_id, "times" );
xvt_font_map( font_id, font_win );
if (xvt_font_get_family_mapped( font_id, buf, 99 ))
{
xin_family_name_times = (char*)XinMemoryAlloc( strlen( buf ) + 1 );
strcpy( xin_family_name_times, buf );
}
xvt_font_set_family( font_id, "fixed" );
xvt_font_map( font_id, font_win );
if (xvt_font_get_family_mapped( font_id, buf, 99 ))
{
xin_family_name_fixed = (char*)XinMemoryAlloc( strlen( buf ) + 1 );
strcpy( xin_family_name_fixed, buf );
}
xvt_font_set_family( font_id, "helvetica" );
xvt_font_map( font_id, font_win );
if (xvt_font_get_family_mapped( font_id, buf, 99 ))
{
xin_family_name_helvetica = (char*)XinMemoryAlloc( strlen( buf ) + 1 );
strcpy( xin_family_name_helvetica, buf );
}
xvt_font_destroy( font_id );
XinWindowDestroy( (XinWindow)font_win );
xin_family_names_initialized = TRUE;
}
if ( !xvt_font_get_family( font->xvt_fntid, buf1, FONT_ATTR_SIZE ) )
return;
if (xin_stricmp( buf1, xin_family_name_system ) == 0)
family = XinFontFamilySystem;
else if (xin_stricmp( buf1, xin_family_name_fixed ) == 0)
family = XinFontFamilyFixed;
else if (xin_stricmp( buf1, xin_family_name_times ) == 0)
family = XinFontFamilyTimes;
else if (xin_stricmp( buf1, xin_family_name_helvetica) == 0)
family = XinFontFamilyHelvetica;
else
family = XinFontFamilyOther;
font->family = family;
attrib = xvt_font_get_style( font->xvt_fntid );
font->italic = (attrib & XVT_FS_ITALIC ? TRUE : FALSE);
font->bold = (attrib & XVT_FS_BOLD ? TRUE : FALSE);
font->size = (int)xvt_font_get_size( font->xvt_fntid );
font->from_xvt_font = FALSE;
}
}
static BOOLEAN
ConvertEvent( EVENT * ep, XinEvent * xiep )
{
BOOLEAN retval = TRUE;
switch ( ep->type )
{
case E_CREATE:
xiep->type = XinEventCreate;
break;
case E_DESTROY:
xiep->type = XinEventDestroy;
break;
case E_FOCUS:
xiep->type = XinEventFocus;
xiep->v.focus.active = ep->v.active;
break;
case E_SIZE:
xiep->type = XinEventResize;
xiep->v.resize.width = ep->v.size.width;
xiep->v.resize.height = ep->v.size.height;
break;
case E_UPDATE:
xiep->type = XinEventPaint;
xiep->v.paint.rect = *( XinRect * ) & ep->v.update.rct;
break;
case E_CLOSE:
xiep->type = XinEventCloseButton;
break;
case E_MOUSE_DOWN:
xiep->type = XinEventMouseDown;
xiep->v.mouse.where.v = ep->v.mouse.where.v;
xiep->v.mouse.where.h = ep->v.mouse.where.h;
xiep->v.mouse.shift = ep->v.mouse.shift;
xiep->v.mouse.control = ep->v.mouse.control;
xiep->v.mouse.button = ep->v.mouse.button;
break;
case E_MOUSE_UP:
xiep->type = XinEventMouseUp;
xiep->v.mouse.where.v = ep->v.mouse.where.v;
xiep->v.mouse.where.h = ep->v.mouse.where.h;
xiep->v.mouse.shift = ep->v.mouse.shift;
xiep->v.mouse.control = ep->v.mouse.control;
xiep->v.mouse.button = ep->v.mouse.button;
#ifndef NO_PRIMARY_SELECTION
#if XIWS == XIWS_XM
if ( xiep->v.mouse.button == 2 )
get_primary_selection( itf, win );
#endif
#endif
break;
case E_MOUSE_MOVE:
xiep->type = XinEventMouseMove;
xiep->v.mouse.where.v = ep->v.mouse.where.v;
xiep->v.mouse.where.h = ep->v.mouse.where.h;
xiep->v.mouse.shift = ep->v.mouse.shift;
xiep->v.mouse.control = ep->v.mouse.control;
xiep->v.mouse.button = ep->v.mouse.button;
break;
case E_MOUSE_DBL:
xiep->type = XinEventMouseDouble;
xiep->v.mouse.where.v = ep->v.mouse.where.v;
xiep->v.mouse.where.h = ep->v.mouse.where.h;
xiep->v.mouse.shift = ep->v.mouse.shift;
xiep->v.mouse.control = ep->v.mouse.control;
xiep->v.mouse.button = ep->v.mouse.button;
break;
case E_CHAR:
xiep->type = XinEventCharacter;
xiep->v.character.ch = ep->v.chr.ch;
#if XIWS == XIWS_WM
/* TODO ep->v.chr.shift and ep->v.chr.control are not set properly for
* XVT/CH */
xiep->v.character.shift = FALSE;
xiep->v.character.control = FALSE;
#else
xiep->v.character.shift = ep->v.chr.shift;
xiep->v.character.control = ep->v.chr.control;
#endif
#if XIWS == XIWS_WIN
if ( xiep->v.character.ch == '\t' && xiep->v.character.shift )
/* ignore bogus shift-tab from XVT */
retval = FALSE;
#endif
break;
case E_HSCROLL:
xiep->type = XinEventHScroll;
xiep->v.scroll.action = ConvertWhat( ep->v.scroll.what );
xiep->v.scroll.position = ep->v.scroll.pos;
break;
case E_VSCROLL:
xiep->type = XinEventVScroll;
xiep->v.scroll.action = ConvertWhat( ep->v.scroll.what );
xiep->v.scroll.position = ep->v.scroll.pos;
break;
case E_COMMAND:
xiep->type = XinEventMenuCommand;
xiep->v.menu_command.tag = ep->v.cmd.tag;
xiep->v.menu_command.shift = ep->v.cmd.shift;
xiep->v.menu_command.control = ep->v.cmd.control;
break;
case E_FONT:
xiep->type = XinEventFont;
xiep->v.font.font = XinFontXvtConvert( ep->v.font.font_id );
XinFontNativeConvert( xiep->v.font.font );
break;
case E_CONTROL:
xiep->type = XinEventControl;
xiep->v.control.control_id = ep->v.ctl.id;
switch ( ep->v.ctl.ci.type )
{
/* non-xvt versions do not need to support buttons, radio buttons,
* and check boxes */
case WC_PUSHBUTTON:
xiep->v.control.ctrl_info.type = XinWindowTypeButton;
break;
case WC_RADIOBUTTON:
xiep->v.control.ctrl_info.type = XinWindowTypeRadioButton;
break;
case WC_CHECKBOX:
xiep->v.control.ctrl_info.type = XinWindowTypeCheckBox;
break;
case WC_HSCROLL:
xiep->v.control.ctrl_info.win = ( XinWindow ) ep->v.ctl.ci.win;
xiep->v.control.ctrl_info.type = XinWindowTypeHorizontalScrollBar;
xiep->v.control.ctrl_info.v.scroll.action = ConvertWhat( ep->v.ctl.ci.v.scroll.what );
xiep->v.control.ctrl_info.v.scroll.position = ep->v.ctl.ci.v.scroll.pos;
break;
case WC_VSCROLL:
xiep->v.control.ctrl_info.win = ( XinWindow ) ep->v.ctl.ci.win;
xiep->v.control.ctrl_info.type = XinWindowTypeVerticalScrollBar;
xiep->v.control.ctrl_info.v.scroll.action = ConvertWhat( ep->v.ctl.ci.v.scroll.what );
xiep->v.control.ctrl_info.v.scroll.position = ep->v.ctl.ci.v.scroll.pos;
break;
default:
break;
}
break;
case E_TIMER:
xiep->type = XinEventTimer;
xiep->v.timer.id = ep->v.timer.id;
break;
case E_QUIT:
xiep->type = XinEventQuit;
xiep->v.quit.query = ep->v.query;
break;
case E_HELP:
xiep->type = XinEventHelp;
xiep->v.help.obj = ( XinWindow ) ep->v.help.obj;
xiep->v.help.tag = ep->v.help.tag;
xiep->v.help.topic_id = ( long ) ep->v.help.tid;
break;
case E_USER:
xiep->type = XinEventUser;
xiep->v.user.id = ep->v.user.id;
xiep->v.user.ptr = ep->v.user.ptr;
break;
default:
retval = FALSE;
break;
}
return retval;
}
long
XinXvtEventHandler( WINDOW win, EVENT * ep )
{
WindowInfo *ehlt;
EVENT fake_event;
assert4( ep->type != E_CREATE || win != TASK_WIN || xin_teh != NULL, "",
20095, "XinAppSystemSetupInit was not provided." );
if ( ep->type == E_CREATE && xin_teh )
{
XinXvtWindowRegister( ( XinWindow ) win, xin_teh );
XinWindowCreateFinish( ( XinWindow ) win );
xin_teh = NULL;
}
/* Modal behavior */
#if XIWS == XIWS_MAC || XIWS == XIWS_XM || XIWS == XIWS_PM || XIWS == XIWS_WM || XIWS == XIWS_WXGTK
#if XIWS == XIWS_MAC
if ( xin_modal_win == ( XinWindow ) win
&& ep->type == E_FOCUS && !ep->v.active )
XinWindowFrontSet( xin_modal_win );
#else
if ( xin_modal_win != XI_NULL_WINDOW
&& ep->type == E_FOCUS
&& ep->v.active
&& xin_modal_win != ( XinWindow ) win )
XinWindowFrontSet( xin_modal_win );
#endif
if ( xin_modal_win != XI_NULL_WINDOW
&& ( XinWindow ) win != xin_modal_win
&& XinWindowParentGet( ( XinWindow ) win ) != xin_modal_win && ep->type != E_UPDATE
&& ep->type != E_TIMER )
return 0L;
#endif
/* Autoclose behavior */
if ( ( ( ep->type == E_FOCUS && !ep->v.active ) ||
( ep->type == E_CHAR && ep->v.chr.ch == '\033' ) ) &&
( WINDOW ) xin_autoclose_win == win )
{
MEMCLEAR( fake_event );
fake_event.type = E_CLOSE;
ep = &fake_event;
}
/* Font event */
if ( ep->type == E_COMMAND && ep->v.cmd.tag == XI_MENU_FONT_SELECT )
{
XVT_FNTID font_id;
font_id = xvt_dwin_get_font( win );
xvt_dm_post_font_sel( win, font_id, NULL, 0L );
xvt_font_destroy( font_id );
return 0L;
}
/* Help event - the user pressed F1 */
if (ep->type == E_HELP)
{ /* XVT sends the event to the task window. We want to redirect it to the focus window. */
win = (WINDOW)XinWindowFocusGet();
}
ehlt = find_window_info( win );
if ( ehlt != NULL )
{
XinEvent event;
MEMCLEAR( event );
if ( ConvertEvent( ep, &event ) )
{
EVENT* old_cur_event = cur_xvt_event;
cur_xvt_event = ep;
( *ehlt->event_handler ) ( ( XinWindow ) win, &event );
cur_xvt_event = old_cur_event;
if ( event.type == XinEventFont )
XinFontDestroy( event.v.font.font );
}
if ( ep->type == E_DESTROY )
deregister_window( win );
}
return 0L;
}
/*START*/
/*
this function creates a window or a scroll bar using the information in 'Def'.
*/
XinWindow
XinWindowCreate( XinWindowDef * Def )
{
/*END*/
WINDOW parent;
long flags;
WIN_TYPE win_type;
XinWindow win;
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
int old_icon_rid;
#endif
switch ( Def->type )
{
case XinWindowTypeDocument:
if ( Def->parent == XI_NULL_WINDOW )
parent = TASK_WIN;
else
parent = ( WINDOW ) Def->parent;
flags = ( Def->close_button ? WSF_CLOSE : 0 ) |
( Def->horizontal_scroll_bar ? WSF_HSCROLL : 0 ) |
( Def->vertical_scroll_bar ? WSF_VSCROLL : 0 ) |
( Def->visible ? 0 : WSF_INVISIBLE ) |
( Def->enabled ? 0 : WSF_DISABLED ) |
( Def->maximized ? WSF_MAXIMIZED : 0 ) |
( Def->iconizable ? WSF_ICONIZABLE : 0 ) |
( Def->iconized ? WSF_ICONIZED : 0 );
#if XVT_CHECK_VERSION(4, 50, 0)
if ( Def->mode == XinModalWait )
{
win_type = W_MODAL;
if ( Def->close_button || Def->menu != NULL || Def->menu_bar_rid != 0 )
XinError( 20301, XinSeverityFatal, 0L );
}
else
#endif
switch ( Def->border_style )
{
case XinBorderSizable:
win_type = W_DOC;
flags |= WSF_SIZE;
break;
case XinBorderSingle:
win_type = W_PLAIN;
flags &= ~WSF_CLOSE;
break;
case XinBorderDouble:
win_type = W_DBL;
flags &= ~WSF_CLOSE;
break;
case XinBorderNone:
win_type = W_NO_BORDER;
flags &= ~WSF_CLOSE;
break;
case XinBorderFixed:
win_type = W_DOC;
break;
default:
win_type = W_DOC;
flags |= WSF_SIZE;
break;
}
if ( Def->menu == NULL && Def->menu_bar_rid == 0 )
flags |= WSF_NO_MENUBAR;
switch ( Def->mode )
{
case XinModalWait:
/* This is too clever. If we are in DSC45, then XinModalWait falls through
to the XinModalReturn case. */
#if XVT_CHECK_VERSION(4, 50, 0)
return XI_NULL_WINDOW;
#endif
xin_finish_create_def = Def;
/* don't break! We need to do the XinModalReturn stuff as well. */
case XinModalReturn:
if ( parent == TASK_WIN )
parent = SCREEN_WIN;
else
parent = TASK_WIN;
break;
default:
break;
}
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
if ( Def->iconizable && Def->icon_rid != 0 )
{
old_icon_rid = ( int ) xvt_vobj_get_attr( NULL_WIN,
ATTR_WIN_PM_CLASS_ICON );
xvt_vobj_set_attr( NULL_WIN, ATTR_WIN_PM_CLASS_ICON, Def->icon_rid );
}
else
old_icon_rid = 0;
#endif
if ( Def->eh )
xin_teh = Def->eh;
xin_finish_create_menu = Def->menu;
#if XIWS == XIWS_WIN
if (parent == SCREEN_WIN)
xvt_vobj_set_attr( 0, ATTR_WIN_POPUP_DETACHED, TRUE );
#endif
win = ( XinWindow ) xvt_win_create( win_type, ( RCT * ) ( Def->p_rect ),
Def->title, Def->menu_bar_rid == 0 ? NULL_MENU_RID
: Def->menu_bar_rid, parent, flags, EM_ALL,
( EVENT_HANDLER ) XinXvtEventHandler, Def->app_data );
#if XIWS != XIWS_XM && XIWS != XIWS_WXGTK
#if XVT_CHECK_VERSION(4, 50, 0)
if ( Def->mode != XinModalWait && win != XI_NULL_WINDOW &&
xvt_vobj_is_valid( ( WINDOW ) win ) )
XinWindowFocusSet( win );
#endif
#endif
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
if ( old_icon_rid != 0 )
xvt_vobj_set_attr( NULL_WIN, ATTR_WIN_PM_CLASS_ICON, old_icon_rid );
#endif
assert4( win, "", 20090, "create_window returned NULL" );
#if XVT_CHECK_VERSION(4, 50, 0)
if ( xvt_vobj_is_valid( ( WINDOW ) win ) )
{ /* We check because the window may have closed during its initial actions. */
#endif
switch ( Def->mode )
{
case XinModalReturn:
if ( Def->parent != XinWindowTaskGet( )
&& Def->parent != XinWindowScreenGet( ) )
{ /* Modal to parent only */
WindowInfo *info = find_window_info( ( WINDOW ) win );
assert4( info != NULL, "", 20091, "Window information corrupt" );
info->prev_modal = Def->parent;
XinWindowEnable( Def->parent, FALSE );
}
else if ( xin_modal_win != XI_NULL_WINDOW )
{ /* Nested modal */
WindowInfo *info = find_window_info( ( WINDOW ) win );
assert4( info != NULL, "", 20092, "Window information corrupt" );
info->prev_modal = xin_modal_win;
#if XIWS == XIWS_WIN || XIWS == XIWS_PM || XIWS == XIWS_WM || XIWS == XIWS_MAC
XinWindowEnable( xin_modal_win, FALSE );
#if XIWS == XIWS_MAC
XinWindowFrontSet( win );
#endif
#endif
xin_modal_win = win;
}
else
{
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
XinWindowEnable( XinWindowTaskGet( ), FALSE );
#endif
xin_modal_win = win;
#if XIWS == XIWS_WM || XIWS == XIWS_MAC
{
SLIST win_list = xvt_scr_list_wins( );
SLIST_ELT elt;
for ( elt = xvt_slist_get_first( win_list ); elt != NULL;
elt = xvt_slist_get_next( win_list, elt ) )
if ( ( XinWindow ) * xvt_slist_get_data( elt ) != xin_modal_win )
XinWindowEnable( ( XinWindow ) * xvt_slist_get_data( elt ), FALSE );
xvt_slist_destroy( win_list );
}
#endif
}
break;
case XinModalAutoclose:
xin_autoclose_win = win;
break;
default:
break;
}
#if XVT_CHECK_VERSION(4, 50, 0)
}
#endif
return win;
case XinWindowTypeButton:
case XinWindowTypeRadioButton:
case XinWindowTypeCheckBox:
case XinWindowTypeHorizontalScrollBar:
case XinWindowTypeVerticalScrollBar:
{
WIN_DEF ctl_def;
#if XVT_CHECK_VERSION(4, 50, 0)
XVT_COLOR_COMPONENT colors[8];
#endif
MEMCLEAR( ctl_def );
switch ( Def->type )
{
case XinWindowTypeButton:
ctl_def.wtype = WC_PUSHBUTTON;
break;
case XinWindowTypeRadioButton:
ctl_def.wtype = WC_RADIOBUTTON;
break;
case XinWindowTypeCheckBox:
ctl_def.wtype = WC_CHECKBOX;
break;
case XinWindowTypeHorizontalScrollBar:
Def->title = "";
ctl_def.wtype = WC_HSCROLL;
break;
case XinWindowTypeVerticalScrollBar:
Def->title = "";
ctl_def.wtype = WC_VSCROLL;
break;
default:
break;
}
flags = ( Def->visible ? 0 : CTL_FLAG_INVISIBLE );
if ( !Def->enabled )
flags |= CTL_FLAG_DISABLED;
ctl_def.rct = *( RCT * ) Def->p_rect;
ctl_def.text = Def->title;
ctl_def.v.ctl.ctrl_id = Def->control_id;
ctl_def.v.ctl.flags = flags;
#if XVT_CHECK_VERSION(4, 50, 0)
if ( Def->back_color )
{
colors[0].type = XVT_COLOR_BLEND;
colors[0].color = Def->back_color;
colors[1].type = XVT_COLOR_NULL;
ctl_def.ctlcolors = colors;
}
if ( Def->font )
ctl_def.v.ctl.font_id = Def->font->xvt_fntid;
#endif
return ( XinWindow ) xvt_ctl_create_def( &ctl_def, ( WINDOW ) Def->parent, 0L );
}
default:
break;
}
return 0L;
/*START*/
}
/* This function is called when the create event for a window comes thru.
Other higher level stuff depends on this being done before any events
for the window are passed on. */
void
XinWindowCreateFinish( XinWindow win )
{
/*END*/
#if XIWS == XIWS_PM
{
HWND hwnd = ( HWND ) xvt_vobj_get_attr( ( WINDOW ) win, ATTR_NATIVE_WINDOW );
if ( hwnd && old_pm_proc == NULL )
old_pm_proc = WinSubclassWindow( hwnd, pm_proc );
}
#endif
if ( xin_finish_create_menu != NULL )
XinWindowMenuReplace( win, 0, xin_finish_create_menu );
xvt_vobj_set_attr( NULL_WIN, ATTR_SUPPRESS_UPDATE_CHECK, ( long ) TRUE );
if ( xin_finish_create_def != NULL )
{
XinWindowDef * Def = xin_finish_create_def;
if ( Def->parent != XinWindowTaskGet( )
&& Def->parent != XinWindowScreenGet( ) )
{ /* Modal to parent only */
WindowInfo *info = find_window_info( ( WINDOW ) win );
assert4( info != NULL, "", 20091, "Window information corrupt" );
info->prev_modal = Def->parent;
XinWindowEnable( Def->parent, FALSE );
}
else if ( xin_modal_win != XI_NULL_WINDOW )
{ /* Nested modal */
WindowInfo *info = find_window_info( ( WINDOW ) win );
assert4( info != NULL, "", 20092, "Window information corrupt" );
info->prev_modal = xin_modal_win;
#if XIWS == XIWS_WIN || XIWS == XIWS_PM || XIWS == XIWS_WM || XIWS == XIWS_MAC
XinWindowEnable( xin_modal_win, FALSE );
#if XIWS == XIWS_MAC
XinWindowFrontSet( win );
#endif
#endif
xin_modal_win = win;
}
else
{
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
XinWindowEnable( XinWindowTaskGet( ), FALSE );
#endif
xin_modal_win = win;
#if XIWS == XIWS_WM || XIWS == XIWS_MAC
{
SLIST win_list = xvt_scr_list_wins( );
SLIST_ELT elt;
for ( elt = xvt_slist_get_first( win_list ); elt != NULL;
elt = xvt_slist_get_next( win_list, elt ) )
if ( ( XinWindow ) * xvt_slist_get_data( elt ) != xin_modal_win )
XinWindowEnable( ( XinWindow ) * xvt_slist_get_data( elt ), FALSE );
xvt_slist_destroy( win_list );
}
#endif
}
xin_finish_create_def = NULL;
}
/*START*/
}
/*END*/
#if XIWS != XIWS_WM
static CURSOR
XinCursorToCURSOR( XinCursor Cursor )
{
switch ( Cursor )
{
case XI_CURSOR_ARROW:
return CURSOR_ARROW;
case XI_CURSOR_IBEAM:
return CURSOR_IBEAM;
case XI_CURSOR_CROSS:
return CURSOR_CROCE;
}
return ( CURSOR ) Cursor;
}
#endif
/*START*/
/*
this function sets the current cursor. the argument 'Cursor' can be:
XI_CURSOR_ARROW the ubiquitous arrow cursor
XI_CURSOR_IBEAM ibeam insertion point for edit controls
XI_CURSOR_CROSS a plus sign cursor (crosshairs)
XI_CURSOR_RESIZE horizontal resize
XI_CURSOR_HAND hand cursor (for moving columns in a list)
XI_CURSOR_VRESIZE vertical resize
when the cursor is set, it remains in that state until the cursor is changed
by another call to this function. an exception is when XinCursorWait is called.
this changes the cursor to the waiting cursor (usually an hourglass), indicating that
the application
is busy. as soon as the event handler that is currently being processed returns,
then the cursor changes back to the current cursor (i.e. whatever cursor was
set the last time that XinWindowCursorSet was called)
*/
void
XinWindowCursorSet( XinWindow win, XinCursor Cursor )
{
/*END*/
#if XIWS != XIWS_WM
xvt_win_set_cursor( ( WINDOW ) win, XinCursorToCURSOR( Cursor ) );
#else
NOREF( win );
NOREF( Cursor );
#endif
/*START*/
}
/*
this function destroys a previously created XinWindow. The XinWindow could either
be a top level window, or a scroll bar.
*/
void
XinWindowDestroy( XinWindow win )
{
/*END*/
WindowInfo *info = find_window_info( ( WINDOW ) win );
if ( win == xin_autoclose_win )
xin_autoclose_win = XI_NULL_WINDOW;
if ( app_terminating )
return;
if ( info != NULL )
{
if ( win == xin_modal_win )
{
xin_modal_win = info->prev_modal;
if ( xin_modal_win == XI_NULL_WINDOW )
{ /* Last modal window closed */
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
XinWindowEnable( XinWindowTaskGet( ), TRUE );
#elif XIWS == XIWS_WM || XIWS == XIWS_MAC
{
SLIST win_list = xvt_scr_list_wins( );
SLIST_ELT elt;
for ( elt = xvt_slist_get_first( win_list ); elt != NULL;
elt = xvt_slist_get_next( win_list, elt ) )
XinWindowEnable( ( XinWindow ) * xvt_slist_get_data( elt ), TRUE );
xvt_slist_destroy( win_list );
}
#endif
}
else
{ /* Top nested window closed */
#if XIWS == XIWS_WIN || XIWS == XIWS_PM || XIWS == XIWS_WM || XIWS == XIWS_MAC
XinWindowEnable( xin_modal_win, TRUE );
#if XIWS != XIWS_WIN
XinWindowFrontSet( xin_modal_win );
#endif
#endif
}
}
else if ( xin_modal_win != XI_NULL_WINDOW || info->prev_modal != XI_NULL_WINDOW )
{ /* Window is not top modal window */
WindowInfo *cur_info;
XinWindow cur_win = xin_modal_win;
if ( cur_win != XI_NULL_WINDOW )
{
do
{
cur_info = find_window_info( ( WINDOW ) cur_win );
assert4( cur_info != NULL, "", 20094, "Window information corrupt" );
cur_win = cur_info->prev_modal;
} while ( cur_win != XI_NULL_WINDOW && cur_win != win );
}
/* If cur_win is not null, then remove this window from the modal list.
* Otherwise, if there is a prev_modal link, the window is a parented
* modal. */
if ( cur_win != XI_NULL_WINDOW )
cur_info->prev_modal = info->prev_modal;
else if ( info->prev_modal != XI_NULL_WINDOW )
XinWindowEnable( info->prev_modal, TRUE );
}
}
xvt_vobj_destroy( ( WINDOW ) win );
/*START*/
}
/*END*/
static DRAW_MODE
DrawModeToMODE( XinDrawMode Mode )
{
switch ( Mode )
{
case XinDrawModeCopy:
return M_COPY;
case XinDrawModeXor:
return M_XOR;
}
return M_COPY;
}
static XinDrawMode
MODEToDrawMode( DRAW_MODE Mode )
{
switch ( Mode )
{
case M_COPY:
return XinDrawModeCopy;
case M_XOR:
return XinDrawModeXor;
default:
break;
}
return XinDrawModeCopy;
}
/*START*/
/*
this function sets the drawing mode to XinDrawModeCopy or XinDrawModeXor.
see the discussion above on drawing modes.
*/
void
XinWindowDrawModeSet( XinWindow win, XinDrawMode mode )
{
/*END*/
xvt_dwin_set_draw_mode( ( WINDOW ) win, DrawModeToMODE( mode ) );
/*START*/
}
/*
this function gets the currently set drawing tools. see the discussion above
on drawing tools for more information.
*/
XinDrawTools *
XinWindowDrawToolsGet( XinWindow win, XinDrawTools * DrawTools )
{
/*END*/
DRAW_CTOOLS ct;
xvt_dwin_get_draw_ctools( ( WINDOW ) win, &ct );
DrawTools->pen.fore_color = ct.pen.color;
DrawTools->pen.pattern = PATToPenPattern( ct.pen.pat );
DrawTools->pen.width = ct.pen.width;
DrawTools->brush.fore_color = ct.brush.color;
DrawTools->brush.pattern = PATToBrushPattern( ct.brush.pat );
DrawTools->draw_mode = MODEToDrawMode( ct.mode );
DrawTools->opaque_text = ct.opaque_text;
DrawTools->text_fore_color = ct.fore_color;
DrawTools->text_back_color = ct.back_color;
return DrawTools;
/*START*/
}
/*
this function gets the currently drawing mode. see the discussion above
on drawing mode for more information.
*/
XinDrawMode
XinWindowDrawModeGet( XinWindow win )
{
/*END*/
DRAW_CTOOLS ct;
XinDrawMode mode;
xvt_dwin_get_draw_ctools( ( WINDOW ) win, &ct );
mode = MODEToDrawMode( ct.mode );
return mode;
/*START*/
}
/*
this function gets an XinDrawTools that is a common configuration. the
common configuration consists of a black pen of width of 1 pixel, a solid
black brush, copy mode, foreground text color of black, background text color
of white, and non-opaque text.
the implementation below is complete.
*/
XinDrawTools *
XinWindowDrawToolsNormalGet( XinDrawTools * ct )
{
ct->pen.width = 1;
ct->pen.pattern = XinPenSolid;
ct->pen.fore_color = XI_COLOR_BLACK;
ct->brush.pattern = XinBrushSolid;
ct->brush.fore_color = XI_COLOR_BLACK;
ct->draw_mode = XinDrawModeCopy;
ct->text_fore_color = XI_COLOR_BLACK;
ct->text_back_color = XI_COLOR_WHITE;
ct->opaque_text = FALSE;
return ct;
}
/*
this function sets the current drawing tools. the drawing tools may have been
defined by the user of Xin. or they may have been gotten from a call to
XinWindowDrawToolsNormalGet, or they may have been gotten from a call to
XinWindowDrawToolsGet.
*/
void
XinWindowDrawToolsSet( XinWindow win, XinDrawTools * ct )
{
/*END*/
#if XIWS == XIWS_WM
{
DRAW_CTOOLS xct;
xct.pen.color = ct->pen.fore_color;
xi_fix_color( &xct.pen.color );
xct.pen.pat = ct->pen.pattern;
xct.pen.width = ct->pen.width;
xct.pen.style = P_SOLID;
xct.brush.color = ct->brush.fore_color;
xi_fix_color( &xct.brush.color );
xct.brush.pat = ct->brush.pattern;
xct.mode = DrawModeToMODE( ct->draw_mode );
xct.opaque_text = ct->opaque_text;
xct.fore_color = ct->text_fore_color;
xi_fix_color( &xct.fore_color );
xct.back_color = ct->text_back_color;
xi_fix_color( &xct.back_color );
xvt_dwin_set_draw_ctools( ( WINDOW ) win, &xct );
}
#else
{
DRAW_CTOOLS xct;
xct.pen.color = ct->pen.fore_color;
xct.pen.pat = PenPatternToPAT( ct->pen.pattern );
xct.pen.width = ct->pen.width;
switch ( ct->pen.pattern )
{
case XinPenSolid:
case XinPenHollow:
xct.pen.style = P_SOLID;
break;
case XinPenDashed:
xct.pen.style = P_DASH;
break;
default:
break;
}
xct.brush.color = ct->brush.fore_color;
xct.brush.pat = BrushPatternToPAT( ct->brush.pattern );
xct.mode = DrawModeToMODE( ct->draw_mode );
xct.opaque_text = ct->opaque_text;
xct.fore_color = ct->text_fore_color;
xct.back_color = ct->text_back_color;
xvt_dwin_set_draw_ctools( ( WINDOW ) win, &xct );
}
#endif
/*START*/
}
/*
this function draws an ellipse in the specified window, following the state of
clipping, pens, brushes, and copy mode. see the drawing discussion above for
more details.
*/
void
XinWindowEllipseDraw( XinWindow Win, XinRect * rctp )
{
/*END*/
RCT r;
r.left = rctp->left;
r.top = rctp->top;
r.right = rctp->right;
r.bottom = rctp->bottom;
xvt_dwin_draw_oval( ( WINDOW ) Win, &r );
/*START*/
}
/*
this function sets the enabled state of a window. see the discussion on
windows above for information on enabling and disabling windows.
*/
void
XinWindowEnable( XinWindow Win, BOOLEAN Enable )
{
/*END*/
xvt_vobj_set_enabled( ( WINDOW ) Win, Enable );
/*START*/
}
/*
this function causes an XinEventUser to be sent to the window. for the
MFC implementation, this function simply declares an XinEvent, clears the
event, sets the 'id' and 'ptr' fields in the XinEvent, and calls the
event handler for the window.
*/
void
XinWindowEventUserSend( XinWindow win, long id, void *ptr )
{
/*END*/
EVENT event;
event.type = E_USER;
event.v.user.id = id;
event.v.user.ptr = ptr;
XinXvtEventHandler( ( WINDOW ) win, &event );
/*START*/
}
/*
this function maps a font to a previously created XinWindow.
*/
void
XinWindowFontMap( XinWindow Win, XinFont * Font )
{
/*END*/
xvt_font_map( Font->xvt_fntid, ( WINDOW ) Win );
/*START*/
}
void
XinFontUnmap( XinFont * font )
{
xvt_font_unmap( font->xvt_fntid );
}
/*
this function returns the window with the current keyboard focus.
normally, this is the top window.
*/
XinWindow
XinWindowFocusGet( void )
{
/*END*/
return ( XinWindow ) xvt_scr_get_focus_topwin( );
/*START*/
}
/*
this function makes the specified window have the keyboard focus. it
doesn't change which window is on top.
*/
void
XinWindowFocusSet( XinWindow Win )
{
/*END*/
xvt_scr_set_focus_vobj( ( WINDOW ) Win );
/*START*/
}
/*
this function makes the specified window be the top window.
*/
void
XinWindowFrontSet( XinWindow Win )
{
/*END*/
xvt_vobj_raise( ( WINDOW ) Win );
/*START*/
}
void
XinWindowHotkeySet( XinWindow win, char ch )
{
NOREF( win );
NOREF( ch );
}
/*
this function draws the icon specifed by the resource id in 'IconRid' in the
specified window. the MFC implementation ignores the fore_color and back_color
because the icons have colors. fore_color and back_color are only used
on GUIs where icons might be black and white, such as X/Motif. 'x' and
'y' specify the position where the icon is drawn.
*/
void
XinWindowIconDraw( XinWindow Win, int x, int y, int IconRid,
XinColor fore_color, XinColor back_color )
{
/*END*/
#if XIWS == XIWS_WM
NOREF( Win );
NOREF( x );
NOREF( y );
NOREF( IconRid );
NOREF( fore_color );
NOREF( back_color );
#else
#if XIWS == XIWS_XM || XIWS == XIWS_MAC || XIWS == XIWS_WXGTK
if ( fore_color )
xvt_dwin_set_fore_color( ( WINDOW ) Win, fore_color );
if ( back_color )
xvt_dwin_set_back_color( ( WINDOW ) Win, back_color );
#else
NOREF( fore_color );
NOREF( back_color );
#endif
/*** Hack for PM only 08/96 XVT 4.02 */
#if XIWS == XIWS_PM
{
XinDrawTools new_ctools;
XinDrawTools save_ctools;
new_ctools.pen.width = 1;
new_ctools.pen.fore_color = XI_COLOR_BLACK;
new_ctools.pen.pattern = XinPenSolid;
new_ctools.brush.pattern = XinBrushSolid;
new_ctools.brush.fore_color = XI_COLOR_BLACK;
new_ctools.draw_mode = XinDrawModeCopy;
new_ctools.opaque_text = TRUE;
new_ctools.text_fore_color = fore_color;
new_ctools.text_back_color = back_color;
XinWindowDrawToolsGet( Win, &save_ctools );
XinWindowDrawToolsSet( Win, &new_ctools );
{
RCT r;
r.top = y;
r.left = x;
r.bottom = y + 1;
r.right = x + 1;
xvt_dwin_draw_rect( ( WINDOW ) Win, &r );
}
XinWindowDrawToolsSet( Win, &save_ctools );
}
#endif
xvt_dwin_draw_icon( ( WINDOW ) Win, x, y, IconRid );
#endif
/*START*/
}
/*END*/
static XinPoint save_move_to;
/*START*/
/*
this function draws a line from the point previously passed to XinWindowLineMoveTo
or the point in the last XinWindowLineDraw call
to the point passed to this function. this function obeys the state in the
draw tools (or the functions that set the individual components of drawing tools).
the state that affects line drawing is the draw mode and pen.
*/
void
XinWindowLineDraw( XinWindow Win, XinPoint * pnt )
{
/*END*/
PNT mtp,
mpnt;
mtp.v = save_move_to.v;
mtp.h = save_move_to.h;
mpnt.v = pnt->v;
mpnt.h = pnt->h;
if ( mtp.v != mpnt.v && mtp.h != mpnt.h )
{
if ( mtp.h > mpnt.h )
{
PNT tpnt;
tpnt = mtp;
mtp = mpnt;
mpnt = tpnt;
}
#if XIWS == XIWS_PM
if ( mtp.v > mpnt.v )
{
mtp.v--;
mpnt.h--;
}
else
{
mpnt.v--;
mpnt.h--;
}
#elif XIWS == XIWS_MAC
if ( mtp.v > mpnt.v )
{
mpnt.h--;
mpnt.v++;
}
else
{
mtp.v++;
mpnt.h--;
}
mtp.v--;
mpnt.v--;
#elif XIWS == XIWS_WIN
if ( mtp.v > mpnt.v )
{
mpnt.v--;
mtp.v--;
}
#elif XIWS == XIWS_XM || XIWS == XIWS_WXGTK
if ( mtp.v > mpnt.v )
{
mpnt.h--;
mtp.v--;
}
else
{
mpnt.h--;
mpnt.v--;
}
#endif
}
else
{
#if XIWS == XIWS_MAC || XIWS == XIWS_XM || XIWS == XIWS_PM || XIWS == XIWS_WXGTK
if ( mtp.v == mpnt.v )
--mpnt.h;
if ( mtp.h == mpnt.h )
--mpnt.v;
#endif
}
xvt_dwin_draw_set_pos( ( WINDOW ) Win, mtp );
xvt_dwin_draw_line( ( WINDOW ) Win, mpnt );
save_move_to = *pnt;
/*START*/
}
/*
the user of Xin calls this function just prior to calling XinWindowLineDraw,
to specify the starting point for drawing a line.
*/
void
XinWindowLineMoveTo( XinWindow Win, XinPoint * pnt )
{
/*END*/
NOREF( Win );
save_move_to = *pnt;
/*START*/
}
/*
if a menu item is checkable, then this function checks or un-checks the menu
item.
*/
void
XinWindowMenuItemCheck( XinWindow Win, XinMenuTag Tag, BOOLEAN check )
{
/*END*/
xvt_menu_set_item_checked( ( WINDOW ) Win, ( MENU_TAG ) Tag, check );
/*START*/
}
/*
this function enables or disables a menu item.
*/
void
XinWindowMenuItemEnable( XinWindow Win, XinMenuTag Tag, BOOLEAN Enable )
{
/*END*/
xvt_menu_set_item_enabled( ( WINDOW ) Win, ( MENU_TAG ) Tag, Enable );
/*START*/
}
/*
this function sets the checked font in the font selection dialog box to the
specified font. the next time that the font selection dialog is put up,
it will reflect the effects of the call to this function.
*/
void
XinWindowMenuFontSet( XinWindow win, XinFont * fontp )
{
/*END*/
xvt_menu_set_font_sel( ( WINDOW ) win, fontp->xvt_fntid );
/*START*/
}
/*END*/
static XinMenuItem *copy_menu_items( MENU_ITEM * items, int *p_nbr_children );
static char *
copy_xvt_menu_text( char *text, char mnemonic )
{
char *new_text;
char *from;
char *to;
int size = strlen( text ) + 2;
new_text = to = XinMemoryAlloc( size );
for ( from = text; *from != '\0'; )
{
if ( *from == mnemonic )
{
*to++ = '~';
mnemonic = '\0';
}
*to++ = *from++;
}
*to = '\0';
return new_text;
}
static void
copy_menu_item( XinMenuItem * new_item, MENU_ITEM * item )
{
new_item->tag = item->tag;
if ( item->text == NULL )
new_item->text = NULL;
else
new_item->text = copy_xvt_menu_text( item->text, ( char ) item->mkey );
new_item->enabled = item->enabled;
new_item->checked = item->checked;
new_item->checkable = item->checkable;
new_item->separator = item->separator;
if ( item->child == 0 )
{
new_item->nbr_children = 0;
new_item->children = NULL;
}
else
new_item->children = copy_menu_items( item->child,
&new_item->nbr_children );
}
static XinMenuItem *
copy_menu_items( MENU_ITEM * items, int *p_nbr_children )
{
MENU_ITEM *item;
XinMenuItem *new_items;
XinMenuItem *new_item;
int count;
count = 0;
for ( item = items; item->tag != 0; item++, count++ )
;
*p_nbr_children = count;
if ( count == 0 )
return new_items = NULL;
else
{
new_items = XinMemoryAlloc( count * sizeof( XinMenuItem ) );
for ( item = items, new_item = new_items; item->tag != 0;
item++, new_item++ )
copy_menu_item( new_item, item );
}
return new_items;
}
static XinMenu *
make_menu( MENU_ITEM * items )
{
XinMenu *menu = XinMemoryAlloc( sizeof( XinMenu ) );
menu->items = copy_menu_items( items, &menu->nbr_items );
return menu;
}
static MENU_ITEM *make_xvt_menu( int nbr_items, XinMenuItem * items );
static void
xvt_menu_set_text( MENU_ITEM * item, char *text )
{
char *from;
char *to;
int size = strlen( text ) + 1;
item->text = xvt_mem_alloc( size );
for ( from = text, to = item->text; *from != '\0'; )
{
if ( *from == '~' )
{
from++;
item->mkey = *from;
}
else
*to++ = *from++;
}
*to = '\0';
}
static void
copy_item_to_xvt( MENU_ITEM * new_item, XinMenuItem * item )
{
if ( item->text == NULL )
new_item->text = NULL;
else
xvt_menu_set_text( new_item, item->text );
new_item->tag = item->tag;
new_item->enabled = item->enabled;
new_item->checked = item->checked;
new_item->checkable = item->checkable;
new_item->separator = item->separator;
if ( item->nbr_children == 0 )
new_item->child = NULL;
else
new_item->child = make_xvt_menu( item->nbr_children, item->children );
}
static MENU_ITEM *
make_xvt_menu( int nbr_items, XinMenuItem * items )
{
MENU_ITEM *xvt_menu;
XinMenuItem *item;
MENU_ITEM *new_item;
int num;
if ( nbr_items == 0 )
return NULL;
xvt_menu = ( MENU_ITEM * ) xvt_mem_zalloc( ( nbr_items + 1 )
* sizeof( MENU_ITEM ) );
for ( num = 0, item = items, new_item = xvt_menu; num < nbr_items;
item++, new_item++, num++ )
copy_item_to_xvt( new_item, item );
return xvt_menu;
}
static MENU_ITEM *
find_item( MENU_ITEM * tree, XinMenuTag tag )
{
MENU_ITEM *item;
for ( item = tree; item->tag != 0; item++ )
{
if ( item->tag == tag )
return item;
if ( item->child != NULL )
{
MENU_ITEM *sub_item = find_item( item->child, tag );
if ( sub_item != NULL )
return sub_item;
}
}
return NULL;
}
/*START*/
/*
this function returns an XinMenu tree for an existing menu. if tag == 0 then
this function returns the entire menu hierarchy. if tag != 0, then this function
returns the XinMenu tree from the menu item with the specified tag through to
the tips of the branches.
the returned XinMenu has been allocated on the heap, and will need to be freed
by a call to XinMenuDelete.
*/
XinMenu *
XinWindowMenuGet( XinWindow win, XinMenuTag tag )
{
/*END*/
MENU_ITEM *item;
XinMenu *menu;
MENU_ITEM *tree = xvt_menu_get_tree( ( WINDOW ) win );
if ( tag == 0 )
menu = make_menu( tree );
else
{
item = find_item( tree, tag );
if ( item->child == 0 )
menu = NULL;
else
menu = make_menu( item->child );
}
xvt_res_free_menu_tree( tree );
return menu;
/*START*/
}
/*
this function returns the checked state of a checkable menu item.
*/
BOOLEAN
XinWindowMenuItemIsChecked( XinWindow win, XinMenuTag tag )
{
/*END*/
BOOLEAN checked;
XinMenuItem *item = XinWindowMenuItemGet( win, tag );
if ( item == 0 )
return FALSE;
checked = item->checked;
XinMenuItemFree( item );
return checked;
/*START*/
}
/*
this function returns the enabled state of a menu item.
*/
BOOLEAN
XinWindowMenuItemIsEnabled( XinWindow win, XinMenuTag tag )
{
/*END*/
BOOLEAN enabled;
XinMenuItem *item = XinWindowMenuItemGet( win, tag );
if ( item == 0 )
return FALSE;
enabled = item->enabled;
XinMenuItemFree( item );
return enabled;
/*START*/
}
/*
this function replaces a single menu item with the specified tag.
*/
void
XinWindowMenuItemReplace( XinWindow win, XinMenuTag tag, XinMenuItem * item )
{
/*END*/
MENU_ITEM *old_item;
MENU_ITEM *tree = xvt_menu_get_tree( ( WINDOW ) win );
old_item = find_item( tree, tag );
if ( item != NULL )
{
copy_item_to_xvt( old_item, item );
}
xvt_res_free_menu_tree( tree );
/*START*/
}
/*
this function retrieves a menu item. it allocates the XinMenuItem. the
allocated XinMenuItem should be placed in a menu tree, or else explicitely
freed, otherwise, a memory leak will occur.
*/
XinMenuItem *
XinWindowMenuItemGet( XinWindow win, XinMenuTag tag )
{
/*END*/
MENU_ITEM *item;
XinMenuItem *new_item;
MENU_ITEM *tree = xvt_menu_get_tree( ( WINDOW ) win );
item = find_item( tree, tag );
if ( item == NULL )
new_item = NULL;
else
{
new_item = XinMemoryAlloc( sizeof( XinMenuItem ) );
copy_menu_item( new_item, item );
}
xvt_res_free_menu_tree( tree );
return new_item;
/*START*/
}
/*
this function replaces an existing menu tree with the specified menu tree.
if tag == 0, then this function replaces the entire menu tree for the window.
if tag != 0, then this function replaces just the branch of the tree, starting
at the menu item with the specified tag.
*/
void
XinWindowMenuReplace( XinWindow win, XinMenuTag tag, XinMenu * menu )
{
/*END*/
MENU_ITEM *item;
MENU_ITEM *tree;
if ( tag == 0 )
{
tree = make_xvt_menu( menu->nbr_items, menu->items );
if ( tree == NULL )
return;
xvt_menu_set_tree( ( WINDOW ) win, tree );
}
else
{
tree = xvt_menu_get_tree( ( WINDOW ) win );
item = find_item( tree, tag );
if ( item != NULL )
{
if ( item->child != NULL )
xvt_res_free_menu_tree( item->child );
if ( menu->nbr_items == 0 )
item->child = NULL;
else
item->child = make_xvt_menu( menu->nbr_items, menu->items );
xvt_menu_set_tree( ( WINDOW ) win, tree );
}
}
if ( tree != NULL )
xvt_res_free_menu_tree( tree );
/*START*/
}
/*
gets the text of the specified menu item.
*/
char *
XinWindowMenuItemTextGet( XinWindow win, XinMenuTag tag )
{
/*END*/
XinMenuItem *item = XinWindowMenuItemGet( win, tag );
XinInitBuffer( );
if ( item == 0 )
return NULL;
if ( item->text == NULL )
xin_buffer[0] = '\0';
else
strcpy( xin_buffer, item->text );
XinMenuItemFree( item );
return xin_buffer;
/*START*/
}
/*
sets the text of the specified menu item.
*/
void
XinWindowMenuItemTextSet( XinWindow win, XinMenuTag tag, char *text )
{
/*END*/
xvt_menu_set_item_title( ( WINDOW ) win, ( MENU_TAG ) tag, text );
/*START*/
}
/*
this function traps the mouse to the specified window. see the discussion
above on mouse trapping. the argument 'continuous_mouse_moves' should be
implemented if not difficult to do.
*/
void
XinWindowMouseTrap( XinWindow win, BOOLEAN continuous_mouse_moves )
{
/*END*/
/* This is only handled under Motif. */
NOREF( continuous_mouse_moves );
xvt_win_trap_pointer( ( WINDOW ) win );
/*START*/
}
/*
this function releases a previously trapped mouse.
*/
void
XinWindowMouseRelease( void )
{
/*END*/
xvt_win_release_pointer( );
/*START*/
}
/*
under the MFC port, this function will return the MFC object for the window.
this facilitates the module using Xin to write code that uses MFC directly if
necessary.
*/
long
XinWindowNativeGet( XinWindow win )
{
/*END*/
return xvt_vobj_get_attr( ( WINDOW ) win, ATTR_NATIVE_WINDOW );
/*START*/
}
/*
this function forces all pending paint events to be generated. if certain
regions have been invalidated, and the module using Xin does not know that
all invalidated regions have received their respective paint events, then
the user of Xin can call this function. this is often done before calling
a scroll rectangular region function, because the scroll rectangular region
function uses the actual pixels in the window as the input for the bitblt.
*/
void
XinWindowPaintForce( XinWindow Win )
{
/*END*/
xvt_dwin_update( ( WINDOW ) Win );
/*START*/
}
/*
when the user of Xin is processing an XinEventPaint, then it can call this
function to determine if a particular rectangle needs to be drawn.
*/
BOOLEAN
XinWindowPaintNeeds( XinWindow Win, XinRect * rctp )
{
/*END*/
return xvt_dwin_is_update_needed( ( WINDOW ) Win, ( RCT * ) rctp );
/*START*/
}
/*
this function returns the parent of the specified window. for all top level
windows, the parent window is the task window. for scroll bars, the parent
window is the window that contains the scroll bar. Xin does not implement
child windows of top level windows.
*/
XinWindow
XinWindowParentGet( XinWindow Win )
{
/*END*/
return ( XinWindow ) xvt_vobj_get_parent( ( WINDOW ) Win );
/*START*/
}
/*
this function sets the current pen for drawing lines. calls to XinWindowPenGet
and XinWindowDrawToolsGet will reflect the changes made through this call.
*/
void
XinWindowPenSet( XinWindow win, XinPen * Pen )
{
/*END*/
CPEN cpen;
cpen.color = Pen->fore_color;
cpen.pat = PenPatternToPAT( Pen->pattern );
cpen.width = Pen->width;
switch ( Pen->pattern )
{
case XinPenDashed:
cpen.style = P_DASH;
break;
case XinPenDotted:
cpen.style = P_DOT;
break;
default:
cpen.style = P_SOLID;
break;
}
#if XIWS == XIWS_WM
xi_fix_color( &cpen.color );
#endif
xvt_dwin_set_cpen( ( WINDOW ) win, &cpen );
/*START*/
}
/*
this function draws a pie in the specified window, following the state of
clipping, pens, brushes, and copy mode. see the drawing discussion above for
more details.
*/
void
XinWindowPieDraw( XinWindow Win, XinRect* rctp, XinPoint* start, XinPoint* stop )
{
/*END*/
RCT r;
r.left = rctp->left;
r.top = rctp->top;
r.right = rctp->right;
r.bottom = rctp->bottom;
xvt_dwin_draw_pie( ( WINDOW ) Win, &r, start->h, start->v, stop->h, stop->v );
/*START*/
}
/*
This function is used to translate points from one window coordinate system to
another. It does not have to work for scrollbars. The coordinate system of a
window is 0,0 in the upper-left corner of the client rectangle. The screen window
is 0,0 in the upper-left corner of the display.
*/
void
XinWindowPointsTranslate( XinWindow FromWin, XinWindow ToWin, XinPoint * Pnts, int NbrPnts )
{
/*END*/
xvt_vobj_translate_points( ( WINDOW ) FromWin, ( WINDOW ) ToWin, ( PNT * ) Pnts, NbrPnts );
/*START*/
}
/*
this function draws a polygon in the specified window, following the state of
clipping, pens, brushes, and copy mode. see the drawing discussion above for
more details.
*/
void
XinWindowPolygonDraw( XinWindow Win, XinPoint* points, int nbr_points )
{
/*END*/
xvt_dwin_draw_polygon( ( WINDOW ) Win, (PNT*)points, nbr_points );
/*START*/
}
/*
this function draws a rectangle in the specified window, following the state of
clipping, pens, brushes, and copy mode. see the drawing discussion above for
more details.
*/
void
XinWindowRectDraw( XinWindow Win, XinRect * rctp )
{
/*END*/
RCT r;
r.left = rctp->left;
r.top = rctp->top;
r.right = rctp->right;
r.bottom = rctp->bottom;
/* Hack for OS2 - rectangles won't draw if right or bottom equal
to SHRT_MAX 8/96 XVT 4.02 */
#if XIWS == XIWS_PM
if ( r.right == SHRT_MAX )
r.right = 9999;
if ( r.bottom == SHRT_MAX )
r.bottom = 9999;
#endif
xvt_dwin_draw_rect( ( WINDOW ) Win, &r );
/*START*/
}
/*
this function draws a dotted rectangle in the specified window (added by Guy).
*/
void
XinWindowRoundRectDraw( XinWindow Win, XinRect * rctp, int rh, int rv )
{
/*END*/
RCT r;
r.left = rctp->left;
r.top = rctp->top;
r.right = rctp->right;
r.bottom = rctp->bottom;
xvt_dwin_draw_roundrect(( WINDOW ) Win, &r, rh, rv );
/*START*/
}
/*
this function draws a dotted rectangle in the specified window (added by Guy).
*/
void
XinWindowDottedRectDraw( XinWindow Win, XinRect * rctp )
{
/*END*/
RCT r;
r.left = rctp->left;
r.top = rctp->top;
r.right = rctp->right;
r.bottom = rctp->bottom;
xvt_dwin_draw_dotted_rect( ( WINDOW ) Win, &r );
/*START*/
}
/*
this function fills in the rectangle passed in as a pointer 'Rctp' with the
coordinates of the client area of the specified window. The top and left
will always be 0. This function can be called for the screen window to
get the display size.
*/
XinRect *
XinWindowRectGet( XinWindow Win, XinRect * Rctp )
{
/*END*/
RCT r;
xvt_vobj_get_client_rect( ( WINDOW ) Win, &r );
Rctp->top = r.top;
Rctp->left = r.left;
Rctp->bottom = r.bottom;
Rctp->right = r.right;
return Rctp;
/*START*/
}
/*
this function introduces a paint event into the event queue. the area for which
a paint event will be generated is specified in the argument 'rctp'.
*/
void
XinWindowRectInvalidate( XinWindow win, XinRect * rctp )
{
/*END*/
RCT r;
if ( rctp == NULL )
{
xvt_dwin_invalidate_rect( ( WINDOW ) win, NULL );
#ifdef COALESCE_UPDATES
{
WindowInfo *info = find_window_info( ( WINDOW ) win );
if ( info != NULL && info->coalesce.coalescing != 0 )
info->coalesce.invalidated = FALSE;
}
#endif
return;
}
r.left = rctp->left;
r.top = rctp->top;
r.right = rctp->right;
r.bottom = rctp->bottom;
#ifdef COALESCE_UPDATES
{
WindowInfo *info = find_window_info( ( WINDOW ) win );
if ( info != NULL && info->coalesce.coalescing != 0 )
{
if ( info->coalesce.invalidated )
XinRectEnclose( &info->coalesce.inv_rct, &info->coalesce.inv_rct,
rctp );
else
info->coalesce.inv_rct = *rctp;
info->coalesce.invalidated = TRUE;
}
else
xvt_dwin_invalidate_rect( ( WINDOW ) win, &r );
}
#else
xvt_dwin_invalidate_rect( ( WINDOW ) win, &r );
#endif
/*START*/
}
/*
this function gets the rectangle of a window, including the border of the window.
The top and left values will reflect the windows position within its parent.
This function can be called for the screen window to get the display size.
*/
XinRect *
XinWindowRectOuterGet( XinWindow Win, XinRect * Rctp )
{
/*END*/
RCT r;
xvt_vobj_get_outer_rect( ( WINDOW ) Win, &r );
Rctp->top = r.top;
Rctp->left = r.left;
Rctp->bottom = r.bottom;
Rctp->right = r.right;
return Rctp;
/*START*/
}
/*
this function causes a rectangular region to be scrolled in a horizontal direction,
a vertical direction, or both. the window system will do a bitblt to move the pixels,
and invalidate the exposed region. only pixels inside the rectangle 'Rctp' are
affected. no pixels outside of the rectangle are affected. The clipping rectangle
should not affect this function.
the paint event for the exposed region must come through recursively.
*/
void
XinWindowRectScroll( XinWindow Win, XinRect * Rctp, int dh, int dv )
{
/*END*/
#if XIWS == XIWS_WM
{ /* Strange bug in CH needs clipping region set
* twice. */
XinRect rct;
rct = *Rctp;
rct.bottom += 24;
XinWindowClipSet( Win, &rct );
XinWindowClipSet( Win, NULL );
}
#endif
#if XIWS == XIWS_PM
/* Hack for OS2 - headings don't scroll if clip rect is not set
8/96 XVT 4.02 */
XinWindowClipSet( Win, Rctp );
#endif
#if XIWS == XIWS_MAC
XinWindowClipSet( Win, NULL );
#endif
xvt_dwin_scroll_rect( ( WINDOW ) Win, ( RCT * ) Rctp, dh, dv );
/*START*/
}
/*
this function changes the size and/or position of the window as
specified by the rectangle, which specifies the outer rectangle.
*/
void
XinWindowRectSet( XinWindow Win, XinRect * Rctp )
{
/*END*/
xvt_vobj_move( ( WINDOW ) Win, ( RCT * ) Rctp );
/*START*/
}
/*
this function has the identical functionality to XinWindowPointsTranslate, except
that it translates a rectangle instead of points.
*/
void
XinWindowRectTranslate( XinWindow FromWin, XinWindow ToWin, XinRect * rect )
{
/*END*/
xvt_vobj_translate_points( ( WINDOW ) FromWin, ( WINDOW ) ToWin, ( PNT * ) rect, 2 );
/*START*/
}
/*
this function returns the screen window to the module using Xin.
*/
XinWindow
XinWindowScreenGet( void )
{
/*END*/
return ( XinWindow ) SCREEN_WIN;
/*START*/
}
/*
this function makes a window visible or invisible.
*/
void
XinWindowShow( XinWindow Win, BOOLEAN Show )
{
/*END*/
xvt_vobj_set_visible( ( WINDOW ) Win, Show );
/*START*/
}
/*
this function returns the task window to the module using Xin.
*/
XinWindow
XinWindowTaskGet( void )
{
/*END*/
return ( XinWindow ) TASK_WIN;
/*START*/
}
/*END*/
BOOLEAN xin_use_mdi_flag = TRUE; /* This is set in xiport2.c */
/*START*/
/*
this function returns the window that is most appropriate to be
a drop-down-position window's parent.
*/
XinWindow
XinWindowDropDownParentGet( XinWindow creating_win )
{
/*END*/
#if XIWS == XIWS_WIN
#if 0
if ( creating_win == xin_modal_win || xin_use_mdi_flag )
return ( XinWindow ) SCREEN_WIN; /* Unless creating_win is modal, this
will have a title bar. Life sucks. */
return ( XinWindow ) TASK_WIN;
#endif
return ( XinWindow ) SCREEN_WIN;
#else
return ( XinWindow ) TASK_WIN;
#endif
/*START*/
}
/*
this function sets or resets the opaque drawing mode for text drawing.
*/
void
XinWindowTextOpaqueSet( XinWindow win, BOOLEAN opaque )
{
/*END*/
DRAW_CTOOLS ct;
xvt_dwin_get_draw_ctools( ( WINDOW ) win, &ct );
ct.opaque_text = opaque;
xvt_dwin_set_draw_ctools( ( WINDOW ) win, &ct );
/*START*/
}
/*
this function draws text in the specified window, using the specified font,
at the specified position. it uses the current fore_color, and back_color
if drawing in opaque mode. it obeys the current clipping region.
*/
void
XinWindowTextDraw( XinWindow Win, XinFont * font, int x, int y,
char *buf, int len )
{
/*END*/
xvt_dwin_set_font( ( WINDOW ) Win, font->xvt_fntid );
xvt_dwin_draw_text( ( WINDOW ) Win, x, y, buf, len );
/*START*/
}
/*
this function draws text in the specified window, using the specified font,
at the specified position and rotated by the specified amount.
it uses the current fore_color, and back_color if drawing in opaque mode.
it obeys the current clipping region.
*/
void
XinWindowTextRotateDraw( XinWindow Win, XinFont * font, int x, int y,
int rotation, char *buf, int len )
{
/*END*/
XinRect rect;
int leading, ascent, descent, height;
int num;
if ( rotation == 0 )
{
XinWindowTextDraw( Win, font, x, y, buf, len );
return;
} else if ( rotation != 90 && rotation != 270 )
return;
xvt_dwin_set_font( (WINDOW)Win, font->xvt_fntid );
xvt_font_map( font->xvt_fntid, (WINDOW)Win );
xvt_font_get_metrics( font->xvt_fntid, &leading, &ascent, &descent );
height = leading + ascent + descent;
if ( len == -1 )
len = strlen( buf );
if ( rotation == 90 )
{
rect.top = y;
rect.bottom = y + len * height;
rect.left = x - ( ascent + leading );
rect.right = x + descent;
} else
{
rect.top = y - len * height;
rect.bottom = y;
rect.left = x - descent;
rect.right = x + ascent + leading;
}
y = rect.top + leading + ascent;
for ( num = 0; num < len; num++, y += height, buf++ )
{
int width = xvt_dwin_get_text_width( (WINDOW)Win, buf, 1 );
if ( width < height )
x = rect.left + ( height - width ) / 2;
else
x = rect.left;
xvt_dwin_draw_text( (WINDOW)Win, x, y, buf, 1 );
}
xvt_dwin_draw_text( ( WINDOW ) Win, x, y, buf, len );
/*START*/
}
/*
this function kills a timer identified by 'Timer_id'.
*/
void
XinWindowTimerKill( XinWindow win, long Timer_id )
{
/*END*/
NOREF( win );
xvt_timer_destroy( Timer_id );
/*START*/
}
/*
this function creates a timer that will generate events a specified number of
milliseconds apart.
*/
long
XinWindowTimerSet( XinWindow Win, long Millisecs )
{
/*END*/
return xvt_timer_create( ( WINDOW ) Win, Millisecs );
/*START*/
}
/*
this function returns the title of the specified window.
*/
char *
XinWindowTitleGet( XinWindow Win )
{
/*END*/
static char title[250];
if ( xvt_vobj_get_title( ( WINDOW ) Win, title, sizeof( title ) ) == NULL )
title[0] = '\0';
return title;
/*START*/
}
/*
this function sets the title of the specified window.
*/
void
XinWindowTitleSet( XinWindow Win, char *Title )
{
/*END*/
xvt_vobj_set_title( ( WINDOW ) Win, Title );
/*START*/
}
/*END*/
static SCROLL_TYPE
convert_to_SCROLL_TYPE( XinScrollBarType type )
{
switch ( type )
{
case XinScrollBarTypeHorizontal:
return HSCROLL;
case XinScrollBarTypeVertical:
return VSCROLL;
case XinScrollBarTypeEither:
return HVSCROLL;
}
return HSCROLL;
}
/*
this function gets the current position of the scroll bar specified by
the argument 'Win'.
*/
int
XinScrollBarPositionGet( XinWindow Win, XinScrollBarType Type )
{
return xvt_sbar_get_pos( ( WINDOW ) Win, convert_to_SCROLL_TYPE( Type ) );
}
/*
this function sets the current position of the scroll bar specified by
the argument 'Win'.
*/
void
XinScrollBarPositionSet( XinWindow Win, XinScrollBarType Type, int Top )
{
if ( app_terminating )
return;
xvt_sbar_set_pos( ( WINDOW ) Win, convert_to_SCROLL_TYPE( Type ), Top );
}
/*
this function gets the current proportion for a scrollbar
*/
int
XinScrollBarProportionGet( XinWindow Win, XinScrollBarType Type )
{
return xvt_sbar_get_proportion( ( WINDOW ) Win, convert_to_SCROLL_TYPE( Type ) );
}
/*
this function gets the current range for a scrollbar
*/
void
XinScrollBarRangeGet( XinWindow Win, XinScrollBarType Type, int *Rng1, int *Rng2 )
{
if ( app_terminating )
return;
xvt_sbar_get_range( ( WINDOW ) Win, convert_to_SCROLL_TYPE( Type ), Rng1, Rng2 );
}
/*
this function sets the range (min_val, max_val), proportion, and position for
a scrollbar
*/
void
XinScrollBarSet( XinWindow Win, XinScrollBarType Type, int min_val, int max_val,
int proportion, int pos )
{
WINDOW xvt_win = ( WINDOW ) Win;
SCROLL_TYPE scroll_type = convert_to_SCROLL_TYPE( Type );
#if XIWS == XIWS_XM
WINDOW parent_win = xvt_vobj_get_parent( xvt_win );
if ( proportion != 0 )
{
if ( pos == min_val )
pos = min_val + 1;
if ( pos == ( max_val - proportion ) )
pos = max_val - proportion - 1;
#endif
xvt_sbar_set_range( xvt_win, scroll_type, min_val, max_val );
xvt_sbar_set_proportion( xvt_win, scroll_type, proportion );
#if XIWS == XIWS_WXGTK
if (pos >= 0)
#endif
xvt_sbar_set_pos( xvt_win, scroll_type, pos );
#if XIWS == XIWS_XM
{
WINDOW focus_win = xvt_scr_get_focus_vobj();
if ( parent_win && (focus_win == xvt_win) )
xvt_scr_set_focus_vobj( parent_win );
}
}
#endif
}
/*
this function queries whether a particular format is available on the clipboard.
*/
BOOLEAN
XinClipboardFormatAvail( XinClipboardFormat Format )
{
/*END*/
switch ( Format )
{
case XinClipboardFormatText:
return xvt_cb_has_format( CB_TEXT, NULL );
case XinClipboardFormatBitmap:
return FALSE;
}
return FALSE;
/*START*/
}
/*
given a format, this function gets the contents of the clipboard.
*/
void *
XinClipboardGet( XinClipboardFormat Format, long *size )
{
/*END*/
char *ptr = NULL;
if ( !xvt_cb_open( FALSE ) )
return ptr;
switch ( Format )
{
case XinClipboardFormatText:
{
void *cb_ptr;
cb_ptr = xvt_cb_get_data( CB_TEXT, NULL, size );
if ( cb_ptr != NULL && *size > 0 )
{
ptr = XinMemoryAlloc( ( int ) ( *size + 1 ) );
memcpy( ptr, cb_ptr, ( int ) *size );
ptr[( int ) *size] = '\0';
}
break;
}
case XinClipboardFormatBitmap:
ptr = NULL;
break;
}
xvt_cb_close( );
return ptr;
/*START*/
}
/*
this function puts data on to the clipboard. the format of the
data is specified in the argument 'format'.
*/
void
XinClipboardPut( XinClipboardFormat format, long size, void *data )
{
/*END*/
CB_FORMAT xvt_format;
char *buf;
if ( !xvt_cb_open( TRUE ) )
return;
buf = xvt_cb_alloc_data( size + 1 );
memcpy( buf, data, ( size_t ) size );
buf[( int ) size] = '\0';
switch ( format )
{
case XinClipboardFormatText:
xvt_format = CB_TEXT;
buf = NULL;
break;
case XinClipboardFormatBitmap:
xvt_format = CB_PICT;
break;
default:
xvt_format = CB_APPL;
break;
}
xvt_cb_put_data( xvt_format, NULL, size + 1, ( PICTURE ) buf );
xvt_cb_free_data( );
xvt_cb_close( );
/*START*/
}
/*END*/
void
xi_terminate( void )
{
app_terminating = TRUE;
xvt_vobj_destroy( TASK_WIN );
}
/*START*/
/*
when the application is terminated, it generates an XinEventQuit event.
during the XinEventQuit, the application can put up a dialog box if desired,
querying from the user whether it is ok to quit the application, and
possibly saving files. if it is ok for the application to quit, then
during processing of that event, the module using Xin should call
XinAppQuitOk.
*/
void
XinAppQuitOk( void )
{
/*END*/
xvt_app_allow_quit( );
/*START*/
}
/*
this function terminates the application. it will cause an XinEventQuit
event to be generated. see XinAppQuitOk for more details.
*/
void
XinAppTerminate( void )
{
/*END*/
XinMemoryFree( xin_buffer );
if (xin_family_names_initialized)
{
XinMemoryFree( xin_family_name_times );
XinMemoryFree( xin_family_name_fixed );
XinMemoryFree( xin_family_name_system );
XinMemoryFree( xin_family_name_helvetica );
}
app_terminating = TRUE;
xvt_vobj_destroy( TASK_WIN );
/*START*/
}
/*
this function prints to a file named "DEBUG". if the file does not exist,
then this function does nothing. if the file exists, then the first time
that this function is called, it creates the debug file over top of the
existing one. thereafter, this function appends to the debug file.
The data written to the file must be flushed at the end of the function,
perhaps by closing the file.
*/
void
XinDebugPrintf( char *format,... )
{
/*END*/
va_list argptr;
XinInitBuffer( );
va_start( argptr, format );
vsprintf( xin_buffer, format, argptr );
va_end( argptr );
xvt_debug_printf( "%s", xin_buffer );
/*START*/
}
/*
this function forces any pending events to be sent to the application.
it typically is called during processing that will take more than one
or two seconds.
*/
void
XinPendingEventsProcess( void )
{
/*END*/
xvt_app_process_pending_events( );
/*START*/
}
/*
this function makes a small noise.
*/
void
XinBeep( void )
{
/*END*/
xvt_scr_beep( );
/*START*/
}
/*
this function takes separate red, green, and blue values and creates
one RGB value.
the following implementation is complete.
*/
XinColor
XinColorMake( int red, int green, int blue )
{
return ( red << 16 ) | ( green << 8 ) | blue;
}
/*
this function compares a string to a pattern. the pattern can contain
wild cards (*, ?) returns TRUE if the pattern matches the string.
if 'case_sensitive' is true, then this function pays attention to the
case of the characters.
*/
BOOLEAN
XinStringMatch( char *string, char *pattern, BOOLEAN case_sensitive )
{
/*END*/
return xvt_str_match( string, pattern, case_sensitive );
/*START*/
}
/*
this function changes the cursor to the wait cursor until the program
returns from processing the event during which this function was called.
*/
void
XinCursorWait( )
{
/*END*/
xvt_scr_set_busy_cursor( );
/*START*/
}
/*
this function gets metrics of many things in the GUI.
*/
long
XinMetricGet( XinMetricType type )
{
switch ( type )
{
case XinMetricIconHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_ICON_HEIGHT );
case XinMetricIconWidth:
return xvt_vobj_get_attr( NULL_WIN, ATTR_ICON_WIDTH );
case XinMetricHorizontalScrollBarHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_CTL_HORZ_SBAR_HEIGHT );
case XinMetricVerticalScrollBarWidth:
return xvt_vobj_get_attr( NULL_WIN, ATTR_CTL_VERT_SBAR_WIDTH );
case XinMetricScreenHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_SCREEN_HEIGHT );
case XinMetricScreenWidth:
return xvt_vobj_get_attr( NULL_WIN, ATTR_SCREEN_WIDTH );
case XinMetricSizableFrameHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_DOCFRAME_HEIGHT );
case XinMetricSizableFrameWidth:
return xvt_vobj_get_attr( NULL_WIN, ATTR_DOCFRAME_WIDTH );
case XinMetricDoubleFrameHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_DBLFRAME_HEIGHT );
case XinMetricDoubleFrameWidth:
return xvt_vobj_get_attr( NULL_WIN, ATTR_DBLFRAME_WIDTH );
case XinMetricFrameHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_FRAME_HEIGHT );
case XinMetricFrameWidth:
return xvt_vobj_get_attr( NULL_WIN, ATTR_FRAME_WIDTH );
case XinMetricMenuHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_MENU_HEIGHT );
case XinMetricTitleHeight:
return xvt_vobj_get_attr( NULL_WIN, ATTR_TITLE_HEIGHT );
case XinMetricVerticalStagger:
return xvt_vobj_get_attr( NULL_WIN, ATTR_DOC_STAGGER_VERT );
case XinMetricHorizontalStagger:
return xvt_vobj_get_attr( NULL_WIN, ATTR_DOC_STAGGER_HORZ );
case XinMetricScreenHRes:
return xvt_vobj_get_attr( NULL_WIN, ATTR_SCREEN_HRES );
case XinMetricScreenVRes:
return xvt_vobj_get_attr( NULL_WIN, ATTR_SCREEN_VRES );
}
return 0;
}
/*
in some situations, we desire to coalesce invalidated regions. this is not
used for MFC.
*/
void
XinCoalesceInvalidates( XinWindow win, BOOLEAN coalesce )
{
/*END*/
#ifdef COALESCE_UPDATES
WindowInfo *info = find_window_info( ( WINDOW ) win );
if ( info != NULL )
{
if ( coalesce )
{
if ( info->coalesce.coalescing == 0 )
info->coalesce.invalidated = FALSE;
++info->coalesce.coalescing;
}
else
{
--info->coalesce.coalescing;
if ( info->coalesce.coalescing == 0 && info->coalesce.invalidated )
XinWindowRectInvalidate( win, &info->coalesce.inv_rct );
}
}
#else
NOREF( win );
NOREF( coalesce );
#endif
/*START*/
}
/*END*/
void
XinXvtEventGet( void *xvte )
{
*( EVENT * ) xvte = *cur_xvt_event;
}
#define UNDEFINED 1000
char *
XinXvtEventTextGet( void *xvte )
{
int num;
static struct
{
int type;
char *desc;
} xvt_event_text[] =
{
{
E_CREATE, "E_CREATE"
},
{
E_DESTROY, "E_DESTROY"
},
{
E_FOCUS, "E_FOCUS"
},
{
E_SIZE, "E_SIZE"
},
{
E_UPDATE, "E_UPDATE"
},
{
E_CLOSE, "E_CLOSE"
},
{
E_MOUSE_DOWN, "E_MOUSE_DOWN"
},
{
E_MOUSE_UP, "E_MOUSE_UP"
},
{
E_MOUSE_MOVE, "E_MOUSE_MOVE"
},
{
E_MOUSE_DBL, "E_MOUSE_DBL"
},
{
E_CHAR, "E_CHAR"
},
{
E_VSCROLL, "E_VSCROLL"
},
{
E_HSCROLL, "E_HSCROLL"
},
{
E_COMMAND, "E_COMMAND"
},
{
E_FONT, "E_FONT"
},
{
E_CONTROL, "E_CONTROL"
},
{
E_TIMER, "E_TIMER"
},
{
E_QUIT, "E_QUIT"
},
{
E_HELP, "E_HELP"
},
{
E_USER, "E_USER"
},
{
UNDEFINED, "Unknown XVT Event"
}
};
for ( num = 0; xvt_event_text[num].type != ( ( EVENT * ) xvte )->type &&
xvt_event_text[num].type != UNDEFINED; num++ )
;
return xvt_event_text[num].desc;
}
/*START*/
/*
this function returns whether a rectangle is empty or not.
the following implementation is complete.
*/
BOOLEAN
XinRectEmpty( XinRect * rect )
{
return ( rect->top >= rect->bottom && rect->left >= rect->right );
}
/*
this function determines the intersection between two mathmatical rectangles.
the following implementation is complete.
*/
XinRect *
XinRectIntersect( XinRect * result, XinRect * r1, XinRect * r2 )
{
XinRect rect;
rect = *r1;
if ( r2->top > rect.top )
rect.top = r2->top;
if ( r2->left > rect.left )
rect.left = r2->left;
if ( r2->bottom < rect.bottom )
rect.bottom = r2->bottom;
if ( r2->right < rect.right )
rect.right = r2->right;
if ( rect.bottom < rect.top || rect.right < rect.left )
{
rect.bottom = rect.top;
rect.right = rect.left;
}
*result = rect;
return result;
}
/*
this function determines whether the specified point is contained in the
specified rectangle.
the following implementation is complete.
*/
BOOLEAN
XinRectPointContained( XinRect * rect, XinPoint * point )
{
return ( point->h >= rect->left && point->h <= rect->right
&& point->v >= rect->top && point->v <= rect->bottom );
}
/*
get the enclosing rectangle of two other rectangles.
src1, src2 are the rects of interest.
dst is set to the enclosing rect and returned.
If is OK for dst to equal one of the sources.
the following implementation is complete.
*/
XinRect *
XinRectEnclose( XinRect * dst, XinRect * src1, XinRect * src2 )
{
XinRect rct;
rct.top = min( src1->top, src2->top );
rct.left = min( src1->left, src2->left );
rct.bottom = max( src1->bottom, src2->bottom );
rct.right = max( src1->right, src2->right );
*dst = rct;
return ( dst );
}
/*END*/
static void
menu_free_items( int nbr_items, XinMenuItem * items )
{
int num;
XinMenuItem *item;
for ( num = 0, item = items; num < nbr_items; num++, item++ )
{
if ( item->text != NULL )
XinMemoryFree( item->text );
if ( item->nbr_children != 0 )
{
menu_free_items( item->nbr_children, item->children );
XinMemoryFree( item->children );
}
}
}
static char *
copy_menu_text( char *text )
{
char *new_text;
int size = strlen( text ) + 1;
new_text = XinMemoryAlloc( size );
memcpy( new_text, text, size );
return new_text;
}
static XinMenuItem *
menu_clone_items( int nbr_items, XinMenuItem * items )
{
int num;
XinMenuItem *item;
XinMenuItem *new_items;
new_items = XinMemoryAlloc( nbr_items * sizeof( XinMenuItem ) );
memmove( new_items, items, nbr_items * sizeof( XinMenuItem ) );
for ( num = 0, item = new_items; num < nbr_items; num++, item++ )
{
if ( item->text != NULL )
item->text = copy_menu_text( item->text );
if ( item->nbr_children != 0 )
item->children = menu_clone_items( item->nbr_children, item->children );
}
return new_items;
}
/*START*/
/*
this function adds the specified menu item into a menu structure at the position
indicated by index. It does not change the menu for any window.
it returns a pointer to the newly created menu item.
*/
XinMenuItem *
XinMenuAdd( XinMenu * menu, int index, XinMenuItem * item )
{
/*END*/
if ( index < 0 || index > menu->nbr_items )
return NULL;
if ( menu->nbr_items == 0 )
{
menu->nbr_items = 1;
menu->items = XinMemoryAlloc( sizeof( XinMenuItem ) );
}
else
{
menu->nbr_items++;
menu->items = XinMemoryRealloc( menu->items, menu->nbr_items
* sizeof( XinMenuItem ) );
}
if ( index < menu->nbr_items - 1 )
memmove( menu->items + index + 1, menu->items + index,
( menu->nbr_items - index - 1 ) * sizeof( XinMenuItem ) );
memmove( menu->items + index, item, sizeof( XinMenuItem ) );
item = menu->items + index;
if ( item->text != NULL )
item->text = copy_menu_text( item->text );
if ( item->nbr_children != 0 )
item->children = menu_clone_items( item->nbr_children, item->children );
return item;
/*START*/
}
/*
this function creates an empty menu. subsequent to this, the module using Xin
will probably call XinMenuAdd.
the following implementation is complete.
*/
XinMenu *
XinMenuCreate( void )
{
XinMenu *menu = XinMemoryAlloc( sizeof( XinMenu ) );
menu->nbr_items = 0;
menu->items = NULL;
return menu;
}
/*
this function deletes a menu item at a specified index in a menu structure.
It does not change the menu for any window.
*/
BOOLEAN
XinMenuDelete( XinMenu * menu, int index )
{
/*END*/
if ( index < 0 || index >= menu->nbr_items )
return FALSE;
menu->nbr_items--;
if ( index < menu->nbr_items )
memmove( menu->items + index, menu->items + index + 1,
( menu->nbr_items - index ) * sizeof( XinMenuItem ) );
return TRUE;
/*START*/
}
/*
this function allocates and duplicates a menu hierarchy
*/
XinMenu *
XinMenuDuplicate( XinMenu * menu )
{
/*END*/
XinMenu *new_menu = XinMemoryAlloc( sizeof( XinMenu ) );
new_menu->nbr_items = menu->nbr_items;
if ( menu->nbr_items != 0 )
new_menu->items = menu_clone_items( menu->nbr_items, menu->items );
else
new_menu->items = NULL;
return new_menu;
/*START*/
}
/*
this function frees a menu hierarchy
*/
void
XinMenuFree( XinMenu * menu )
{
/*END*/
if ( menu->items != NULL )
{
menu_free_items( menu->nbr_items, menu->items );
XinMemoryFree( menu->items );
}
XinMemoryFree( menu );
/*START*/
}
/*
this function adds the specified child menu item into a parent menu item.
It does not change the menu for any window.
*/
XinMenuItem *
XinMenuItemAdd( XinMenuItem * parent, int index, XinMenuItem * child )
{
/*END*/
if ( index < 0 || index > parent->nbr_children )
return NULL;
if ( parent->nbr_children == 0 )
{
parent->nbr_children = 1;
parent->children = XinMemoryAlloc( sizeof( XinMenuItem ) );
}
else
{
parent->nbr_children++;
parent->children = XinMemoryRealloc( parent->children, parent->nbr_children
* sizeof( XinMenuItem ) );
}
if ( index < parent->nbr_children - 1 )
memmove( parent->children + index + 1, parent->children + index,
( parent->nbr_children - index - 1 ) * sizeof( XinMenuItem ) );
memmove( parent->children + index, child, sizeof( XinMenuItem ) );
child = parent->children + index;
if ( child->text != NULL )
child->text = copy_menu_text( child->text );
if ( child->nbr_children != 0 )
child->children = menu_clone_items( child->nbr_children, child->children );
return child;
/*START*/
}
/*
this function creates a menu item from a text string.
*/
XinMenuItem *
XinMenuItemCreate( char *text )
{
/*END*/
XinMenuItem *item = XinMemoryZeroAlloc( sizeof( XinMenuItem ) );
if ( text != NULL )
item->text = copy_menu_text( text );
return item;
/*START*/
}
/*
this function allocates and duplicates a menu item.
*/
XinMenuItem *
XinMenuItemDuplicate( XinMenuItem * item )
{
/*END*/
XinMenuItem *new_item = XinMemoryAlloc( sizeof( XinMenuItem ) );
memmove( new_item, item, sizeof( XinMenuItem ) );
if ( item->nbr_children != 0 )
new_item->children = menu_clone_items( item->nbr_children,
item->children );
if ( item->text != NULL )
new_item->text = copy_menu_text( item->text );
return new_item;
/*START*/
}
/*
this function deletes a child menu item from a parent menu item.
It does not change the menu for any window.
*/
BOOLEAN
XinMenuItemDelete( XinMenuItem * item, int index )
{
/*END*/
if ( index < 0 || index >= item->nbr_children )
return FALSE;
item->nbr_children--;
if ( index < item->nbr_children )
memmove( item->children + index, item->children + index + 1,
( item->nbr_children - index ) * sizeof( XinMenuItem ) );
return TRUE;
/*START*/
}
/*
this function frees the memory for a menu item.
*/
void
XinMenuItemFree( XinMenuItem * item )
{
/*END*/
if ( item->nbr_children != 0 )
{
menu_free_items( item->nbr_children, item->children );
XinMemoryFree( item->children );
}
if ( item->text != NULL )
XinMemoryFree( item->text );
XinMemoryFree( item );
/*START*/
}
/*
this function sets the text on a menu item.
It does not change the menu for any window.
*/
void
XinMenuItemTextSet( XinMenuItem * item, char *text )
{
/*END*/
if ( item->text != NULL )
XinMemoryFree( item->text );
if ( text == NULL )
item->text = NULL;
else
item->text = copy_menu_text( text );
/*START*/
}
/*END*/
#if XIWS == XIWS_XM
long
XinWindowGetWidget( XinWindow win )
{
return xvt_vobj_get_attr( ( WINDOW ) win, ATTR_X_WIDGET );
}
#endif
/*START*/
/*
this function returns whether the bold attribute is set for a font.
*/
BOOLEAN
XinFontBoldGet( XinFont * font )
{
return font->bold;
}
/*
this function sets the bold attribute for a font.
*/
void
XinFontBoldSet( XinFont * font, BOOLEAN flag )
{
/*END*/
unsigned long attrib;
font->bold = flag;
attrib = xvt_font_get_style( font->xvt_fntid );
if ( flag )
attrib |= XVT_FS_BOLD;
else
attrib &= ~XVT_FS_BOLD;
xvt_font_set_style( font->xvt_fntid, attrib );
/*START*/
}
/*
this function compares two fonts, and if they will have exactly the same
appearance, the function returns TRUE; if not, FALSE.
*/
BOOLEAN
XinFontCompare( XinFont * f1, XinFont * f2 )
{
/*END*/
char buf1[FONT_ATTR_SIZE];
char buf2[FONT_ATTR_SIZE];
if ( f1 == f2 )
return TRUE;
if ( !f1->from_xvt_font && !f2->from_xvt_font )
return ( f1->family == f2->family && f1->size == f2->size
&& f1->bold == f2->bold && f1->italic == f2->italic );
/* XVT internal compare */
/* If both font have valid native descs, compare those */
if ( xvt_font_get_native_desc( f1->xvt_fntid, buf1, FONT_ATTR_SIZE ) &&
xvt_font_get_native_desc( f2->xvt_fntid, buf2, FONT_ATTR_SIZE ) )
{
if ( *buf1 && *buf2 )
return ( strncmp( buf1, buf2, FONT_ATTR_SIZE ) == 0 );
}
/* If one of the fonts lacks nd, compare portable attrs */
if ( xvt_font_get_style( f1->xvt_fntid ) != xvt_font_get_style( f2->xvt_fntid ) )
return FALSE;
if ( xvt_font_get_size( f1->xvt_fntid ) != xvt_font_get_size( f2->xvt_fntid ) )
return FALSE;
if ( !xvt_font_get_family( f1->xvt_fntid, buf1, FONT_ATTR_SIZE ) )
return FALSE;
if ( !xvt_font_get_family( f2->xvt_fntid, buf2, FONT_ATTR_SIZE ) )
return FALSE;
return ( strncmp( buf1, buf2, FONT_ATTR_SIZE ) == 0 );
/*START*/
}
/*
this function creates a new font and initializes it with
a copy of the "Source" font, unless "Source" is NULL.
*/
void
XinFontCopy( XinFont ** Dest, XinFont * Source )
{
/*END*/
XinFont *new_font;
if ( Source == NULL )
*Dest = NULL;
else
{
new_font = XinMemoryAlloc( sizeof( XinFont ) );
*Dest = new_font;
*new_font = *Source;
new_font->xvt_fntid = xvt_font_create( );
xvt_font_copy( new_font->xvt_fntid, Source->xvt_fntid,
( unsigned long ) XVT_FA_ALL );
}
/*START*/
}
/*
this function allocates (creates) a font. after allocating the font,
the module using Xin may set the family, set the size, bold style,
italic style, and map the font to a window.
*/
XinFont *
XinFontCreate( void )
{
/*END*/
XinFont *xin_font;
xin_font = XinMemoryZeroAlloc( sizeof( XinFont ) );
xin_font->xvt_fntid = xvt_font_create( );
return xin_font;
/*START*/
}
/*
this function destroys a font
*/
void
XinFontDestroy( XinFont * font )
{
/*END*/
xvt_font_destroy( font->xvt_fntid );
XinMemoryFree( font );
/*START*/
}
/*
this function returns the family for a font. If the font was selected
from a dialog, then XinFontFamilyOther may be returned.
*/
XinFontFamily
XinFontFamilyGet( XinFont * font )
{
return font->family;
}
/*
this function sets the family for a font.
*/
void
XinFontFamilySet( XinFont * font, XinFontFamily family )
{
/*END*/
font->family = family;
switch ( family )
{
case XinFontFamilySystem:
xvt_font_set_family( font->xvt_fntid, XVT_FFN_SYSTEM );
break;
case XinFontFamilyFixed:
xvt_font_set_family( font->xvt_fntid, XVT_FFN_COURIER );
break;
case XinFontFamilyTimes:
xvt_font_set_family( font->xvt_fntid, XVT_FFN_TIMES );
break;
case XinFontFamilyHelvetica:
xvt_font_set_family( font->xvt_fntid, XVT_FFN_HELVETICA );
break;
default:
break;
}
/*START*/
}
/*
this function returns the mapped state of a font.
*/
BOOLEAN
XinFontIsMapped( XinFont * font )
{
/*END*/
return xvt_font_is_mapped( font->xvt_fntid );
/*START*/
}
/*
this function returns the italic style state for a font.
*/
BOOLEAN
XinFontItalicGet( XinFont * font )
{
return font->italic;
}
/*
this function sets the italic style state for a font.
*/
void
XinFontItalicSet( XinFont * font, BOOLEAN flag )
{
/*END*/
unsigned long attrib;
font->italic = flag;
attrib = xvt_font_get_style( font->xvt_fntid );
if ( flag )
attrib |= XVT_FS_ITALIC;
else
attrib &= ~XVT_FS_ITALIC;
xvt_font_set_style( font->xvt_fntid, attrib );
/*START*/
}
/*
this function gets the vertical metrics for a font. the font must be mapped to
a window in order to call this function.
*/
void
XinFontMetricsGet( XinFont * Font, int *Leading, int *Ascent, int *Descent )
{
/*END*/
xvt_font_get_metrics( Font->xvt_fntid, Leading, Ascent,
Descent );
/*START*/
}
/*
this function returns the point size for a font.
*/
int
XinFontSizeGet( XinFont * Font )
{
return Font->size;
}
/*
this function sets the point size for a font.
*/
void
XinFontSizeSet( XinFont * Font, int size )
{
/*END*/
Font->size = size;
xvt_font_set_size( Font->xvt_fntid, size );
/*START*/
}
/*
this function gets the width in pixels for the specified text, based on the
specified font. the font must be mapped to a window. if 'len' is equal to
-1, then this function returns the pixel length of the entire string pointed
to by text. if 'len' is not equal to -1, then this function returns the pixel
length of the first 'len' characters of the string in 'text'
*/
int
XinFontTextWidthGet( XinFont * font, char *text, int len )
{
/*END*/
XVT_FNTID font_id = font->xvt_fntid;
WINDOW win;
if ( !xvt_font_is_mapped( font_id ) )
return 0;
win = xvt_font_get_win( font_id );
xvt_dwin_set_font( win, font_id );
return xvt_dwin_get_text_width( win, text, len );
/*START*/
}
/*
this function destroys (frees) a bitmap.
*/
void
XinBitmapDestroy( XinBitmap * bitmap )
{
/*END*/
xvt_image_destroy( bitmap->image );
XinMemoryFree( bitmap );
/*START*/
}
/*END*/
/*START*/
/*
this function allocates, and reads a bitmap from the specified file.
*/
XinBitmap *
XinBitmapRead( char *filename )
{
/*END*/
XVT_IMAGE image;
XinBitmap *bitmap;
if ( ( image = xvt_image_read( filename ) ) == NULL )
return NULL;
bitmap = XinMemoryAlloc( sizeof( XinBitmap ) );
bitmap->image = image;
if ( xin_palette == NULL )
xin_palette = xvt_palet_create( XVT_PALETTE_USER, 0 );
xvt_palet_add_colors_from_image( xin_palette, bitmap->image );
xvt_vobj_set_palet( SCREEN_WIN, xin_palette );
return bitmap;
/*START*/
}
/*START*/
/*
this function allocates, and reads a bitmap from the resource file.
*/
XinBitmap *
XinBitmapReadRes( short id)
{
/*END*/
XVT_IMAGE image;
XinBitmap *bitmap;
if ( ( image = xvt_res_get_image( id ) ) == NULL )
return NULL;
bitmap = XinMemoryAlloc( sizeof( XinBitmap ) );
bitmap->image = image;
if ( xin_palette == NULL )
xin_palette = xvt_palet_create( XVT_PALETTE_USER, 0 );
xvt_palet_add_colors_from_image( xin_palette, bitmap->image );
xvt_vobj_set_palet( SCREEN_WIN, xin_palette );
return bitmap;
/*START*/
}
/*
this function returns the width and height of the
specified bitmap.
*/
void
XinBitmapSizeGet( XinBitmap * bitmap, short *pw, short *ph )
{
/*END*/
xvt_image_get_dimensions( bitmap->image, pw, ph );
/*START*/
}
/*
this function returns the next band to be printed. see the discussion on printing
and banding above for more details.
*/
XinRect *
XinPrintBandNext( void )
{
/*END*/
return ( XinRect * ) xvt_print_get_next_band( );
/*START*/
}
/*
this function is called when a page has been completely drawn. it causes the page
to be sent to the printer.
*/
BOOLEAN
XinPrintPageEnd( XinPrintRecord * rec )
{
/*END*/
return xvt_print_close_page( ( PRINT_RCD * ) rec );
/*START*/
}
/*
this function is called when the module using Xin is about to print a page.
*/
BOOLEAN
XinPrintPageStart( XinPrintRecord * rec )
{
/*END*/
return xvt_print_open_page( ( PRINT_RCD * ) rec );
/*START*/
}
/*
this function allocates and initializes a print record. after this function has
been called, then XinDialogPrinterSetup can be called, getting the user's
instructions on which printer to print the document, whether the document is printed
in landscape or portrait mode, etc. then, the filled in XinPrintRecord is passed
to XinPrintPageStart, XinPrintBandNext, and XinPrintPageEnd.
The returned print record will contain the default printer setup.
*/
XinPrintRecord *
XinPrintRecordCreate( int *p_size )
{
/*END*/
return ( XinPrintRecord * ) xvt_print_create( p_size );
/*START*/
}
/*
this function frees up the memory and any resources
allocated for a print record.
*/
void
XinPrintRecordDestroy( XinPrintRecord * rec )
{
/*END*/
xvt_print_destroy( ( PRINT_RCD * ) rec );
/*START*/
}
/*
this function returns whether a print record still contains valid information. an
example of invalid information is if the print record contains information on a
printer that is no longer attached to the computer.
*/
BOOLEAN
XinPrintRecordValidate( XinPrintRecord * rec )
{
/*END*/
return xvt_print_is_valid( ( PRINT_RCD * ) rec );
/*START*/
}
/*
This function gets the height and width of the printer area in pixels (or dots),
and the vertical and horizontal resolution in pixels per inch.
*/
void
XinPrintRecordMetricsGet( XinPrintRecord * rec, long * height, long * width,
long * vres, long * hres )
{
/*END*/
xvt_app_escape(XVT_ESC_GET_PRINTER_INFO, ( PRINT_RCD * ) rec, height,
width, vres, hres);
/*START*/
}
/*
on some implementations, it is necessary, or desirable, to start a
separate thread for printing.
if threaded printing is implemented, then the thread should be started so that it
calls 'func' as soon as it starts. 'func' then does the actual printing.
if threaded printing is not implemented, then this function simply calls 'func'.
*/
BOOLEAN
XinPrintThreadStart( XinPrintHandler func, long app_data )
{
/*END*/
return xvt_print_start_thread( func, app_data );
/*START*/
}
/*
this function creates a print window.
*/
XinWindow
XinPrintWindowCreate( XinPrintRecord * rec, char *title )
{
/*END*/
return ( XinWindow ) xvt_print_create_win( ( PRINT_RCD * ) rec, title );
/*START*/
}
/*
this function destroys a print window.
*/
void
XinPrintWindowDestroy( XinWindow win )
{
/*END*/
xvt_vobj_destroy( ( WINDOW ) win );
/*START*/
}
/*END*/
#if XIWS == XIWS_WIN
static char *
find_last_slash( char *str )
{
char *p = str + strlen( str ) - 1;
if ( *str == '\0' )
return NULL;
while ( p != str )
{
if ( *p == '\\' || *p == '/' )
return p;
p--;
}
return NULL;
}
static void
copy_leading_path( char *path, char *dest )
{
char *p = find_last_slash( path );
if ( p != NULL )
{
int len = ( int ) ( p - path );
memmove( dest, path, len );
dest[len] = '\0';
}
else
*dest = '\0';
}
#endif
/*START*/
/*
This function returns the full directory path based on "full_name", which
may contain relative directory information.
The implementation is complete.
*/
BOOLEAN
XinDirectoryAbsoluteGet( char *full_name, XinDirectory * dir )
{
/*END*/
#if XIWS == XIWS_WIN
XinDirectory current_dir;
if ( isalpha( full_name[0] ) && full_name[1] == ':' )
{ /* Drive letter - find current directory for
* that drive */
if ( full_name[2] == '\\' || full_name[2] == '/' )
{ /* Got full path name */
copy_leading_path( full_name, ( char * ) dir );
}
else
{ /* Relative path for that drive. */
XinDirectory save_dir;
char *p_dir = ( char * ) dir;
if ( !XinDirectoryCurrentGet( &save_dir ) )
return FALSE;
current_dir[0] = full_name[0];
current_dir[1] = ':';
current_dir[2] = '.';
current_dir[3] = '\0';
if ( !XinDirectoryCurrentSet( &current_dir ) )
return FALSE;
if ( !XinDirectoryCurrentGet( &current_dir ) )
{
XinDirectoryCurrentSet( &save_dir );
return FALSE;
}
XinDirectoryCurrentSet( &save_dir );
strcpy( p_dir, current_dir );
p_dir += strlen( p_dir );
*p_dir++ = '/';
copy_leading_path( full_name + 2, p_dir );
}
}
else
{
char *p_dir = ( char * ) dir;
if ( !XinDirectoryCurrentGet( &current_dir ) )
return FALSE;
if ( full_name[0] == '\\' || full_name[0] == '/' )
{ /* Got full path, but need drive */
*p_dir++ = current_dir[0];
*p_dir++ = ':';
}
else
{ /* Relative path */
strcpy( p_dir, current_dir );
p_dir += strlen( p_dir );
*p_dir++ = '/';
}
copy_leading_path( full_name, p_dir );
}
{
/* copy_leading_path() can copy nothing, but we appended a '/' for it
* regardless. */
char *p_dir = ( char * ) dir;
p_dir += strlen( ( char * ) dir ) - 1;
if ( *p_dir == '/' )
{
*p_dir = '\0';
}
}
#elif XIWS == XIWS_MAC
char *p_dir;
/* Leading colon means it is relative */
if ( full_name[0] == ':' )
{
if ( !XinDirectoryCurrentGet( dir ) )
return FALSE;
p_dir = ( char * ) dir + strlen( ( char * ) dir );
}
else
{
*( char * ) dir = '\0';
p_dir = ( char * ) dir;
}
/* Directory goes to last colon. */
{
char *p = strrchr( full_name, ':' );
if ( p != NULL )
{
int len = ( int ) ( p - full_name );
memmove( p_dir, full_name, len );
p_dir[len] = '\0';
}
}
#else
char *p_dir;
/* Leading slash means it is absolute */
if ( full_name[0] != '/' )
{
if ( !XinDirectoryCurrentGet( dir ) )
return FALSE;
p_dir = ( char * ) dir + strlen( ( char * ) dir );
}
else
{
*( char * ) dir = '\0';
p_dir = ( char * ) dir;
}
/* Directory goes to last slash. */
{
char *p = strrchr( full_name, '/' );
if ( p != NULL )
{
int len = ( int ) ( p - full_name - 1 );
memmove( p_dir, full_name, len );
p_dir[len] = '\0';
}
}
#endif
return TRUE;
/*START*/
}
/*
this function gets the current directory, and puts the result in an
XinDirectory.
*/
BOOLEAN
XinDirectoryCurrentGet( XinDirectory * dir )
{
/*END*/
return ( xvt_fsys_get_dir( ( DIRECTORY * ) dir ) );
/*START*/
}
/*
given an XinDirectory, this function sets the current directory.
*/
BOOLEAN
XinDirectoryCurrentSet( XinDirectory * dir )
{
/*END*/
return ( xvt_fsys_set_dir( ( DIRECTORY * ) dir ) );
/*START*/
}
/*
given an XinFileListSpec, this function returns the list of files that match the
spec.
*/
XinFileList *
XinFileListGet( XinFileListSpec * spec )
{
/*END*/
static XinFileList files = {0, NULL};
int num;
SLIST slist;
SLIST_ELT element;
char **p_file_name;
for ( num = 0; num < files.nbr_files; num++ )
XinMemoryFree( files.file_names[num] );
XinMemoryFree( files.file_names );
files.nbr_files = 0;
files.file_names = NULL;
if ( spec == NULL )
return NULL;
if ( ( slist = xvt_fsys_list_files( spec->dirs_only ? DIR_TYPE : spec->type,
spec->pattern, spec->include_dirs ) ) == NULL )
return NULL;
files.nbr_files = xvt_slist_count( slist );
files.file_names = XinMemoryAlloc( files.nbr_files * sizeof( char * ) );
p_file_name = files.file_names;
for ( element = xvt_slist_get_first( slist ); element != NULL;
element = xvt_slist_get_next( slist, element ), p_file_name++ )
{
long el_type;
char *text;
int len;
text = xvt_slist_get( slist, element, &el_type );
len = strlen( text ) + 1;
*p_file_name = XinMemoryAlloc( len );
memmove( *p_file_name, text, len );
}
xvt_slist_destroy( slist );
return &files;
/*START*/
}
static XinErrorHandler error_handler = NULL;
/*
the module using Xin calls this function when it encounters an error, and needs
to take some action. there are two possible states of severity:
XinSeverityWarning and XinSeverityFatal. if the severity is XinSeverityWarning,
then this function puts up a error message box. if the severity is
XinSeverityFatal, then this function puts up an error message box, then terminates
the application.
the module using Xin may set an error handler function by calling XinErrorHandlerSet.
if it does, then the new error handler is called. if the new error handler function
returns TRUE, then this function should terminate the application.
the following implementation is complete.
*/
void
XinError( int errcode, XinSeverity severity, long app_data )
{
BOOLEAN terminate = ( severity == XinSeverityFatal );
if ( error_handler != NULL )
terminate = ( *error_handler ) ( errcode, severity, app_data );
if ( terminate )
XinAppTerminate( );
}
/*
this function gets and returns the Xin error handling function.
*/
XinErrorHandler
XinErrorHandlerGet( void )
{
return error_handler;
}
/*
this function sets the Xin error handling function.
*/
void
XinErrorHandlerSet( XinErrorHandler handler )
{
error_handler = handler;
}
/*END*/
void
XinInitBuffer( )
{
if ( xin_buffer == NULL )
xin_buffer = XinMemoryAlloc( TEMP_BUFFER_SIZE );
}
void
XinIconSizeGet( int icon_rid, int *widthp, int *heightp )
{
NOREF( icon_rid );
*widthp = 32;
*heightp = 32;
}
#if XIWS == XIWS_WIN || XIWS == XIWS_PM
static struct
{
short xi_key;
short v_key;
BOOLEAN shift;
}
vk_table[] =
{
#if XIWS == XIWS_WIN
{
'\033', VK_ESCAPE, FALSE
},
{
XI_KEY_BTAB, VK_BACK, TRUE,
},
{
'\r', VK_RETURN, FALSE
},
{
XI_KEY_PREV, VK_PRIOR, FALSE
},
{
XI_KEY_NEXT, VK_NEXT, FALSE
},
#endif
#if XIWS == XIWS_PM
{
'\033', VK_ESC, FALSE
},
{
XI_KEY_BTAB, VK_BACKTAB, TRUE,
},
{
'\r', VK_ENTER, FALSE
},
{
XI_KEY_PREV, VK_PAGEUP, FALSE
},
{
XI_KEY_NEXT, VK_PAGEDOWN, FALSE
},
#endif
{
XI_KEY_DEL, VK_DELETE, FALSE
},
{
'\t', VK_TAB, FALSE
},
{
XI_KEY_END, VK_END, FALSE
},
{
XI_KEY_HOME, VK_HOME, FALSE
},
{
XI_KEY_LEFT, VK_LEFT, FALSE
},
{
XI_KEY_UP, VK_UP, FALSE
},
{
XI_KEY_RIGHT, VK_RIGHT, FALSE
},
{
XI_KEY_DOWN, VK_DOWN, FALSE
},
{
XI_KEY_F1, VK_F1, FALSE
},
{
XI_KEY_F2, VK_F2, FALSE
},
{
XI_KEY_F3, VK_F3, FALSE
},
{
XI_KEY_F4, VK_F4, FALSE
},
{
XI_KEY_F5, VK_F5, FALSE
},
{
XI_KEY_F6, VK_F6, FALSE
},
{
XI_KEY_F7, VK_F7, FALSE
},
{
XI_KEY_F8, VK_F8, FALSE
},
{
XI_KEY_F9, VK_F9, FALSE
},
{
XI_KEY_F10, VK_F10, FALSE
},
{
XI_KEY_F11, VK_F11, FALSE
},
{
XI_KEY_F12, VK_F12, FALSE
},
{
0, 0, FALSE
}
};
#endif
#if XIWS == XIWS_WIN
BOOLEAN XVT_CALLCONV1
xin_xvt_win_raw_event_hook( MSG * pmsg, HWND * phwnd )
{
NOREF( phwnd );
switch ( pmsg->message )
{
case WM_SYSKEYDOWN:
{
WindowInfo *ehlt;
ehlt = find_window_info_from_HWND( pmsg->hwnd );
if ( ehlt != NULL )
{
XinEvent event;
MEMCLEAR( event );
event.type = XinEventCharacter;
event.v.character.ch = pmsg->wParam & 0xff;
event.v.character.shift = FALSE;
event.v.character.control = FALSE;
event.v.character.alt = TRUE;
event.v.character.consumed = FALSE;
if ( event.v.character.ch != 18 )
{
int cnt;
for ( cnt = 0; vk_table[cnt].xi_key != 0; ++cnt )
{
if ( vk_table[cnt].v_key == event.v.character.ch )
{
event.v.character.ch = vk_table[cnt].xi_key;
event.v.character.shift = vk_table[cnt].shift;
break;
}
}
{
EVENT* old_cur_event = cur_xvt_event;
EVENT xvt_event;
xvt_event.v.chr.ch = pmsg->wParam & 0xff;
xvt_event.v.chr.shift = FALSE;
xvt_event.v.chr.control = FALSE;
cur_xvt_event = &xvt_event;
( *ehlt->event_handler ) ( ( XinWindow ) ehlt->win, &event );
cur_xvt_event = old_cur_event;
}
#if XVT_CHECK_VERSION(4, 50, 0)
return !event.v.character.consumed;
#else
return event.v.character.consumed;
#endif
}
}
break;
}
}
#if XVT_CHECK_VERSION(4, 50, 0)
return TRUE;
#else
return FALSE;
#endif
}
#endif
#if XIWS == XIWS_PM
BOOLEAN XVT_CALLCONV1
xin_xvt_pm_raw_event_hook( QMSG * pmsg )
{
if ( pmsg->msg == ( ULONG ) WM_CHAR &&
( ( ( USHORT ) SHORT1FROMMP( pmsg->mp1 ) & KC_ALT ) != 0 ) )
{
WindowInfo *ehlt;
ehlt = find_window_info_from_HWND( pmsg->hwnd );
if ( ehlt != NULL )
{
XinEvent event;
MEMCLEAR( event );
event.type = XinEventCharacter;
event.v.character.ch = LONGFROMMP( pmsg->mp2 );
event.v.character.shift = FALSE;
event.v.character.control = FALSE;
event.v.character.alt = TRUE;
event.v.character.consumed = FALSE;
if ( event.v.character.ch != 18 )
{
int cnt;
for ( cnt = 0; vk_table[cnt].xi_key != 0; ++cnt )
{
if ( vk_table[cnt].v_key == event.v.character.ch )
{
event.v.character.ch = vk_table[cnt].xi_key;
event.v.character.shift = vk_table[cnt].shift;
break;
}
}
{
EVENT xvt_event;
EVENT* old_cur_event = cur_xvt_event;
xvt_event.v.chr.ch = LONGFROMMP( pmsg->mp2 );
xvt_event.v.chr.shift = FALSE;
xvt_event.v.chr.control = FALSE;
cur_xvt_event = &xvt_event;
( *ehlt->event_handler ) ( ( XinWindow ) ehlt->win, &event );
cur_xvt_event = old_cur_event;
}
return !event.v.character.consumed;
}
}
}
return TRUE;
}
#endif
static char *xin_help_file_name = NULL;
/*START*/
/* Native help (only implemented on Windows - these calls do nothing elsewhere) */
void
XinHelpFileNameSet( char *filename )
{
/*END*/
if (xin_help_file_name != NULL)
XinMemoryFree( xin_help_file_name );
xin_help_file_name = (char *)XinMemoryAlloc( (strlen( filename ) + 1) * sizeof( char ) );
strcpy( xin_help_file_name, filename );
/*START*/
}
char *
XinHelpFileNameGet()
{
/*END*/
return xin_help_file_name;
/*START*/
}
/* This function only does anything on Windows. */
BOOLEAN
XinNativeHelp( XinWindow win, char *help_key )
{
/*END*/
#if XIWS == XIWS_WIN
if (xin_help_file_name != NULL && win != XI_NULL_WINDOW &&
help_key != NULL)
{
return WinHelp( (HWND)XinWindowNativeGet( win ), xin_help_file_name,
HELP_KEY, (long)help_key );
}
return FALSE;
#else
return FALSE;
#endif
}