utils.c

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

C
807
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <assert.h>
#include <ctype.h>
#include "winvi.h"
#include "color.h"
#include "font.h"
#include "utils.h"
#include "banner.h"
#include "aboutdlg.h"
#include "win.h"

/*
 * WriteText - write a length specified string to a window
 */
void WriteText( HWND hwnd, int x, int y, type_style *style, char * text, int len )
{
    HDC         hdc;
    #ifdef __WINDOWS_386__
        short   tab;
    #else
        int     tab;
    #endif

    if( len > 0 ){
        hdc = TextGetDC( hwnd, style );
        tab = FontTabWidth( style->font );
        TabbedTextOut( hdc, x, y, text, len, 1, &tab, 0 );
        TextReleaseDC( hwnd, hdc );
    }

} /* WriteText */

/*
 * WriteString - write a null delimited string to a window
 */
void WriteString( HWND hwnd, int x, int y, type_style *style, char *text )
{
    WriteText( hwnd, x, y, style, text, strlen( text ) );

} /* WriteString */

/*
 * TextGetDC - get the DC for a window, and set its properties
 */
HDC TextGetDC( HWND hwnd, type_style *style )
{
    HDC     hdc;

    hdc = GetDC( hwnd );
    SaveDC( hdc );
    SelectObject( hdc, FontHandle( style->font ) );
    // SelectObject( hdc, ColorPen( style->foreground ) );
    // SelectObject( hdc, ColorBrush( style->background ) );
    SetTextColor( hdc, ColorRGB( style->foreground ) );
    SetBkColor( hdc, ColorRGB( style->background ) );
    return( hdc );

} /* GetTextDC */

/*
 * TextReleaseDC - release the dc for a window
 */
void TextReleaseDC( HWND hwnd, HDC hdc )
{
    RestoreDC( hdc, -1 );
    ReleaseDC( hwnd, hdc );

} /* TextReleaseDC */

/*
 * BlankRectIndirect - blank out a rectangle given a pointer to the rectangle
 */
void BlankRectIndirect( HWND hwnd, UINT color, RECT *rect )
{
    HDC     hdc;

    hdc = GetDC( hwnd );
    FillRect( hdc, rect, ColorBrush( color ) );
    ReleaseDC( hwnd, hdc );

} /* BlankRectIndirect */

/*
 * BlankRect - blank out a rectangle given its coordinates
 */
void BlankRect( HWND hwnd, UINT color, int x1, int x2, int y1, int y2 )
{
    RECT    rect;

    rect.left = x1;
    rect.right = x2;
    rect.top = y1;
    rect.bottom = y2;
    BlankRectIndirect( hwnd, color, &rect );

} /* BlankRect */

/*
 * MyTextExtent - get the text extend of a string in a specified style
 */
int MyTextExtent( HWND hwnd, type_style *style, char *text, unsigned length )
{
    HDC         hdc;
    int         extent;
    unsigned    text_len, extra;
    int         font_width;
    #ifdef __WINDOWS_386__
        short   tab;
    #else
        int     tab;
    #endif

    hdc = TextGetDC( hwnd, style );
    font_width = FontAverageWidth( style->font );
    tab = FontTabWidth( style->font );
    text_len = strlen( text );
    extra = 0;
    if( length > text_len ) {
        extra = length - text_len - 1;
        length = text_len;
    }
    extent = LOWORD( GetTabbedTextExtent( hdc, text, length, 1, &tab ) );
    extent += extra * font_width;
    TextReleaseDC( hwnd, hdc );
    return( extent );

} /* MyTextExtent */

int MyStringExtent( HWND hwnd, type_style *style, char *text )
{
    return( MyTextExtent( hwnd, style, text, strlen( text ) ) );
}

/*
 * ClientToRowCol - Given an (x,y) in client coords inside an *EDIT* window,
 *                  fill in the row and col with the correct values (base 1).
 */
