setvideo.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 865 行 · 第 1/2 页

C
865
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Video mode set processing.
*
****************************************************************************/


#include <conio.h>
#include "gdefn.h"
#include "gbios.h"
#include "montypes.h"

#ifdef __QNX__

#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/console.h>
#include <sys/dev.h>
#include <sys/kernel.h>

static struct _console_ctrl     *ConCtrl;
static unsigned                 old_hscroll;

static void HScrollOff()
{
    int                         h;

    if( ConCtrl == NULL ) {
        h = open( "//0/dev/con1", O_RDONLY );
        if( h != -1 ) {
            ConCtrl = console_open( h, O_RDWR );
            close( h );
        }
    }
    if( ConCtrl != NULL ) {
        old_hscroll = console_ctrl( ConCtrl, -1, CONSOLE_NOHSCROLL, CONSOLE_NOHSCROLL );
    }
}

static void HScrollRestore()
{
    if( ConCtrl != NULL ) {
        console_ctrl( ConCtrl, -1, old_hscroll, CONSOLE_NOHSCROLL );
    }
}

#endif // __QNX__


#if defined( _DEFAULT_WINDOWS )
    #undef HANDLE               // already defined by WPI
    #undef GLOBALHANDLE
    #include "win.h"
    #include <stdarg.h>
    #if defined( __OS2__ )
        #include "pmmenu.h"
    #endif

    WPI_PRES            _Mem_dc = NULL;
    HDC                 _Hdc;
    HBITMAP             _Mem_bmp = NULL;
    HWND                _CurrWin = NULL;
    extern HWND         _MainWindow;
    #if !defined( __OS2__ )
        extern HMENU    _SubMenuWindows;
    #else
        extern HWND     _GetWinMenuHandle();
    #endif
    extern void         _GetWindowNameAndCoords( char*, char*, int*, int*, int*, int*   );
    static LPWDATA _NewGphWindow( HWND hwnd, ... );
    static short _registergphclass( WPI_INST );

#else

extern gr_device _FARD  _TextDevice, _GrCGA_4, _GrCGA_6, _GrHGC_11,
                        _GrEGA_13, _GrEGA_14, _GrEGA_15, _GrEGA_16,
                        _GrVGA_17, _GrVGA_18, _GrVGA_19;
  #if defined( _SUPERVGA )
extern gr_device _FARD  _GrSVGA_100, _GrSVGA_102, _GrSVGA_103,
                        _GrSVGA_104, _GrSVGA_105;
  #endif


typedef struct supported_video_mode {
    short           mode;
    gr_device _FARD *dev;
} SUPP_MODE;


static SUPP_MODE        VideoModes[] = {
    _TEXTBW40,          &_TextDevice,
    _TEXTC40,           &_TextDevice,
    _TEXTBW80,          &_TextDevice,
    _TEXTC80,           &_TextDevice,
    _MRES4COLOR,        &_GrCGA_4,
    _MRESNOCOLOR,       &_GrCGA_4,
    _HRESBW,            &_GrCGA_6,
    _TEXTMONO,          &_TextDevice,
    _HERCMONO,          &_GrHGC_11,
    _MRES16COLOR,       &_GrEGA_13,
    _HRES16COLOR,       &_GrEGA_14,
    _ERESNOCOLOR,       &_GrEGA_15,
    _ERESCOLOR,         &_GrEGA_16,
    _VRES2COLOR,        &_GrVGA_17,
    _VRES16COLOR,       &_GrVGA_18,
    _MRES256COLOR,      &_GrVGA_19,
  #if defined( _SUPERVGA )
    0x100,              &_GrSVGA_100,
    0x101,              &_GrSVGA_100,
    0x102,              &_GrSVGA_102,
    0x103,              &_GrSVGA_103,
    0x104,              &_GrSVGA_104,
    0x105,              &_GrSVGA_105,
  #endif
    -1,                 NULL
};


static short            SelectMode( short );
#endif


static void SetTextInfo( void )
/*=======================

   This routine initializes the graphics text defaults. */

{
    short               height;
    short               width;

    /* Make the graphics text look the same on all devices. Take the
       width to height visual ratio to be 5:8 and assume that the
       width to height ratio of the physical dimensions of the screen
       is 4 : 3. The size is about 1.5 the size of BIOS text.   */

    height = ( _CurrState->vc.numypixels * 3 ) /
                                ( _CurrState->vc.numtextrows * 2 );
    width = ( (long) height * _CurrState->vc.numxpixels * 15 ) /    // 3 * 5
                ( (long) _CurrState->vc.numypixels * 32 );          // 4 * 8
    _setcharsize( height, width );
    _settextorient( 1, 0 );
    _settextpath( _PATH_RIGHT );
    _setcharspacing( 0 );
    _settextalign( _NORMAL, _NORMAL );
}


static void _InitVariables( void )
/*================================

   This routine initializes all of the global variables used by the
   graphics functions. */

