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