www.pudn.com > MicroWindows-Source-200606.zip > lowgdi.c


/***************************************************************************** 
 * 
 * Lowgdi.c: 低階繪圖介面 
 * 
 ****************************************************************************/ 
 
#include  
#include "lowgdi.h" 
extern char engfont[1920]; 
 
/* useful macros */ 
#define _lgVideoCall(a, b, c, d)    _DX=d; _CX=c; _BX=b; _AX=a; \ 
                                    geninterrupt(0x10); 
#define _lgMouseCall(a, b, c, d)    _DX=d; _CX=c; _BX=b; _AX=a; \ 
                                    geninterrupt(0x33); 
#define _lgOutportb(a, b)           outportb(a, b) 
#define _lgAL                       _AL 
#define _lgBL                       _BL 
#define _lgAX                       _AX 
#define _lgBX                       _BX 
#define _lgCX                       _CX 
#define _lgDX                       _DX 
 
/* global variables */ 
int     _lgClipX1 = 0, _lgClipY1 = 0, _lgClipX2 = 639, _lgClipY2 = 479; 
BOOL    _lgClipOut = FALSE; 
int     _lgRX1 = 0, _lgRY1 = 0, _lgRX2 = 0, _lgRY2 = 0; 
int     _lgScreenWidth = 640, _lgScreenHeight = 480; 
int     _lgColor = LG_WHITE, _lgBgColor = LG_BLACK; 
BOOL    _lgXOR = FALSE; 
int     _lgYaddr[500]; 
BYTE far *_lgDBitmap = (BYTE far*)0xa0000000; 
BYTE    _lgMask[8]      ={0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1}; 
BYTE    _lgLeftMask[8]  ={0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; 
BYTE    _lgRightMask[8] ={0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; 
BYTE    _lgBitPlane [8] ={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; 
BOOL    _lgMouseActive = TRUE, _lgCursorTempHide = FALSE; 
BYTE    _lgMSavedImage[256]; 
int     _lgMLastX = 0, _lgMLastY = 0, _lgMButton = 0; 
BOOL    _lgMLButtonHitted = FALSE; 
BOOL    _lgMouseHided = FALSE; 
 
BYTE _lgMScreenMask[32]= 
{ 
    0x3f, 0xff, 0x1f, 0xff, 0x0f, 0xff, 0x07, 0xff, 0x03, 0xff, 
    0x01, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0x1f, 
    0x01, 0xff, 0x10, 0xff, 0x30, 0xff, 0xf8, 0x7f, 0xf8, 0x7f, 
    0xfc, 0x3f 
}; 
 
BYTE _lgMCursorMask[32]= 
{ 
    0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 
    0x7c, 0x00, 0x7e, 0x00, 0x7f, 0x00, 0x7f, 0x80, 0x7f, 0xc0, 
    0x7c, 0x00, 0x46, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 
    0x00, 0x00 
}; 
 
#define _lgClipAccept(a, b)     (a|b) 
#define _lgClipReject(a, b)     (a&b) 
#define _lgClipTop              0x08 
#define _lgClipBottom           0x04 
#define _lgClipRight            0x02 
#define _lgClipLeft             0x01 
#define _lgClipInside           0x00 
 
void _lgLineClipper(int x1, int y1, int x2, int y2); 
void _lgRectClipper(int x1, int y1, int x2, int y2); 
int  _lgClipOutcode(int x , int y); 
void _lgHline (int x1, int x2, int y); 
void _lgVline (int x, int y1, int y2); 
void _lgDisplayCursor (void); 
void _lgUpdateMouse (void); 
void _lgMouseTempHide (int x1, int y1, int x2, int y2); 
void _lgMouseTempShow (void); 
void _lgMSaveBack (void); 
void _lgMRestoreBack (void); 
void _lgLowPoint (int x, int y); 
 
BOOL    _lgOpenGraphics() 
{ 
    int i; 
 
    _lgVideoCall (0x101a, 0xffff, 0, 0);    /* detect if VGA exists */ 
    if (_lgBX==0xffff) return (FALSE);      /* VGA not exists! */ 
 
    _lgVideoCall (0x12, 0, 0, 0); 
    for (i=0; i<500; i++) _lgYaddr[i]=80 * i; 
 
    /* set write mode 2 */ 
    _lgOutportb (0x3ce, 5); 
    _lgOutportb (0x3cf, 2); 
 
    /* set pen normal */ 
    _lgOutportb (0x3ce, 3); 
    _lgOutportb (0x3cf, 0); 
 
    /* initial the mouse */ 
    _lgMouseCall (0, 0, 0, 0); 
    if (!_lgAX) 
    { 
        _lgMouseActive=FALSE; 
        return (TRUE); 
    } 
     
    _lgMouseCall (2, 0, 0, 0);      /* disable the text cursor */ 
    _lgMouseCall (4, 0, _lgScreenWidth/2, _lgScreenHeight/2);  /* centerize */ 
    _lgMouseCall (7, 0, 0, _lgScreenWidth-1);   /* set X range */ 
    _lgMouseCall (8, 0, 0, _lgScreenHeight-1);  /* set Y range */ 
    _lgMSaveBack(); 
    _lgDisplayCursor(); 
 
    return (TRUE); 
} 
 
BOOL    _lgCloseGraphics() 
{ 
    /* return to VGA colored text mode 80x25 */ 
    _lgVideoCall (0x03, 0, 0, 0); 
 
    if (_lgMouseActive == TRUE) 
    { 
        _lgMouseCall (0x31, 0, 0, 0);       /* deinitial the mouse */ 
    } 
 
    return (TRUE); 
} 
 
void    _lgRect     (int x1, int y1, int x2, int y2) 
{ 
    _lgLine (x1, y1, x2, y1); 
    _lgLine (x1, y2, x2, y2); 
    _lgLine (x1, y1, x1, y2); 
    _lgLine (x2, y1, x2, y2); 
} 
 
void    _lgPoint    (int x, int y) 
{ 
    unsigned addr=_lgYaddr[y] + (x >> 3); 
    BYTE mask = _lgMask[x & 7]; 
 
    if (x<_lgClipX1 || y<_lgClipY1 || x>_lgClipX2 || y>_lgClipY2) return; 
 
    _lgMouseTempHide (x, y, x, y); 
    _lgOutportb (0x3ce, 8);         /* setup latch register */ 
    _lgOutportb (0x3cf, mask); 
    mask=*(_lgDBitmap+addr); 
    *(_lgDBitmap+addr)=_lgColor; 
    _lgMouseTempShow (); 
} 
 
void    _lgLowPoint (int x, int y) 
{ 
    unsigned addr=_lgYaddr[y] + (x >> 3); 
    BYTE mask = _lgMask[x & 7]; 
    _lgOutportb (0x3ce, 8);         /* setup latch register */ 
    _lgOutportb (0x3cf, mask); 
    mask=*(_lgDBitmap+addr); 
    *(_lgDBitmap+addr)=_lgColor; 
} 
 
void    _lgLine     (int x1, int y1, int x2, int y2) 
{ 
    int dx, dy, i, e, incx, incy, inc1, inc2, x, y, tmp; 
 
    _lgLineClipper (x1, y1, x2, y2); 
    if (_lgClipOut) return; 
    _lgMouseTempHide (_lgRX1, _lgRY1, _lgRX2, _lgRY2); 
 
    if (_lgRX1==_lgRX2) 
    { 
        if (_lgRY1 > _lgRY2) 
        { 
            tmp=_lgRY2; 
            _lgRY2=_lgRY1; 
            _lgRY1=tmp; 
        } 
 
        _lgVline (_lgRX1, _lgRY1, _lgRY2); 
    } 
    else if (_lgRY1==_lgRY2) 
    { 
        if (_lgRX1 > _lgRX2) 
        { 
            tmp=_lgRX2; 
            _lgRX2=_lgRX1; 
            _lgRX1=tmp; 
        } 
 
        _lgHline (_lgRX1, _lgRX2, _lgRY1); 
    } 
    else 
    { 
 
        dx=_lgRX2-_lgRX1; 
        dy=_lgRY2-_lgRY1; 
 
        if (dx<0) dx=-dx; 
        if (dy<0) dy=-dy; 
 
        if (x2 dy) 
        { 
            _lgLowPoint (x, y); 
 
            e       = 2* dy - dx; 
            inc1    = 2* (dy-dx); 
            inc2    = 2* dy; 
 
            for (i=0; i=0) 
                { 
                    y+=incy; 
                    e+=inc1; 
                } 
                else e+=inc2; 
 
                x+=incx; 
                _lgLowPoint (x, y); 
            } 
        } 
        else 
        { 
            _lgLowPoint (x, y); 
            e       = 2* dx - dy; 
            inc1    = 2* (dx-dy); 
            inc2    = 2* dx; 
 
            for (i=0; i=0) 
                { 
                    x+=incx; 
                    e+=inc1; 
                } 
                else e+=inc2; 
 
                y+=incy; 
                _lgLowPoint (x, y); 
            } 
        } 
    } 
 
    _lgMouseTempShow(); 
} 
 
void    _lgSolidRect(int x1, int y1, int x2, int y2) 
{ 
    int y; 
 
    _lgRectClipper (x1, y1, x2, y2); 
    if (_lgClipOut) return; 
    _lgMouseTempHide (_lgRX1, _lgRY1, _lgRX2, _lgRY2); 
 
    for (y=_lgRY1; y<=_lgRY2; y++) 
    { 
        _lgHline (_lgRX1, _lgRX2, y); 
    } 
 
    _lgMouseTempShow(); 
} 
 
void _lgDrawText (int x, int y, char *text) 
{ 
    int i, l = strlen (text), xc = x; 
    char *fontptr; 
 
    _lgRectClipper (x, y, x + l*8 - 1, y + 14); 
    if (_lgClipOut) return; 
    _lgMouseTempHide (_lgRX1, _lgRY1, _lgRX2, _lgRY2); 
 
    for (i = 0; i < l; i++, xc += 8) 
    { 
        if ((unsigned)*text > 127) continue;      /* high-byte char omitted */ 
        fontptr = engfont + (*text++) * 15; 
        _lgPutFont (fontptr, xc, y, 8, 15); 
    } 
 
    _lgMouseTempShow(); 
} 
 
 
 
void _lgHline (int x1, int x2, int y) 
{ 
    register unsigned int i; 
    unsigned int addr=_lgYaddr[y], startx, endx; 
    static BYTE mask; 
 
    startx=x1 >> 3; 
    endx  =x2 >> 3; 
 
    _lgOutportb (0x3ce, 8); 
 
    if (startx==endx) 
    { 
 
        if (x2 & 7) mask=_lgLeftMask[x1 & 7] & _lgRightMask[x2 & 7]; 
        else mask=_lgLeftMask[x1 & 7]; 
        _lgOutportb (0x3cf, mask); 
        addr+=startx; 
        mask=*(_lgDBitmap+addr); 
        *(_lgDBitmap+addr)=_lgColor; 
    } 
    else 
    { 
        /* draw the left side */ 
        addr+=startx; 
        mask=_lgLeftMask[x1 & 7]; 
        _lgOutportb (0x3cf, mask); 
 
        mask=*(_lgDBitmap+addr); 
        *(_lgDBitmap+addr)=_lgColor; 
 
        _lgOutportb (0x3cf, 0xff); 
        for (i=startx+1; i> 3); 
        tmp = *(_lgDBitmap + addr); 
        *(_lgDBitmap+addr)=_lgColor; 
    } 
 
    if (tmp) ; 
} 
 
 
int     _lgGetScreenWidth() 
{ 
    return (_lgScreenWidth); 
} 
 
int     _lgGetScreenHeight() 
{ 
    return (_lgScreenHeight); 
} 
 
int     _lgGetColor () 
{ 
    return (_lgColor); 
} 
 
int     _lgGetBgColor () 
{ 
    return (_lgBgColor); 
} 
 
BOOL    _lgGetXOR () 
{ 
    return (_lgXOR); 
} 
 
BOOL _lgIsMouseActive() 
{ 
    return (_lgMouseActive); 
} 
 
void    _lgSetColor (int c) 
{ 
    _lgColor = c; 
} 
 
void    _lgSetBgColor (int c) 
{ 
    _lgBgColor = c; 
} 
 
void    _lgSetXOR (BOOL xor) 
{ 
    _lgXOR = xor; 
    if (xor == TRUE) 
    { 
        _lgOutportb (0x3ce, 3); 
        _lgOutportb (0x3cf, 0x18); 
    } 
    else 
    { 
        _lgOutportb (0x3ce, 3); 
        _lgOutportb (0x3cf, 0); 
    } 
} 
 
void    _lgResetClipping() 
{ 
    _lgSetClippingRect (0, 0, _lgScreenWidth-1, _lgScreenHeight-1); 
} 
 
void    _lgSetClippingRect(int x1, int y1, int x2, int y2) 
{ 
    int x3, y3, x4, y4; 
 
    /* swapping */ 
    x3=x1x2 ? x1:x2; 
    y3=y1y2 ? y1:y2; 
 
    if (x3 < 0) x3 = 0; 
    if (y3 < 0) y3 = 0; 
    if (x4 < 0) x4 = 0; 
    if (y4 < 0) y4 = 0; 
 
    if (x3 > _lgScreenWidth-1)     x3=_lgScreenWidth-1; 
    if (y3 > _lgScreenHeight-1)    y3=_lgScreenHeight-1; 
    if (x4 > _lgScreenWidth-1)     x4=_lgScreenWidth-1; 
    if (y4 > _lgScreenHeight-1)    y4=_lgScreenHeight-1; 
 
    _lgClipX1=x3; 
    _lgClipY1=y3; 
    _lgClipX2=x4; 
    _lgClipY2=y4; 
} 
 
void _lgMSaveBack() 
{ 
    BOOL xor = _lgXOR; 
    if (_lgMouseHided || _lgCursorTempHide) return; 
 
    _lgSetXOR (FALSE); 
    _lgGetImage (_lgMSavedImage, _lgMLastX, _lgMLastY, 
                                 _lgMLastX+15, _lgMLastY+15); 
    _lgSetXOR (xor); 
} 
 
void _lgMRestoreBack() 
{ 
    BOOL xor = _lgXOR; 
    if (_lgMouseHided || _lgCursorTempHide) return; 
 
    _lgSetXOR (FALSE); 
    _lgPutImage (_lgMSavedImage, _lgMLastX, _lgMLastY, 
                                 _lgMLastX+15, _lgMLastY+15); 
    _lgSetXOR (xor); 
} 
 
void _lgDisplayCursor () 
{ 
    int bc=_lgColor, bgc=_lgBgColor; 
    int bcx1=_lgClipX1, bcx2=_lgClipX2, bcy1=_lgClipY1, bcy2=_lgClipY2; 
 
    if (_lgMouseHided || _lgCursorTempHide) return; 
 
    _lgResetClipping(); 
 
    _lgOutportb (0x3ce, 3); 
    _lgOutportb (0x3cf, 0x08);          /* AND pen */ 
    _lgSetColor (LG_WHITE); 
    _lgSetBgColor (LG_BLACK); 
    _lgPutFont (_lgMScreenMask, _lgMLastX, _lgMLastY, 16, 16); 
    _lgOutportb (0x3ce, 3); 
    _lgOutportb (0x3cf, 0x10);          /* OR pen */ 
    _lgPutFont (_lgMCursorMask, _lgMLastX, _lgMLastY, 16, 16); 
    _lgSetColor   (bc); 
    _lgSetBgColor (bgc); 
    _lgSetXOR (_lgXOR);                 /* restore pen mode */ 
 
    _lgClipX1=bcx1; _lgClipY1=bcy1; 
    _lgClipX2=bcx2; _lgClipY2=bcy2; 
} 
 
BYTE _lgGetMouseButton () 
{ 
    _lgUpdateMouse(); 
 
    if (_lgMLButtonHitted == TRUE && _lgMButton == LGM_BUTTONUP) 
    { 
        _lgMLButtonHitted = FALSE; 
    } 
 
    return (_lgMButton); 
} 
 
int  _lgGetMouseX () 
{ 
    _lgUpdateMouse(); 
    return (_lgMLastX); 
} 
 
int  _lgGetMouseY () 
{ 
    _lgUpdateMouse(); 
    return (_lgMLastY); 
} 
 
void _lgMouseTempHide(int x1, int y1, int x2, int y2) 
{ 
    int bcx1=_lgClipX1, bcx2=_lgClipX2, bcy1=_lgClipY1, bcy2=_lgClipY2; 
    int oca, ocb; 
    BOOL hide = FALSE; 
 
    if (_lgMouseActive == FALSE) return; 
    if (_lgCursorTempHide || _lgMouseHided) return; 
 
    if (x1==-1 && y1==-1) 
    { 
        hide = TRUE; 
    } 
    else 
    { 
        _lgClipX1=x1-8; 
        _lgClipY1=y1-4; 
        _lgClipX2=x2+8; 
        _lgClipY2=y2+4; 
 
        oca=_lgClipOutcode (_lgMLastX, _lgMLastY); 
        ocb=_lgClipOutcode (_lgMLastX+16, _lgMLastY+16); 
 
        if (_lgClipAccept(oca, ocb)) 
        { 
            if (!_lgClipReject (oca, ocb)) hide = TRUE; 
        } 
        else 
        { 
            hide = TRUE; 
        } 
    } 
 
    if (hide == TRUE) 
    { 
        _lgMRestoreBack(); 
        _lgCursorTempHide=TRUE; 
    } 
 
    _lgClipX1=bcx1; 
    _lgClipY1=bcy1; 
    _lgClipX2=bcx2; 
    _lgClipY2=bcy2; 
} 
 
void _lgMouseTempShow() 
{ 
    if (_lgMouseHided) return; 
 
    if (_lgCursorTempHide==TRUE) 
    { 
        _lgCursorTempHide=FALSE; 
        _lgMSaveBack(); 
        _lgDisplayCursor(); 
    } 
} 
 
void _lgUpdateMouse () 
{ 
    int     x, y, state; 
 
    if (_lgMouseActive == FALSE) return; 
 
    _lgMouseCall (3, 0, 0, 0); 
    x     = _lgCX; 
    y     = _lgDX; 
    state = _lgBX; 
 
    if (x!=_lgMLastX || y!=_lgMLastY)   /* mouse moved */ 
    { 
        _lgMRestoreBack(); 
        _lgMLastX  = x; 
        _lgMLastY  = y; 
        _lgMSaveBack(); 
        _lgDisplayCursor(); 
    } 
 
    _lgMButton = LGM_MOVE; 
 
    if (state & 1)          /* 1 = LBUTTON_DOWN */ 
    { 
        if (_lgMLButtonHitted == TRUE) 
        { 
            _lgMButton = LGM_DRAG; 
        } 
        else 
        { 
            _lgMButton = LGM_BUTTONDOWN; 
        } 
 
        _lgMLButtonHitted = TRUE; 
    } 
    else 
    { 
        if (_lgMLButtonHitted == TRUE) 
        { 
            _lgMButton = LGM_BUTTONUP; 
        } 
    } 
} 
 
void _lgLineClipper(int x1, int y1, int x2, int y2) 
{ 
    int  tmp; 
    int  outcode1=_lgClipOutcode(x1, y1), outcode2=_lgClipOutcode(x2, y2); 
    int  x3, y3, x4, y4, swap=0; 
    long buf, dx, dy; 
 
    _lgClipOut=1; 
 
    while (_lgClipAccept(outcode1, outcode2)) 
    { 
        if (_lgClipReject (outcode1, outcode2)) break; 
        if (outcode1==_lgClipInside) 
        { 
            tmp=x2; x2=x1; x1=tmp; 
            tmp=y2; y2=y1; y1=tmp; 
            tmp=outcode2; outcode2=outcode1; outcode1=tmp; 
            swap=1; 
        } 
 
        dx=x2-x1; 
        dy=y2-y1; 
 
        if (outcode1 & _lgClipTop) 
        { 
            if (dy) buf=dx*(long)(_lgClipY1-y1)/dy; 
            x1+=buf; 
            y1 =_lgClipY1; 
        } 
        else if (outcode1 & _lgClipBottom) 
        { 
            if (dy) buf=dx*(long)(_lgClipY2-y1)/dy; 
            x1+=buf; 
            y1 =_lgClipY2; 
        } 
        else if (outcode1 & _lgClipRight) 
        { 
            if (dx) buf=dy*(long)(_lgClipX2-x1)/dx; 
            y1+=buf; 
            x1 =_lgClipX2; 
        } 
        else if (outcode1 & _lgClipLeft) 
        { 
            if (dx) buf=dy*(long)(_lgClipX1-x1)/dx; 
            y1+=buf; 
            x1 =_lgClipX1; 
        } 
        outcode1=_lgClipOutcode(x1, y1); 
    } 
 
    if (!_lgClipAccept(outcode1, outcode2)) 
    { 
        if (swap) 
        { 
            _lgRX1=x2; 
            _lgRY1=y2; 
            _lgRX2=x1; 
            _lgRY2=y1; 
        } 
        else 
        { 
            _lgRX1=x1; 
            _lgRY1=y1; 
            _lgRX2=x2; 
            _lgRY2=y2; 
        } 
        _lgClipOut=0;   /* still a drawable line */ 
    } 
} 
 
void _lgRectClipper(int x1, int y1, int x2, int y2) 
{ 
    int tmp; 
    int outcode1=_lgClipOutcode(x1, y1), outcode2=_lgClipOutcode(x2, y2); 
    int x3, y3, x4, y4; 
 
    _lgClipOut=1; 
    while (_lgClipAccept(outcode1, outcode2)) 
    { 
        if (_lgClipReject (outcode1, outcode2)) break; 
        if (outcode1==_lgClipInside) 
        { 
            tmp=x2; x2=x1; x1=tmp; 
            tmp=y2; y2=y1; y1=tmp; 
            tmp=outcode2; outcode2=outcode1; outcode1=tmp; 
        } 
 
        if (outcode1 & _lgClipTop) 
        { 
            y1 =_lgClipY1; 
        } 
        else if (outcode1 & _lgClipBottom) 
        { 
            y1 =_lgClipY2; 
        } 
        else if (outcode1 & _lgClipRight) 
        { 
            x1 =_lgClipX2; 
        } 
        else if (outcode1 & _lgClipLeft) 
        { 
            x1 =_lgClipX1; 
        } 
        outcode1=_lgClipOutcode(x1, y1); 
    } 
 
    if (!_lgClipAccept(outcode1, outcode2)) 
    { 
        x3=x1; x4=x2; y3=y1; y4=y2; 
        if (x1>x2) 
        { 
            x3=x2; 
            x4=x1; 
        } 
        if (y1>y2) 
        { 
            y3=y2; 
            y4=y1; 
        } 
 
        _lgRX1=x3; 
        _lgRY1=y3; 
        _lgRX2=x4; 
        _lgRY2=y4; 
        _lgClipOut=0; 
    } 
} 
 
/********************************************************** 
 * 
 *      1001 | 1000 | 1010 
 *     ------+------+------ 
 *      0001 | 0000 | 0010      Cohen-Sutherland's outcode 
 *     ------+------+------ 
 *      0101 | 0100 | 0110 
 * 
 *********************************************************/ 
 
int  _lgClipOutcode(int x , int y) 
{ 
    int out; 
    if (y<_lgClipY1) out=_lgClipTop; 
    else if (y>_lgClipY2) out=_lgClipBottom; 
    else out=_lgClipInside; 
 
    if (x<_lgClipX1) out|=_lgClipLeft; 
    else if (x>_lgClipX2) out|=_lgClipRight; 
 
    return (out); 
} 
 
void    _lgGetImage (char *image, int x1, int y1, int x2, int y2) 
{ 
    register int xc, yc; 
    int x3, x4; 
    unsigned int yaddr, addr; 
    char p; 
 
    x3=x1 >> 3; 
    x4=x2 >> 3; 
 
    for (yc=y1; yc<=y2; yc++) 
    { 
        yaddr=_lgYaddr[yc]; 
 
        for (p=0; p<4; p++) 
        { 
            _lgOutportb (0x3ce, 4); 
            _lgOutportb (0x3cf, p); 
 
            for (xc=x3; xc<=x4; xc++) 
            { 
                addr=yaddr+xc; 
                *image++ = *(_lgDBitmap + addr); 
            } 
        } 
    } 
 
} 
 
void    _lgPutImage (char *image, int x1, int y1, int x2, int y2) 
{ 
    register int xc, yc; 
    int x3, x4; 
    unsigned yaddr, addr; 
    char p; 
 
    x3=x1 >> 3; 
    x4=x2 >> 3; 
 
    _lgOutportb (0x3ce, 3); 
    _lgOutportb (0x3cf, 0); 
    _lgOutportb (0x3ce, 5); 
    _lgOutportb (0x3cf, 0); 
    _lgOutportb (0x3ce, 8); 
    _lgOutportb (0x3cf, 0xff); 
 
    for (yc=y1; yc<=y2; yc++) 
    { 
        yaddr=_lgYaddr[yc]; 
 
        for (p=0; p<4; p++) 
        { 
            _lgOutportb (0x3c4, 2); 
            _lgOutportb (0x3c5, _lgBitPlane[p]); 
 
            for (xc=x3; xc<=x4; xc++) 
            { 
                addr=yaddr+xc; 
                *(_lgDBitmap+addr)=*image++; 
            } 
        } 
    } 
 
    _lgOutportb (0x3ce, 5); 
    _lgOutportb (0x3cf, 2); 
    _lgOutportb (0x3c4, 2); 
    _lgOutportb (0x3c5, 0x0f); 
    _lgSetXOR (_lgXOR);                 /* restore pen mode */ 
} 
 
int     _lgImageSize (int x1, int y1, int x2, int y2) 
{ 
    return (((((x2 - x1) << 3) + 1) * (y2 - y1 + 1)) >> 2); 
} 
 
void    _lgPutFont  (char *image, int x, int y, int width, int height) 
{ 
    register int xc, yc; 
    int  bkc=_lgColor, bytewidth, yaddr, addr; 
    BYTE *data, next, offset, mask; 
    static BYTE mmask; 
 
    _lgRectClipper (x, y, x+width-1, y+height-1); 
    if (_lgClipOut) return; 
 
    if (width & 7) bytewidth=(width >> 3)+1; 
    else           bytewidth=(width >> 3); 
 
    _lgOutportb (0x3ce, 8); 
 
    for (yc=_lgRY1; yc<=_lgRY2; yc++) 
    { 
        data = image + bytewidth * (yc - y); 
        next = (*data++); 
        offset = (_lgRX1 - x); 
        yaddr = _lgYaddr[yc]; 
 
        for (xc=_lgRX1; xc<=_lgRX2; xc++) 
        { 
            addr=yaddr + (xc >> 3); 
            if (next & (0x80 >> offset)) _lgColor=bkc; 
            else _lgColor=_lgBgColor; 
 
           _lgOutportb (0x3cf, _lgMask[xc & 7]); 
            mmask=*(_lgDBitmap+addr); 
            *(_lgDBitmap+addr)=_lgColor; 
 
            offset++; 
 
            if (offset & 8)     /* offset > 7 */ 
            { 
                offset=0; 
                next=*data++; 
            } 
        } 
 
    } 
 
    _lgColor=bkc; 
} 
 
void    _lgPutDIB   (char *image, int x, int y, int width, int height) 
{ 
    register int xc, yc; 
    int  bkc=_lgColor; 
    char *data; 
 
    _lgRectClipper (x, y, x+width-1, y+height-1); 
    if (_lgClipOut) return; 
    _lgMouseTempHide (_lgRX1, _lgRY1, _lgRX2, _lgRY2); 
 
    for (yc=_lgRY1; yc<=_lgRY2; yc++) 
    { 
        data = image + ((yc - y) * width) + (_lgRX1 - x); 
 
        for (xc=_lgRX1; xc<=_lgRX2; xc++) 
        { 
            _lgColor = *data++; 
            _lgLowPoint (xc, yc); 
        } 
    } 
 
    _lgColor = bkc; 
    _lgMouseTempShow(); 
} 
 
int _lgTextWidth  (char *text) 
{ 
    return (strlen(text) * 8); 
} 
 
int _lgTextHeight (char *text) 
{ 
    if (text) return (15); 
    return (0); 
} 
 
void _lgHideMouse () 
{ 
    if (_lgMouseHided == TRUE) return; 
    _lgMRestoreBack (); 
    _lgMouseHided = TRUE; 
} 
 
void _lgShowMouse () 
{ 
    if (_lgMouseHided == FALSE) return; 
    _lgMouseHided = FALSE; 
    _lgMSaveBack (); 
} 
 
BOOL _lgIsMouseHide (void) 
{ 
    return (_lgMouseHided); 
}