void ClientToRowCol( HWND hwnd, int x, int y, int *row, int *col, int divide )
{
    window      *w;
    dc          dc_line;
    ss_block    *ss, *ss_start, *ss_prev;
    int         startCols, intoCols;
    int         startPixel, lenBlock;
    int         intoExtent, difExtent;
    int         toleftExtent;
    int         avg_width;
    char        *str;

    w = WINDOW_FROM_ID( hwnd );
    *row = y / FontHeight( WIN_FONT( w ) ) + 1;

    if( x < 0 ) {
        *col = 1;
        return;
    }

    if( *row < 1 || *row > CurrentInfo->dc_size ) {
        *col = 0;
        return;
    }

    // get line data
    dc_line = DCFindLine( ( *row ) - 1, hwnd );
    if( dc_line->display != 0 ){
        // line needs to be displayed
        // therefore ss information has not been set!
        // therefore we cant use it to calculate anything of value!
        // best we can do is a good solid guess.
        avg_width = FontAverageWidth( WIN_FONT( w ) );
        *col = x/avg_width + 1;
        return;
    }
    assert( dc_line->valid );
    if( dc_line->start_col < LeftColumn ) {
        // entire line has been scrolled off to left - go to end of that line
        *col = 10000;
        return;
    }
    assert( dc_line->start_col == LeftColumn );
    ss_start = ss = dc_line->ss;

    // find which block x lies on
    while( ss->offset < x ) {
        // this could be the problem ?
        // will ss->offset always be valid
        // if not, this goes right off the end of the valid blocks
        ss++;
    }

    // Not needed anymore now we have slayed the dragon

#if 0
    if( (ss->type < 0) ||
        (ss ->type >= SE_NUMTYPES) ||
        (ss->end > BEYOND_TEXT ) ||
        (ss->len > BEYOND_TEXT )
        ){
        assert( 0 );
    }
#endif

    // grab info about this block
    if( ss != ss_start ) {
        ss_prev = ss - 1;
        startPixel = ss_prev->offset;
        startCols = ss_prev->end + 1;
        lenBlock = ss->end - ss_prev->end;
        str = dc_line->text + startCols;
    } else {
        startPixel = 0;
        startCols = 0;
        str = dc_line->text;
        lenBlock = ss->end + 1;
    }
    // lenBlock must be less than the length of the text
    // and greater than zero
    if( ss->end >= BEYOND_TEXT ) {
        lenBlock = strlen( str );
    }
    lenBlock = max( lenBlock, 0 );

    // avg_width must be greater than 0 (this probablly isn't needed but ...)
    avg_width = max( FontAverageWidth( SEType[ ss->type ].font ), 1 );

    if( EditFlags.RealTabs ){
        char    *start_str, *end_str;
        int     cur_pixel;
        linenum line_num = (linenum)(TopOfPage + *row - 1);
        line    *line;
        fcb     *fcb;
        int     i,v_pos;

        i = CGimmeLinePtr( line_num, &fcb, &line );
        if( i == ERR_NO_ERR ) {
            char *text = line->data;
            // get the tab boundries in this block

            #if 0
            v_pos = WinVirtualCursorPosition( text, startCols );
            if( v_pos < LeftColumn ){
                // block begins off left edge, advance forward to leftColumn
                int rp = WinRealCursorPosition( text, LeftColumn );
                start_str = text + rp;
                v_pos = LeftColumn;
                startPixel = 0;
                lenBlock -=( rp - startCols );
            }
            #else
            if( LeftColumn > 1 ){
                 // this only works for fixed fonts but its better than
                 // being wrong in every case; It's also correct
                 // immediately after every tab stop. And it should be
                 // at least close everywhere else :(
                 *col = x/avg_width + 1;
                 return;
            }
            #endif
            end_str = start_str = text + startCols;

            while( end_str != start_str + lenBlock ){
                if( *end_str == '\t' ){
                    cur_pixel = ( WinVirtualCursorPosition( text, end_str+1-text )
                               -LeftColumn )*avg_width;

                    if( cur_pixel > x ) {
                        // we've found the new boundries for the block.
                        // that do not contain any tabs!
                        break;
                    }
                    start_str = end_str + 1;
                    startPixel = cur_pixel;
                }
                end_str++;
            }
            // startCols are virtual# columns before the block
            v_pos = WinVirtualCursorPosition( text, start_str - text + 1 ) - 1;
            if(start_str == text+startCols ) {
                if( startCols != v_pos ){
                    startCols = v_pos - LeftColumn;
                }
            } else {
                startCols = v_pos - LeftColumn;
            }
            lenBlock = end_str - start_str;
            str = start_str;
        } /* else use the previous values */
    }

    // guess how far we are into block
    x -= startPixel;
    intoCols = x / avg_width;
    if( intoCols > lenBlock ) {
        intoCols = lenBlock;
    }

    // refine guess
    intoExtent = MyTextExtent( hwnd, &SEType[ss->type], str, intoCols );
    if( intoExtent > x ) {
        while( intoExtent > x ) {
            intoCols--;
            difExtent = intoExtent - MyTextExtent( hwnd, &SEType[ss->type], str, intoCols );
            intoExtent -= difExtent;
        }
        intoCols++;
        toleftExtent = intoExtent;
    } else {
        while( intoExtent <= x ) {
            intoCols++;
            toleftExtent = intoExtent;
            difExtent = MyTextExtent( hwnd, &SEType[ss->type], str, intoCols ) - intoExtent;
            intoExtent += difExtent;
        }
    }

    // fine-tune if have | cursor
    if( divide == DIVIDE_MIDDLE ) {
        if( ( x - toleftExtent ) > ( difExtent / 2 ) ) {
            intoCols++;
        }
    }

    *col = startCols + intoCols;

} /* ClientToRowCol */

/*
 * ToggleHourglass - turn the hourglass cursor on/off
 */
void ToggleHourglass( bool on )
{
    static int          isOn;
    static HCURSOR      lastCursor;
    static HCURSOR      waitCursor;

    if( !on ) {
        isOn--;
        if( isOn == 0 ) {
            SetCursor( lastCursor );
        }
    } else {
        if( waitCursor == NULL ) {
            waitCursor = LoadCursor( (HANDLE) NULL, IDC_WAIT );
        }
        lastCursor = SetCursor( waitCursor );
        isOn++;
    }

} /* ToggleHourglass */

long MemSize( void )
{
#ifndef __NT__
    return( GlobalCompact( 0 ) );
#else
    return( 0 );
#endif
}

char *GadgetString;

void SetGadgetString( char *str )
{
    AddString2( &GadgetString, str );
}

#ifdef __AXP__
extern void     delay(unsigned int __milliseconds);
#endif
void MyDelay( int ms )

⌨️ 快捷键说明

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