Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1354 lines
51 KiB

/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Author(s):
Eric W. Sink [email protected]
Jim Seidman [email protected]
*/
#include "all.h"
static BOOL GDI_Rect(HDC hdc, RECT *r)
{
return Rectangle(hdc, r->left, r->top, r->right, r->bottom);
}
/*
This function is responsible for the setting of the text color for a given
element. It takes into account whether the element is an anchor,
an HTML highlight, or whether there was a FONT tag with a COLOR attribute.
Note the precedence of these things.
*/
void x_set_text_color(HDC hdc, struct _element *pel, struct _www *w3doc)
{
#ifdef FEATURE_HTML_HIGHLIGHT
/*
Note that the highlight color overrides the anchor color
*/
if (pel->lFlags & ELEFLAG_HIGHLIGHT)
{
SetTextColor(hdc, gPrefs.highlight_color);
return;
}
#endif /* FEATURE_HTML_HIGHLIGHT */
if ((pel->type == ELE_TEXT) && (pel->lFlags & ELEFLAG_FONT_COLOR))
{
SetTextColor(hdc, pel->portion.text.myColor);
return;
}
if (pel->lFlags & ELEFLAG_ANCHOR)
{
if (pel->lFlags & ELEFLAG_VISITED)
{
if (!gPrefs.bIgnoreDocumentAttributes && w3doc->lFlags & W3DOC_FLAG_COLOR_VLINK)
{
SetTextColor(hdc, w3doc->color_vlink);
}
else
{
SetTextColor(hdc, gPrefs.anchor_color_beenthere);
}
}
else
{
if (!gPrefs.bIgnoreDocumentAttributes && w3doc->lFlags & W3DOC_FLAG_COLOR_VLINK)
{
SetTextColor(hdc, w3doc->color_link);
}
else
{
SetTextColor(hdc, gPrefs.anchor_color);
}
}
return;
}
if (!gPrefs.bIgnoreDocumentAttributes && w3doc->lFlags & W3DOC_FLAG_COLOR_TEXT)
{
SetTextColor(hdc, w3doc->color_text);
}
else if (!gPrefs.bUseSystemColors)
{
SetTextColor(hdc, gPrefs.window_color_text);
}
else
{
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
}
}
/*
TW_DrawOneElement
Draws parts of one element. You can specify whether the specified part should be highlighted or not.
Currently draws text only.
*/
void TW_DrawOneElement(struct Mwin *tw, int elementIndex, int startOffset, int endOffset, BOOL bHighlight)
{
struct _element *pel;
struct GTRFont *pFont;
COLORREF prevTextColor = 0;
COLORREF prevBkColor;
int prevBkMode;
HFONT hOldFont;
SIZE size;
if (elementIndex < 0)
{
return;
}
pel = &(tw->w3doc->aElements[elementIndex]);
if (pel->type != ELE_TEXT)
return;
if (startOffset >= pel->textLen)
{
XX_Assert((0), ("TW_DrawOneElement: Got a bad offset"));
return;
}
XX_DMsg(DBG_VIEWER, ("DOE: %d %d,%d %d\n", elementIndex, startOffset, endOffset, bHighlight));
/*
Set the font
*/
pFont = GTR_GetElementFont(tw->w3doc, pel);
hOldFont = SelectObject(tw->hdc, pFont->hFont);
/*
Set OPAQUE drawing mode, so we get the background color
*/
prevBkMode = SetBkMode(tw->hdc, OPAQUE);
if (bHighlight)
{
prevTextColor = SetTextColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
prevBkColor = SetBkColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHT));
}
else
{
x_set_text_color(tw->hdc, pel, tw->w3doc);
prevBkColor = SetBkColor(tw->hdc, PREF_GetBackgroundColor());
}
myGetTextExtentPoint(tw->hdc,
POOL_GetCharPointer(&tw->w3doc->pool, pel->textOffset),
startOffset, &size);
if ((endOffset < 0) || (endOffset >= pel->textLen))
{
endOffset = pel->textLen - 1;
}
(tw->w3doc->pool.f->DrawChars)( &tw->w3doc->pool, pFont, pel->textOffset + startOffset, endOffset - startOffset + 1, tw->hdc,
pel->r.left + size.cx - tw->offl, pel->r.top - tw->offt, NULL, 0);
SetTextColor(tw->hdc, prevTextColor);
SetBkColor(tw->hdc, prevBkColor);
SetBkMode(tw->hdc, prevBkMode);
SelectObject(tw->hdc, hOldFont);
}
static HRGN x_calc_region(struct Mwin *tw, struct _position *a1, struct _position *a2)
{
int n;
HRGN hElRgn;
BOOL bInSelection;
BOOL bSelStateChanging;
RECT rHilite, rEl;
struct GTRFont *pFont;
RECT roff;
HDC hdc;
HRGN hRgn;
RECT rWnd;
HFONT hPrevFont;
SIZE siz;
RECT rTemp;
if (a1->elementIndex == -1)
return NULL;
hdc = GetDC(tw->win);
bInSelection = FALSE;
/* Calculate a rectangle which we can test element rectangles against
to see if they're on-screen */
GetClientRect(tw->win, &roff);
OffsetRect(&roff, tw->offl, tw->offt);
hRgn = NULL;
for (n = 0; n >= 0; n = tw->w3doc->aElements[n].next)
{
bSelStateChanging = FALSE;
if (n == a1->elementIndex)
{
bSelStateChanging = TRUE;
bInSelection = TRUE;
}
/* Note that if the selection starts and ends on the same
element, both of these ifs may succeed. */
if (n == a2->elementIndex)
{
bSelStateChanging = TRUE;
bInSelection = FALSE;
}
if (tw->w3doc->aElements[n].type != ELE_TEXT)
continue;
rEl = tw->w3doc->aElements[n].r;
pFont = GTR_GetElementFont(tw->w3doc, &tw->w3doc->aElements[n]);
if (!IntersectRect(&rTemp, &rEl, &roff))
continue;
rEl = tw->w3doc->aElements[n].r;
if (bSelStateChanging)
{
rHilite = rEl;
hPrevFont = NULL;
if (pFont)
{
hPrevFont = SelectObject(hdc, pFont->hFont);
}
if (a1->elementIndex == n && a1->offset)
{
myGetTextExtentPoint(hdc, tw->w3doc->pool.chars + tw->w3doc->aElements[n].textOffset,
a1->offset, &siz);
rHilite.left += siz.cx;
}
if (a2->elementIndex == n)
{
myGetTextExtentPoint(hdc, tw->w3doc->pool.chars + tw->w3doc->aElements[n].textOffset,
a2->offset, &siz);
rHilite.right = tw->w3doc->aElements[n].r.left + siz.cx;
}
if (hPrevFont)
{
(void)SelectObject(hdc, hPrevFont);
}
OffsetRect(&rHilite, -tw->offl, -tw->offt);
if (hRgn)
{
hElRgn = CreateRectRgnIndirect(&rHilite);
UnionRgn(hRgn, hElRgn, hRgn);
DeleteObject(hElRgn);
}
else
{
hRgn = CreateRectRgnIndirect(&rHilite);
}
}
else
{
if (bInSelection)
{
rHilite = rEl;
OffsetRect(&rHilite, -tw->offl, -tw->offt);
if (hRgn)
{
hElRgn = CreateRectRgnIndirect(&rHilite);
UnionRgn(hRgn, hElRgn, hRgn);
DeleteObject(hElRgn);
}
else
{
hRgn = CreateRectRgnIndirect(&rHilite);
}
}
}
}
/* Clip to the visible screen area */
GetClientRect(tw->win, &rWnd);
if (hRgn)
{
hElRgn = CreateRectRgnIndirect(&rWnd);
IntersectRgn(hRgn, hElRgn, hRgn);
DeleteObject(hElRgn);
}
ReleaseDC(tw->win, hdc);
return hRgn;
}
/*
Draws multiple text elements.
*/
void TW_DrawElements(struct Mwin *tw, struct _position *start, struct _position *end, BOOL bHighlight)
{
int i;
if (start->elementIndex < 0)
{
return;
}
if (!bHighlight)
{
HRGN rgn;
rgn = x_calc_region(tw, start, end);
InvalidateRgn(tw->win, rgn, TRUE);
DeleteObject(rgn);
UpdateWindow(tw->win);
return;
}
XX_DMsg(DBG_VIEWER, ("DrawElements: %d,%d to %d,%d\n",
start->elementIndex, start->offset,
end->elementIndex, end->offset));
if (start->elementIndex == end->elementIndex)
{
if (start->offset != end->offset)
{
/* highlighting is contained within the same element */
TW_DrawOneElement(tw, start->elementIndex, start->offset, end->offset - 1, bHighlight);
}
}
else
{
/* Cross-element highlighting */
for (i = start->elementIndex; i >= 0; i = tw->w3doc->aElements[i].next)
{
if (i == start->elementIndex)
{
/* Highlight from the starting offset to the end of the element (highlight from) */
TW_DrawOneElement(tw, start->elementIndex, start->offset, -1, bHighlight);
}
else if (i == end->elementIndex)
{
if (end->offset > 0)
{
/* Highlight from offset 0 to the ending offset (highlight up to) */
TW_DrawOneElement(tw, end->elementIndex, 0, end->offset - 1, bHighlight);
}
break;
}
else
{
/* Highlight the entire element */
TW_DrawOneElement(tw, i, 0, -1, bHighlight);
}
}
}
}
void x_draw_image(struct Mwin *tw, struct _element *pel, BOOL bPrinting)
{
RECT rFrame;
HBRUSH hBrush;
float fScale = (float) 0.0;
HFONT hFontElement;
if (!pel->portion.img.myImage)
{
XX_DMsg(DBG_IMAGE, ("myImage is NULL!!\n"));
}
else
{
RECT rto;
int nPicW, nPicH;
int iBorder;
if ((pel->alignment == DOCK_LEFT) || (pel->alignment == DOCK_TOP) || (pel->alignment == DOCK_RIGHT) || (pel->alignment == DOCK_BOTTOM))
{
/* docked images are ignored */
return;
}
rto = pel->r;
OffsetRect(&rto, -tw->offl, -tw->offt);
/* Draw a placeholder in the case where either an image isn't loaded
or the space for it isn't the right size */
nPicW = pel->r.right - pel->r.left;
nPicH = pel->r.bottom - pel->r.top;
iBorder = pel->iBorder;
if (tw->w3doc->pStyles->image_res != 72)
{
iBorder = (int) (iBorder * fScale);
}
nPicW -= 2 * iBorder;
nPicH -= 2 * iBorder;
if ((pel->portion.img.myImage->flags & (IMG_ERROR | IMG_NOTLOADED | IMG_MISSING)) ||
((!bPrinting) && ((nPicW != pel->portion.img.width) || (nPicH != pel->portion.img.height))))
{
XX_Assert((pel->textLen > 0), ("Image does not have ALT text!"));
if (pel->textLen)
{
struct GTRFont *pFont;
if (iBorder > 0)
{
if (pel->lFlags & (ELEFLAG_ANCHOR | ELEFLAG_USEMAP))
{
if (pel->lFlags & ELEFLAG_VISITED)
{
hBrush = CreateSolidBrush(tw->w3doc->color_vlink);
}
else
{
hBrush = CreateSolidBrush(tw->w3doc->color_link);
}
}
else
{
if (!gPrefs.bIgnoreDocumentAttributes && tw->w3doc->lFlags & W3DOC_FLAG_COLOR_TEXT)
{
hBrush = CreateSolidBrush(tw->w3doc->color_text);
}
else if (!gPrefs.bUseSystemColors)
{
hBrush = CreateSolidBrush(gPrefs.window_color_text);
}
else
{
hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
}
}
/* left */
rFrame.left = pel->r.left - tw->offl;
rFrame.right = pel->r.left - tw->offl + iBorder;
rFrame.top = pel->r.top - tw->offt;
rFrame.bottom = pel->r.bottom - tw->offt;
FillRect(tw->hdc, &rFrame, hBrush);
/* right */
rFrame.left = pel->r.right - tw->offl - iBorder;
rFrame.right = pel->r.right - tw->offl;
FillRect(tw->hdc, &rFrame, hBrush);
/* top */
rFrame.left = pel->r.left - tw->offl;
rFrame.right = pel->r.right - tw->offl;
rFrame.top = pel->r.top - tw->offt;
rFrame.bottom = pel->r.top - tw->offt + iBorder;
FillRect(tw->hdc, &rFrame, hBrush);
/* bottom */
rFrame.top = pel->r.bottom - tw->offt - iBorder;
rFrame.bottom = pel->r.bottom - tw->offt;
FillRect(tw->hdc, &rFrame, hBrush);
DeleteObject(hBrush);
}
pFont = GTR_GetNormalFont(tw->w3doc);
if (pFont)
{
hFontElement = pFont->hFont;
if (hFontElement)
{
SelectObject(tw->hdc, hFontElement);
}
}
x_set_text_color(tw->hdc, pel, tw->w3doc);
(tw->w3doc->pool.f->DrawChars)(&tw->w3doc->pool, pFont, pel->textOffset, pel->textLen, tw->hdc, rto.left + iBorder * 2, rto.top + iBorder * 2, &rto, ETO_CLIPPED);
if (pel->portion.img.myImage->flags & (IMG_ERROR | IMG_MISSING))
{
HPEN hPen;
HPEN oldPen;
hPen = CreatePen(PS_SOLID, 0, RGB(255, 0, 0));
oldPen = SelectObject(tw->hdc, hPen);
MoveToEx(tw->hdc, rto.left + (iBorder + 1), rto.top + (iBorder + 1), NULL);
LineTo(tw->hdc, rto.right - (iBorder + 1), rto.bottom - (iBorder + 1));
MoveToEx(tw->hdc, rto.right - (iBorder + 1), rto.top + (iBorder + 1), NULL);
LineTo(tw->hdc, rto.left + (iBorder + 1), rto.bottom - (iBorder + 1));
SelectObject(tw->hdc, oldPen);
DeleteObject(hPen);
}
}
}
else
{
int err;
if (pel->portion.img.myImage->data && pel->portion.img.myImage->pbmi)
{
if (bPrinting)
{
err = Printer_StretchDIBits(tw->hdc, pel->r.left - tw->offl + iBorder,
pel->r.top - tw->offt + iBorder,
pel->r.right - pel->r.left - (iBorder * 2), pel->r.bottom - pel->r.top - (iBorder * 2),
0, 0,
pel->portion.img.myImage->width, pel->portion.img.myImage->height, pel->portion.img.myImage);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
else
{
if (pel->portion.img.myImage->flags & (IMG_PROGRESS | IMG_PARTIAL) &&
pel->portion.img.myImage->bFirstPass)
{
/* only paint what's decoded so far */
long yTo;
RECT rDelta;
yTo = pel->portion.img.myImage->nLastRow; /* decoded up to this line */
rDelta.left = pel->r.left;
rDelta.right = pel->r.right;
rDelta.top = pel->r.top;
rDelta.bottom = pel->r.top + yTo + iBorder*2;
err = GTR_StretchDIBits(tw, tw->hdc, rDelta, iBorder,
0, pel->portion.img.myImage->height - yTo,
pel->portion.img.myImage->width, yTo, pel->portion.img.myImage->data, pel->portion.img.myImage->pbmi,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY,
pel->portion.img.myImage->transparent);
}
else
{
err = GTR_StretchDIBits(tw, tw->hdc, pel->r, iBorder,
0, 0, pel->portion.img.myImage->width, pel->portion.img.myImage->height,
pel->portion.img.myImage->data, pel->portion.img.myImage->pbmi,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY,
pel->portion.img.myImage->transparent);
}
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
}
if (iBorder > 0)
{
if (pel->lFlags & (ELEFLAG_ANCHOR | ELEFLAG_USEMAP))
{
if (pel->lFlags & ELEFLAG_VISITED)
{
hBrush = CreateSolidBrush(tw->w3doc->color_vlink);
}
else
{
hBrush = CreateSolidBrush(tw->w3doc->color_link);
}
}
else
{
if (!gPrefs.bIgnoreDocumentAttributes && tw->w3doc->lFlags & W3DOC_FLAG_COLOR_TEXT)
{
hBrush = CreateSolidBrush(tw->w3doc->color_text);
}
else if (!gPrefs.bUseSystemColors)
{
hBrush = CreateSolidBrush(gPrefs.window_color_text);
}
else
{
hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
}
}
/* left */
rFrame.left = pel->r.left - tw->offl;
rFrame.right = pel->r.left - tw->offl + iBorder;
rFrame.top = pel->r.top - tw->offt;
rFrame.bottom = pel->r.bottom - tw->offt;
FillRect(tw->hdc, &rFrame, hBrush);
/* right */
rFrame.left = pel->r.right - tw->offl - iBorder;
rFrame.right = pel->r.right - tw->offl;
FillRect(tw->hdc, &rFrame, hBrush);
/* top */
rFrame.left = pel->r.left - tw->offl;
rFrame.right = pel->r.right - tw->offl;
rFrame.top = pel->r.top - tw->offt;
rFrame.bottom = pel->r.top - tw->offt + iBorder;
FillRect(tw->hdc, &rFrame, hBrush);
/* bottom */
rFrame.top = pel->r.bottom - tw->offt - iBorder;
rFrame.bottom = pel->r.bottom - tw->offt;
FillRect(tw->hdc, &rFrame, hBrush);
DeleteObject(hBrush);
}
}
}
}
void TW_Draw(struct Mwin *tw, RECT * rWndParam, BOOL bDrawFormControls,
struct _position *pposStart, struct _position *pposEnd, BOOL bTextOpaque, BOOL bPrinting)
{
int i;
COLORREF oldColor;
COLORREF oldBkColor;
int oldMode;
UINT oldTA;
RECT rSect;
struct GTRFont *pFont;
HFONT hFontElement;
struct _element *pel;
int iStartingElement;
int iEndingElement;
RECT rMyWnd;
RECT *rWnd;
float fScale = (float) 0.0;
XX_DMsg(DBG_DRAW, ("Entering TW_Draw\n"));
rWnd = &rMyWnd;
*rWnd = *rWndParam;
XX_Assert((rWnd->bottom > rWnd->top), ("Invalid rWnd in TW_Draw: r = %d, %d, %d, %d\n",
rWnd->left, rWnd->top, rWnd->right, rWnd->bottom));
if (!tw)
return;
if (!tw->w3doc)
{
XX_DMsg(DBG_DRAW, ("w3doc == NULL: no draw\n"));
return;
}
if (tw->w3doc->nLineCount <= 0 || tw->w3doc->nLastFormattedLine < 0)
{
XX_DMsg(DBG_DRAW, ("No lines: no draw\n"));
return;
}
XX_DMsg(DBG_PAL, ("Draw: Calling GTR_RealizePalette\n"));
GTR_RealizePalette(tw->hdc);
oldColor = SetTextColor(tw->hdc, tw->w3doc->color_text);
oldBkColor = SetBkColor(tw->hdc, PREF_GetBackgroundColor());
if (bTextOpaque)
{
oldMode = SetBkMode(tw->hdc, OPAQUE);
}
else
{
oldMode = SetBkMode(tw->hdc, TRANSPARENT);
}
oldTA = SetTextAlign(tw->hdc, TA_TOP | TA_NOUPDATECP | TA_LEFT);
/* TODO should save old font */
OffsetRect(rWnd, tw->offl, tw->offt);
if (tw->w3doc->pStyles->image_res != 72)
{
fScale = (float) ((float) tw->w3doc->pStyles->image_res / 72.0);
}
if (pposStart)
{
i = 0;
iStartingElement = pposStart->elementIndex;
}
else
{
/* Find the first line that is in the window */
for (i = 0; i <= tw->w3doc->nLastFormattedLine; i++)
{
if (tw->w3doc->pLineInfo[i].nYEnd >= rWnd->top)
break;
}
if (i > tw->w3doc->nLastFormattedLine)
{
XX_DMsg(DBG_DRAW, ("Last formatted line is off top of screen!\n"));
i = tw->w3doc->nLastFormattedLine;
}
XX_Assert((i >= 0), ("Bad value for i"));
iStartingElement = tw->w3doc->pLineInfo[i].nFirstElement;
}
if (pposEnd)
{
iEndingElement = pposEnd->elementIndex;
}
else
{
/* i still has a valid line number from before */
for (; i <= tw->w3doc->nLastFormattedLine; i++)
{
if (tw->w3doc->pLineInfo[i].nYStart > rWnd->bottom)
{
/* this line is off the screen. Therefore we only have to go
up to the last element on the previous line. */
if (i > 0)
iEndingElement = tw->w3doc->pLineInfo[i - 1].nLastElement;
else
iEndingElement = 0;
break;
}
}
if (i > tw->w3doc->nLastFormattedLine)
{
iEndingElement = tw->w3doc->pLineInfo[tw->w3doc->nLastFormattedLine].nLastElement;
}
}
if (!pposStart && !pposEnd)
{
tw->w3doc->iFirstVisibleElement = -1;
if (tw->offt == 0)
{
tw->w3doc->iFirstVisibleElement = 0;
}
}
#ifdef XX_DEBUG
if (tw->w3doc->lFlags & W3DOC_FLAG_USEDCACHE)
{
SetPixel(tw->hdc, 0 - tw->offl, 0 - tw->offt, tw->w3doc->color_text);
}
#endif
/*
Draw the elements which need to be redrawn
*/
if (tw->w3doc->nLineCount)
{
for (i = iStartingElement; i >= 0; i = tw->w3doc->aElements[i].next)
{
pel = &(tw->w3doc->aElements[i]);
if (IntersectRect(&rSect, rWnd, &pel->r))
{
if (tw->w3doc->iFirstVisibleElement == -1)
{
tw->w3doc->iFirstVisibleElement = i;
}
/*
set the tw->hdc for the style of the element
*/
pFont = GTR_GetElementFont(tw->w3doc, pel);
if (pFont)
{
hFontElement = pFont->hFont;
if (hFontElement)
{
SelectObject(tw->hdc, hFontElement);
}
}
switch (pel->type)
{
#ifdef FEATURE_TABLES
case ELE_BEGINTABLE:
case ELE_BEGINCELL:
if (pel->iBorder)
{
/* draw 1 pixel border around entire table. */
RECT r;
if (pel->type == ELE_BEGINTABLE)
TW_GetTableBorderCoords(tw->w3doc,i,&r);
else
TW_GetCellBorderCoords(tw->w3doc,i,&r);
OffsetRect(&r,-tw->offl,-tw->offt);
MoveToEx(tw->hdc,r.left,r.top,NULL);
LineTo(tw->hdc,r.right,r.top);
LineTo(tw->hdc,r.right,r.bottom);
LineTo(tw->hdc,r.left,r.bottom);
LineTo(tw->hdc,r.left,r.top);
}
break;
#endif /* FEATURE_TABLES */
case ELE_TEXT:
{
x_set_text_color(tw->hdc, pel, tw->w3doc);
(tw->w3doc->pool.f->DrawChars)( &tw->w3doc->pool, pFont, pel->textOffset, pel->textLen, tw->hdc,
pel->r.left - tw->offl, pel->r.top - tw->offt, NULL, 0);
#if 0
/* This fragment is useful for debugging */
{
RECT r;
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
FrameRect(tw->hdc, &r, GetStockObject(BLACK_BRUSH));
}
#endif
}
break;
case ELE_FORMIMAGE:
case ELE_IMAGE:
x_draw_image(tw, pel, bPrinting);
break;
case ELE_HR:
{
RECT r;
HBRUSH hBrush;
/* The element rectangle on HRule's are for a 100%
* rule. Compute the actual drawing portion.
*/
TW_GetHRuleDrawingCoords(&r,pel);
OffsetRect(&r, -tw->offl, -tw->offt);
if (pel->lFlags & ELEFLAG_HR_NOSHADE)
{
/** The user has requested no shading **/
if (!gPrefs.bIgnoreDocumentAttributes && tw->w3doc->lFlags & W3DOC_FLAG_COLOR_TEXT)
{
hBrush = CreateSolidBrush(tw->w3doc->color_text);
}
else if (!gPrefs.bUseSystemColors)
{
hBrush = CreateSolidBrush(gPrefs.window_color_text);
}
else
{
hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
}
FillRect(tw->hdc, &r, hBrush);
DeleteObject(hBrush);
}
else
{
/* do shading like MS does */
RECT rShade;
/* paint top,left shadow */
hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
rShade.left = r.left; /* top */
rShade.right = r.right;
rShade.top = r.top;
rShade.bottom = rShade.top + 1;
(void) FillRect(tw->hdc, &rShade, hBrush);
rShade.right = rShade.left + 1; /* left */
rShade.bottom = r.bottom; /* well, almost :-) */
(void) FillRect(tw->hdc, &rShade, hBrush);
(void) DeleteObject(hBrush);
/* paint bottom,right highlight */
hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
rShade.right = r.right; /* right */
rShade.left = rShade.right - 1;
rShade.top = r.top + 1;
rShade.bottom = r.bottom;
(void) FillRect(tw->hdc, &rShade, hBrush);
rShade.top = rShade.bottom - 1; /* bottom */
rShade.left = r.left + 1;
(void) FillRect(tw->hdc, &rShade, hBrush);
(void) DeleteObject(hBrush);
}
}
break;
default:
if (bDrawFormControls)
{
switch (pel->type)
{
case ELE_EDIT:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
GetWindowText(pel->form->hWndControl, s, len+1);
GDI_Rect(tw->hdc, &r);
r.left += (r.bottom - r.top) / 8;
if (pel->form->bWantReturn)
{
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
}
else
{
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_SINGLELINE|DT_VCENTER);
}
GTR_FREE(s);
}
}
break;
case ELE_PASSWORD:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
char *p;
GetWindowText(pel->form->hWndControl, s, len+1);
p = s;
while (*p)
{
*p++ = '*';
}
r.left += (r.bottom - r.top) / 8;
GDI_Rect(tw->hdc, &r);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
break;
case ELE_CHECKBOX:
if (pel->form && pel->form->hWndControl)
{
RECT r;
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
r.right = r.left + (r.bottom - r.top);
GDI_Rect(tw->hdc, &r);
if (SendMessage(pel->form->hWndControl, BM_GETCHECK, (WPARAM) 0, 0L))
{
MoveToEx(tw->hdc, r.left, r.top, NULL);
LineTo(tw->hdc, r.right, r.bottom);
MoveToEx(tw->hdc, r.right, r.top, NULL);
LineTo(tw->hdc, r.left, r.bottom);
}
}
break;
case ELE_RADIO:
if (pel->form && pel->form->hWndControl)
{
RECT r;
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
r.right = r.left + (r.bottom - r.top);
Arc(tw->hdc, r.left, r.top, r.right, r.bottom,
r.right, r.top, r.right, r.top);
if (SendMessage(pel->form->hWndControl, BM_GETCHECK, (WPARAM) 0, 0L))
{
HBRUSH hOldBrush;
InflateRect(&r, -((r.right - r.left) / 5), -((r.bottom - r.top) / 5));
hOldBrush = SelectObject(tw->hdc, GetStockObject(BLACK_BRUSH));
Ellipse(tw->hdc, r.left, r.top, r.right, r.bottom);
(void) SelectObject(tw->hdc, hOldBrush);
}
}
break;
case ELE_SUBMIT:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
GetWindowText(pel->form->hWndControl, s, len+1);
RoundRect(tw->hdc, r.left, r.top, r.right, r.bottom,
(r.bottom - r.top) / 3, (r.bottom - r.top) / 3);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_CENTER|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
break;
case ELE_RESET:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
GetWindowText(pel->form->hWndControl, s, len+1);
RoundRect(tw->hdc, r.left, r.top, r.right, r.bottom,
(r.bottom - r.top) / 3, (r.bottom - r.top) / 3);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_CENTER|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
break;
case ELE_COMBO:
if (pel->form && pel->form->hWndControl)
{
int ndx;
int len;
char *s;
RECT r;
ndx = SendMessage(pel->form->hWndControl, CB_GETCURSEL, (WPARAM) 0, 0L);
if (ndx != CB_ERR)
{
len = SendMessage(pel->form->hWndControl, CB_GETLBTEXTLEN, (WPARAM) ndx, 0L);
s = (char *) GTR_MALLOC(len+1);
if (s)
{
(void) SendMessage(pel->form->hWndControl, CB_GETLBTEXT, (WPARAM) ndx, (LPARAM) s);
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
GDI_Rect(tw->hdc, &r);
r.right -= (r.bottom - r.top);
GDI_Rect(tw->hdc, &r);
r.left += (r.bottom - r.top) / 8;
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
}
break;
case ELE_LIST:
case ELE_MULTILIST:
if (pel->form && pel->form->hWndControl)
{
int cVisible;
int iHeight;
int iHeightItem;
RECT r;
int i;
int ndx;
char *s;
int len;
UINT taOld;
COLORREF oldFore;
COLORREF oldBack;
/*
iHeight, iHeightItem and r are now in SCREEN coords
*/
GetWindowRect(pel->form->hWndControl, &r);
iHeight = r.bottom - r.top;
iHeightItem = SendMessage(pel->form->hWndControl, LB_GETITEMHEIGHT, (WPARAM) 0, 0L);
cVisible = iHeight / iHeightItem;
/*
iHeight, iHeightItem and r are now in PRINTER coords
*/
iHeight = pel->r.bottom - pel->r.top;
iHeightItem = iHeight / cVisible;
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
r.bottom = r.top + (cVisible * iHeightItem);
GDI_Rect(tw->hdc, &r);
r.right -= iHeightItem;
GDI_Rect(tw->hdc, &r);
ndx = SendMessage(pel->form->hWndControl, LB_GETTOPINDEX, (WPARAM) 0, 0L);
for (i=0; i<cVisible; i++, ndx++)
{
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
r.top += (i * iHeightItem);
r.bottom = r.top + iHeightItem;
r.right -= (r.bottom - r.top + 1);
r.left += 1;
len = SendMessage(pel->form->hWndControl, LB_GETTEXTLEN, (WPARAM) ndx, 0L);
s = (char *) GTR_MALLOC(len + 1);
if (s)
{
(void) SendMessage(pel->form->hWndControl, LB_GETTEXT, (WPARAM) ndx, (LPARAM) s);
taOld = SetTextAlign(tw->hdc, TA_LEFT|TA_BOTTOM);
if (SendMessage(pel->form->hWndControl, LB_GETSEL, (WPARAM) ndx, 0L))
{
oldFore = SetTextColor(tw->hdc, RGB(255,255,255));
oldBack = SetBkColor(tw->hdc, RGB(0,0,0));
ExtTextOut(tw->hdc, r.left + (r.bottom - r.top) / 8, r.bottom - 1,
ETO_CLIPPED|ETO_OPAQUE, &r, s, len, NULL);
(void) SetBkColor(tw->hdc, oldBack);
(void) SetTextColor(tw->hdc, oldFore);
}
else
{
ExtTextOut(tw->hdc, r.left + (r.bottom - r.top) / 8, r.bottom - 1,
ETO_CLIPPED, &r, s, len, NULL);
}
(void) SetTextAlign(tw->hdc, taOld);
GTR_FREE(s);
}
}
}
break;
case ELE_TEXTAREA:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
GetWindowText(pel->form->hWndControl, s, len+1);
r = pel->r;
OffsetRect(&r, -tw->offl, -tw->offt);
GDI_Rect(tw->hdc, &r);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
GTR_FREE(s);
}
}
break;
default:
break;
}
}
break;
}
}
#ifdef XX_DEBUG
else
{
if (bPrinting)
{
XX_DMsg(DBG_PRINT, ("Element %d not drawn. pel->r is %d,%d,%d,%d and rWnd is %d, %d, %d, %d\n",
i,
pel->r.left, pel->r.top, pel->r.right, pel->r.bottom,
rWnd->left, rWnd->top, rWnd->right, rWnd->bottom
));
}
}
#endif
if ((iEndingElement > 0) && (i == iEndingElement))
{
break; /* out of the loop */
}
}
}
/*
Now the side images, just in case
*/
{
struct ImageElementNode *ien;
int i;
ien = tw->w3doc->image_list;
while (ien)
{
i = ien->elementIndex;
pel = &(tw->w3doc->aElements[i]);
if (IntersectRect(&rSect, rWnd, &pel->r))
{
if (tw->w3doc->iFirstVisibleElement == -1)
{
tw->w3doc->iFirstVisibleElement = i;
}
/*
set the tw->hdc for the style of the element
*/
pFont = GTR_GetElementFont(tw->w3doc, pel);
if (pFont)
{
hFontElement = pFont->hFont;
if (hFontElement)
{
SelectObject(tw->hdc, hFontElement);
}
}
switch (pel->type)
{
case ELE_FORMIMAGE:
case ELE_IMAGE:
x_draw_image(tw, pel, bPrinting);
break;
}
}
ien = ien->next;
}
}
SetTextColor(tw->hdc, oldColor);
SetBkMode(tw->hdc, oldMode);
SetBkColor(tw->hdc, oldBkColor);
SetTextAlign(tw->hdc, oldTA);
if (!bPrinting && !tw->bNoDrawSelection)
{
TW_DrawElements(tw, &tw->w3doc->selStart, &tw->w3doc->selEnd, TRUE);
}
return;
}
/*
** This function is a hook for progressive images. each platform should
** provide its own. It is to get an image displayed w/out going through
** all the reformat code
*/
void
GTR_DrawProgessiveImage (struct Mwin *tw, int elementIndex)
{
/* HACK: copied entire ELE_IMAGE case out of TW_Draw */
struct _element *pel;
float fScale = (float) 0.0;
long yFrom, yTo, hDelta;
long yFrom_Scaled;
long yTo_Scaled;
RECT rDelta;
pel = &(tw->w3doc->aElements[elementIndex]);
/* HACK: much-trimmed copy of ELE_IMAGE case starts here */
switch (pel->type)
{
case ELE_IMAGE:
if (!pel->portion.img.myImage)
{
XX_DMsg(DBG_IMAGE, ("myImage is NULL!!\n"));
}
else
{
int iBorder;
int err;
if ((pel->alignment == DOCK_LEFT) || (pel->alignment == DOCK_TOP) || (pel->alignment == DOCK_RIGHT) || (pel->alignment == DOCK_BOTTOM))
{
/* docked images are ignored */
break;
}
iBorder = pel->iBorder;
if (tw->w3doc->pStyles->image_res != 72)
{
fScale = (float) ((float) tw->w3doc->pStyles->image_res / 72.0);
iBorder = (int) (iBorder * fScale);
}
if (pel->portion.img.myImage->data && pel->portion.img.myImage->pbmi)
{
/* only paint what's changed since last call */
yFrom = pel->portion.img.myImage->nPreviousLastRow;
yTo = pel->portion.img.myImage->nLastRow; /* decoded up to this line */
if (!pel->portion.img.myImage->bFirstPass &&
pel->portion.img.myImage->nPass > pel->portion.img.myImage->nPreviousPass)
{
/* finish off prior pass */
hDelta = pel->portion.img.myImage->height - yFrom;
if (pel->portion.img.myImage->height == pel->portion.img.height)
{
yFrom_Scaled = yFrom;
}
else
{
yFrom_Scaled = (yFrom * pel->portion.img.height)
/ pel->portion.img.myImage->height;
}
rDelta.left = pel->r.left;
rDelta.right = pel->r.right;
rDelta.top = pel->r.top + yFrom_Scaled;
rDelta.bottom = pel->r.bottom;
err = GTR_StretchDIBits(tw, tw->hdc, rDelta, iBorder,
0, 0,
pel->portion.img.myImage->width, hDelta, pel->portion.img.myImage->data, pel->portion.img.myImage->pbmi,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY,
pel->portion.img.myImage->transparent);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
/* reset for this pass */
yFrom = 0;
}
hDelta = yTo - yFrom;
if (pel->portion.img.myImage->height == pel->portion.img.height)
{
yFrom_Scaled = yFrom;
yTo_Scaled = yTo;
}
else
{
yFrom_Scaled = (yFrom * pel->portion.img.height)
/ pel->portion.img.myImage->height;
yTo_Scaled = (yTo * pel->portion.img.height)
/ pel->portion.img.myImage->height;
}
rDelta.left = pel->r.left;
rDelta.right = pel->r.right;
rDelta.top = pel->r.top + yFrom_Scaled;
rDelta.bottom = pel->r.top + yTo_Scaled + iBorder*2;
err = GTR_StretchDIBits(tw, tw->hdc, rDelta, iBorder,
0, pel->portion.img.myImage->height - yTo,
pel->portion.img.myImage->width, hDelta, pel->portion.img.myImage->data, pel->portion.img.myImage->pbmi,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY,
pel->portion.img.myImage->transparent);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
}
break;
default:
break;
}
}