Files : Aggiunto il simbolo wxGTK per Linux git-svn-id: svn://10.65.10.50/trunk@12157 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			5841 lines
		
	
	
		
			150 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			5841 lines
		
	
	
		
			150 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 = ▭
 | 
						|
      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_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
      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_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR < 50
 | 
						|
          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_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
      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_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
      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_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
      }
 | 
						|
#endif
 | 
						|
      return win;
 | 
						|
    case XinWindowTypeButton:
 | 
						|
    case XinWindowTypeRadioButton:
 | 
						|
    case XinWindowTypeCheckBox:
 | 
						|
    case XinWindowTypeHorizontalScrollBar:
 | 
						|
    case XinWindowTypeVerticalScrollBar:
 | 
						|
      {
 | 
						|
        WIN_DEF ctl_def;
 | 
						|
 | 
						|
#if XVT_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
        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_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
        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_CROSS;
 | 
						|
  }
 | 
						|
  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
 | 
						|
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:
 | 
						|
#if XIWS == XIWS_WIN && XVT_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
      /* DRE 10/3/96 The +1 is because XVT mis-reports the widths. */
 | 
						|
      return xvt_vobj_get_attr( NULL_WIN, ATTR_DBLFRAME_HEIGHT ) + 1;
 | 
						|
#else
 | 
						|
      return xvt_vobj_get_attr( NULL_WIN, ATTR_DBLFRAME_HEIGHT );
 | 
						|
#endif
 | 
						|
    case XinMetricDoubleFrameWidth:
 | 
						|
#if XIWS == XIWS_WIN && XVT_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
      /* DRE 10/3/96 The +1 is because XVT mis-reports the widths. */
 | 
						|
      return xvt_vobj_get_attr( NULL_WIN, ATTR_DBLFRAME_WIDTH ) + 1;
 | 
						|
#else
 | 
						|
      return xvt_vobj_get_attr( NULL_WIN, ATTR_DBLFRAME_WIDTH );
 | 
						|
#endif
 | 
						|
    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( ¤t_dir ) )
 | 
						|
        return FALSE;
 | 
						|
      if ( !XinDirectoryCurrentGet( ¤t_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( ¤t_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_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
            return !event.v.character.consumed;
 | 
						|
#else
 | 
						|
            return event.v.character.consumed;
 | 
						|
#endif
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
  }
 | 
						|
#if XVT_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50
 | 
						|
  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
 | 
						|
}
 |