{
    _CurrPos.xcoord = 0;                        /* initial position */
    _CurrPos.ycoord = 0;
    _LogOrg.xcoord = _CurrPos.xcoord;
    _LogOrg.ycoord = _CurrPos.ycoord;
    _CurrPos_w.wx = 0.0;
    _CurrPos_w.wy = 0.0;

    _Window.invert = TRUE;          /* window coordinates defaults  */
    _Window.xleft = 0.0;
    _Window.ybottom = 0.0;
    _Window.xright = 1.0;
    _Window.ytop = 1.0;

    _CurrState->clip_def.xmin = 0;               /* graphics window */
    _CurrState->clip_def.xmax = _CurrState->vc.numxpixels - 1;
    _CurrState->clip_def.ymin = 0;
    _CurrState->clip_def.ymax = _CurrState->vc.numypixels - 1;
    _setclip( _GCLIPON );

    _TextPos.row = 0;                   /* BIOS text cursor position    */
    _TextPos.col = 0;
    _Tx_Row_Min = 0;                            /* text window */
    _Tx_Row_Max = _CurrState->vc.numtextrows - 1;
    _Tx_Col_Min = 0;
    _Tx_Col_Max = _CurrState->vc.numtextcols - 1;
    if( _GrMode ) {
        SetTextInfo();
    }

    memcpy( _FillMask, _DefMask, MASK_LEN );    /* solid fill */
    _HaveMask = 0;                              /* no fill mask set */
    _PaRf_x = 0;                                /* fill pattern    */
    _PaRf_y = 0;                                /* reference point */

    _CharAttr = _DEFAULT_ATTR;
    _CurrColor = ( _CurrState->vc.numcolors - 1 ) & 15;
    _CurrBkColor = 0;
    _CurrActivePage = _CurrVisualPage = 0;
    _CurrState->screen_seg = _CurrState->screen_seg_base;/* pg 0 scrn segment */
    _CurrState->screen_off = _CurrState->screen_off_base;/* pg 0 scrn offset */
    _LineStyle = 0xFFFF;                        /* solid line */
    _StyleWrap = 0;                             /* line style continuation  */
    _PlotAct = 0;                               /* replace mode */
    _Transparent = 1;                           /* transparent mode */
    _Wrap = 1;                                  /* wrapping on */
}


short _WCI86FAR _CGRAPH _setvideomode( short req_mode )
/*================================================

   This routine sets the video mode if it is supported by the current
   hardware configuration. It returns the number of text rows if
   successful, otherwise it returns 0.  */

{
#if defined( _DEFAULT_WINDOWS )
    WPI_INST            Inst;
    HWND                Win;
    WPI_PRES            Win_DC;
    WPI_RECT            rect;
    WPI_TEXTMETRIC      fntinfo;
    HMENU               menu;
    HFONT               old_font;
    LPWDATA             w;
    char*               name = "\0";
    char                dest[80];
    long                x, y;
    int                 x1, y1, x2, y2;
    short               clipy1, clipy2;
    WPI_RECTDIM         right, bottom, height;
  #if defined( __OS2__ )
    ULONG               style;
    HWND                frame;
    MENUITEM            gphmenu;
  #endif
#else
    short               mode;
    short               prev_mode;
#ifdef __QNX__
    int                 wasTextMode;
#endif
    SUPP_MODE           *tab;
    gr_device _FARD     *prev_dev;
    gr_device _FARD     *dev_ptr;
#endif

    _ErrorStatus = _GROK;
    _InitState();
#if defined( _DEFAULT_WINDOWS )
    Win = 0;
  #if defined( __OS2__ )
    Inst.hab = WinQueryAnchorBlock( _MainWindow );
    Inst.mod_handle = NULL;
  #else
    Inst = GetWindowWord( _MainWindow, GWW_HINSTANCE );
  #endif
    _SetInst( &Inst );
    if( !_registergphclass( Inst ) ) {
        _ErrorStatus = _GRMODENOTSUPPORTED;
        return( 0 );
    }
    x = _wpi_getsystemmetrics( SM_CXSCREEN );
    y = _wpi_getsystemmetrics( SM_CYSCREEN );

    _SetPresHeight( y );

    if( req_mode == 0 ) {
        _ErrorStatus = _GRMODENOTSUPPORTED;
        return( 0 );
    } else if( _CurrWin ){
    // Make sure we don't create more than 1 window, and know when to close it
        if( req_mode == _DEFAULTMODE ) {
  #if defined( __OS2__ )
                w = _GetWindowData( _CurrWin );
                Win =  w->frame;
  #else
                Win = _CurrWin;
  #endif
                _wpi_destroywindow( Win );
                return( _CurrState->vc.numtextrows );
        } else {
            // if we are only changing moods, we will reinitialize everything
            _clearscreen( _GCLEARSCREEN );
            init_memdc_bk( x, y );
            init_all();
            _wpi_updatewindow( Win );
            return( _CurrState->vc.numtextrows );
        }
    }
    // Create a new window

    // Get the name and coordinates of the window
    name = "Graphics";
    _GetWindowNameAndCoords( name, dest, &x1, &x2, &y1, &y2 );

  #if defined( __OS2__ )
    style = FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER | FCF_MINMAX |
            FCF_VERTSCROLL | FCF_HORZSCROLL;
    frame = WinCreateStdWindow( _MainWindow,
                WS_VISIBLE | WS_CLIPSIBLINGS,
                &style, "GraphWndClass", dest, 0, NULL, 0, &Win );
    if( frame == 0 ) return( FALSE );
    WinSetOwner( Win, _MainWindow );
    _OldFrameProc = WinSubclassWindow( frame, GraphFrameProc );
  #else
    Win = CreateWindow( "GraphWndClass", dest,
                        WS_CHILD |
                        WS_CAPTION | WS_THICKFRAME |
                        WS_CLIPSIBLINGS | WS_SYSMENU |
                        WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
                        0,  0,
                        0,  0,
                        _MainWindow, NULL,
                        Inst, NULL );
    if( !Win ) return( FALSE );
  #endif

    _CurrWin = Win;
    Win_DC = _wpi_getpres( Win );

    // Create the memory dc
    _Mem_dc = _wpi_createcompatiblepres( Win_DC, Inst, &_Hdc );
    if( !_Mem_dc ){
        _ErrorStatus = _GRMODENOTSUPPORTED;
        _wpi_destroywindow( _CurrWin );
        return( 0 );
    }

    // Create the bitmap to draw on
    _Mem_bmp = _wpi_createcompatiblebitmap( Win_DC, x,y );
    if( !_Mem_bmp ){
        _ErrorStatus = _GRMODENOTSUPPORTED;
        _wpi_destroywindow( _CurrWin );
        return( 0 );
    }

    _wpi_torgbmode( _Mem_dc );
    _wpi_torgbmode( Win_DC );

    _wpi_selectbitmap( _Mem_dc, _Mem_bmp );
    _wpi_releasepres( Win, Win_DC );

    _CurrState->vc.mode = Win;

    w = _NewGphWindow( Win, 9999, -1 );

    // initialize variables, memory device, etc.
    if( !_CreateSysMonoFnt( _Mem_dc ) ) {
        _ErrorStatus = _GRMODENOTSUPPORTED;
        return( 0 );
    }
    init_memdc_bk( x, y );
    init_all();
                        /* Initialize clipping regions */
    clipy1 = _wpi_cvth_y( _CurrState->clip_def.ymin, _GetPresHeight() );
    clipy2 = _wpi_cvth_y( _CurrState->clip_def.ymax, _GetPresHeight() );
    _wpi_setintwrectvalues( &rect, _CurrState->clip_def.xmin,
                                   clipy1,
                                   _CurrState->clip_def.xmax,
                                   clipy2 );
    _ClipRgn = _wpi_createrectrgn( _Mem_dc, &rect );
    _wpi_selectcliprgn( _Mem_dc, _ClipRgn );

  #if defined( __OS2__ )
    GpiDeleteSetId( _Mem_dc, LCID_DEFAULT );
    _CurFnt = LCID_DEFAULT;
  #else
    _CurFnt = GetStockObject( SYSTEM_FONT );
  #endif
    old_font = _MySelectFont( _Mem_dc, _CurFnt );
    _wpi_gettextmetrics( _Mem_dc, &fntinfo );

  #if defined( __OS2__ )
    w->frame = frame;
    menu = _GetWinMenuHandle();
  #else
    w->inst = Inst;
    menu = _SubMenuWindows;
  #endif

    _wpi_getclientrect( _MainWindow, &rect );
    height = _wpi_getheightrect( rect );

    // Calculate where to put the window and how big it should be
    x2 -= x1;
    y2 -= y1;
    x1 *= _wpi_metricmaxcharwidth( fntinfo );
    y1 *= _wpi_metricheight( fntinfo );
    x2 *= _wpi_metricmaxcharwidth( fntinfo );
    y2 *= _wpi_metricheight( fntinfo );
    w->xchar = _wpi_metricmaxcharwidth( fntinfo );
    w->ychar = _wpi_metricheight( fntinfo );
    _wpi_getrectvalues( rect, NULL, NULL, &right, &bottom );
    if( ( x1 < 0 ) || ( x1 >= right ) ) {
        x1 = 0;
    }
    if( ( y1 < 0 ) || ( y1 >= bottom ) ) {
        y1 = 0;
    }
    if( ( x2 <= 0 ) || ( x2 >= right ) ) {
        x2 = right - x1;
    }
    if( ( y2 <= 0 ) || ( y2 >= bottom ) ) {
        y2 = bottom - y1;
    }
  #if defined( __OS2__ )
    WinSendMsg( frame, WM_SETICON,
        MPFROMLONG( WinQuerySysPointer( HWND_DESKTOP, SPTR_APPICON, TRUE ) ), 0 );
    WinSetWindowPos( frame,
                     HWND_TOP,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?