📄 activex.cpp
字号:
{
RECT rc;
GetClientRect(m_displayWindow, &rc);
BitBlt(hdc, 0, 0, rc.right, rc.bottom, m_displayBuffer, 0, 0, SRCCOPY);
}
else
{
PAINTSTRUCT ps;
hdc = BeginPaint(m_displayWindow, &ps);
if(!m_smartSizing)
{
BitBlt
(
hdc,
ps.rcPaint.left,
ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
m_displayBuffer,
ps.rcPaint.left,
ps.rcPaint.top,
SRCCOPY
);
}
else
{
// bleh. There has to be a better way
SetStretchBltMode(hdc, HALFTONE);
StretchBlt
(
hdc,
0,
0,
m_consoleWidth,
m_consoleHeight,
m_displayBuffer,
0,
0,
m_displayBufferWidth,
m_displayBufferHeight,
SRCCOPY
);
}
EndPaint(m_displayWindow, &ps);
}
LeaveCriticalSection(&m_displayBufferMutex);
}
return 0;
default:
break;
}
return DefWindowProc(m_displayWindow, uMsg, wParam, lParam);
}
/* Screen repainting */
void Display_RepaintRect(const RECT * lprc)
{
if(m_smartSizing)
return Display_RepaintAll();
RECT rcDamage;
IntersectRect(&rcDamage, lprc, &m_displayBufferClip);
InvalidateRect(m_displayWindow, &rcDamage, FALSE);
}
void Display_RepaintArea(int x, int y, int cx, int cy)
{
if(m_smartSizing)
return Display_RepaintAll();
RECT rcDamage;
rcDamage.left = x;
rcDamage.top = y;
rcDamage.right = x + cx;
rcDamage.bottom = y + cy;
Display_RepaintRect(&rcDamage);
}
void Display_RepaintPolygon(POINT * point, int npoints, int linewidth)
{
if(m_smartSizing)
return Display_RepaintAll();
RECT rcDamage;
rcDamage.left = MAXLONG;
rcDamage.top = MAXLONG;
rcDamage.right = 0;
rcDamage.bottom = 0;
for(int i = 0; i < npoints; ++ i)
{
if(point[i].x < rcDamage.left)
rcDamage.left = point[i].x;
if(point[i].y < rcDamage.top)
rcDamage.top = point[i].y;
if(point[i].x > rcDamage.right)
rcDamage.right = point[i].x;
if(point[i].y > rcDamage.bottom)
rcDamage.bottom = point[i].y;
}
InflateRect(&rcDamage, linewidth, linewidth);
Display_RepaintRect(&rcDamage);
}
void Display_RepaintAll()
{
InvalidateRgn(m_displayWindow, NULL, FALSE);
}
public:
void Display_SetClip(int x, int y, int cx, int cy)
{
m_displayBufferClip.left = x;
m_displayBufferClip.top = y;
m_displayBufferClip.right = x + cx + 1;
m_displayBufferClip.bottom = y + cy + 1;
HRGN hrgn = CreateRectRgnIndirect(&m_displayBufferClip);
SelectClipRgn(m_displayBuffer, hrgn);
DeleteObject(hrgn);
}
void Display_ResetClip()
{
m_displayBufferClip.left = 0;
m_displayBufferClip.top = 0;
m_displayBufferClip.right = m_displayBufferWidth;
m_displayBufferClip.bottom = m_displayBufferHeight;
SelectClipRgn(m_displayBuffer, NULL);
}
void Display_PaintBitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
{
GdiFlush();
int fromstride = alignup(width * m_displayBufferByteDepth, 4);
int sizex = cx * m_displayBufferByteDepth;
const uint8 * src = data;
uint8 * dst =
(uint8 *)m_displayBufferRaw +
(m_displayBufferHeight - y - cy) * m_displayBufferStride +
x * m_displayBufferByteDepth;
for(int i = 0; i < cy; ++ i)
{
memcpy(dst, src, sizex);
src += fromstride;
dst += m_displayBufferStride;
}
Display_RepaintArea(x, y, cx, cy);
}
void Display_DestBlt(uint8 opcode, int x, int y, int cx, int cy)
{
int dcsave = SaveDC(m_displayBuffer);
SelectObject(m_displayBuffer, GetStockObject(BLACK_BRUSH));
PatBlt(m_displayBuffer, x, y, cx, cy, MAKELONG(0, opcode));
RestoreDC(m_displayBuffer, dcsave);
Display_RepaintArea(x, y, cx, cy);
}
void Display_PatBlt(uint8 opcode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, int fgcolour)
{
HBRUSH hbr = win32_create_brush(brush, fgcolour);
int dcsave = SaveDC(m_displayBuffer);
SetBkColor(m_displayBuffer, bgcolour);
SetTextColor(m_displayBuffer, fgcolour);
SetBrushOrgEx(m_displayBuffer, brush->xorigin, brush->yorigin, NULL);
SelectObject(m_displayBuffer, hbr);
PatBlt(m_displayBuffer, x, y, cx, cy, MAKELONG(0, opcode));
RestoreDC(m_displayBuffer, dcsave);
DeleteObject(hbr);
Display_RepaintArea(x, y, cx, cy);
}
void Display_ScreenBlt(uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy)
{
BitBlt(m_displayBuffer, x, y, cx, cy, m_displayBuffer, srcx, srcy, MAKELONG(0, opcode));
Display_RepaintArea(x, y, cx, cy);
}
void Display_MemBlt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy)
{
HDC hdcSrc = CreateCompatibleDC(m_displayBuffer);
HGDIOBJ hOld = SelectObject(hdcSrc, src);
BitBlt(m_displayBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode));
SelectObject(hdcSrc, hOld);
DeleteDC(hdcSrc);
Display_RepaintArea(x, y, cx, cy);
}
void Display_TriBlt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy, BRUSH * brush, int bgcolour, int fgcolour)
{
// TODO
HDC hdcSrc = CreateCompatibleDC(m_displayBuffer);
HGDIOBJ hOld = SelectObject(hdcSrc, src);
//SELECT_BRUSH(brush, bgcolour, fgcolour);
BitBlt(m_displayBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode));
//RESET_BRUSH();
SelectObject(hdcSrc, hOld);
DeleteDC(hdcSrc);
Display_RepaintArea(x, y, cx, cy);
}
void Display_Line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen)
{
HPEN hpen = CreatePen(pen->style, pen->width, pen->colour);
int dcsave = SaveDC(m_displayBuffer);
SetROP2(m_displayBuffer, opcode);
SelectObject(m_displayBuffer, hpen);
MoveToEx(m_displayBuffer, startx, starty, NULL);
LineTo(m_displayBuffer, endx, endy);
RestoreDC(m_displayBuffer, dcsave);
DeleteObject(hpen);
RECT rcDamage;
if(startx < endx)
{
rcDamage.left = startx;
rcDamage.right = endx;
}
else
{
rcDamage.left = endx;
rcDamage.right = startx;
}
if(starty < endy)
{
rcDamage.top = starty;
rcDamage.bottom = endy;
}
else
{
rcDamage.top = endy;
rcDamage.bottom = starty;
}
InflateRect(&rcDamage, pen->width, pen->width);
Display_RepaintRect(&rcDamage);
}
void Display_Rect(int x, int y, int cx, int cy, int colour)
{
HBRUSH hbr = CreateSolidBrush(colour);
int dcsave = SaveDC(m_displayBuffer);
SelectObject(m_displayBuffer, hbr);
SelectObject(m_displayBuffer, GetStockObject(NULL_PEN));
Rectangle(m_displayBuffer, x, y, x + cx + 1, y + cy + 1);
RestoreDC(m_displayBuffer, dcsave);
DeleteObject(hbr);
Display_RepaintArea(x, y, cx, cy);
}
void Display_Polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints, BRUSH * brush, int bgcolour, int fgcolour)
{
HBRUSH hbr = win32_create_brush(brush, fgcolour);
int dcsave = SaveDC(m_displayBuffer);
SetBkColor(m_displayBuffer, bgcolour);
SetTextColor(m_displayBuffer, fgcolour);
SetPolyFillMode(m_displayBuffer, fillmode);
SelectObject(m_displayBuffer, hbr);
Polygon(m_displayBuffer, point, npoints);
RestoreDC(m_displayBuffer, dcsave);
Display_RepaintPolygon(point, npoints, 0);
}
void Display_Polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)
{
POINT last = points[0];
for(int i = 1; i < npoints; ++ i)
{
points[i].x += last.x;
points[i].y += last.y;
last = points[i];
}
HPEN hpen = CreatePen(pen->style, pen->width, pen->colour);
int dcsave = SaveDC(m_displayBuffer);
SetROP2(m_displayBuffer, opcode);
SelectObject(m_displayBuffer, hpen);
Polyline(m_displayBuffer, points, npoints);
RestoreDC(m_displayBuffer, dcsave);
DeleteObject(hpen);
Display_RepaintPolygon(points, npoints, pen->width);
}
void Display_Ellypse(uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, int fgcolour)
{
// TODO
Display_RepaintArea(x, y, cx, cy);
}
// TBD: optimize text drawing
void Display_DrawGlyph(int mixmode, int x, int y, int cx, int cy, HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)
{
HBITMAP hbmGlyph = (HBITMAP)glyph;
HDC hdcGlyph = CreateCompatibleDC(m_displayBuffer);
HGDIOBJ hOld = SelectObject(hdcGlyph, hbmGlyph);
int dcsave = SaveDC(m_displayBuffer);
switch(mixmode)
{
case MIX_TRANSPARENT:
{
/*
ROP is DSPDxax:
- where the glyph (S) is white, D is set to the foreground color (P)
- where the glyph (S) is black, D is left untouched
This paints a transparent glyph in the specified color
*/
HBRUSH hbr = CreateSolidBrush(fgcolour);
SelectObject(m_displayBuffer, hbr);
BitBlt(m_displayBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, MAKELONG(0, 0xe2));
DeleteObject(hbr);
}
break;
case MIX_OPAQUE:
{
/* Curiously, glyphs are inverted (white-on-black) */
SetBkColor(m_displayBuffer, fgcolour);
SetTextColor(m_displayBuffer, bgcolour);
BitBlt(m_displayBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, SRCCOPY);
}
break;
}
RestoreDC(m_displayBuffer, dcsave);
SelectObject(hdcGlyph, hOld);
DeleteDC(hdcGlyph);
Display_RepaintArea(x, y, cx, cy);
}
void Display_DoGlyph(uint8 font, uint8 flags, int mixmode, int& x, int& y, int bgcolour, int fgcolour, const uint8 * ttext, int& idx)
{
FONTGLYPH * glyph;
glyph = cache_get_font(/*This*/NULL, font, ttext[idx]);
if(!(flags & TEXT2_IMPLICIT_X))
{
int xyoffset = ttext[++ idx];
if((xyoffset & 0x80))
{
if (flags & TEXT2_VERTICAL)
y += ttext[idx + 1] | (ttext[idx + 2] << 8);
else
x += ttext[idx + 1] | (ttext[idx + 2] << 8);
idx += 2;
}
else
{
if (flags & TEXT2_VERTICAL)
y += xyoffset;
else
x += xyoffset;
}
}
if(glyph)
{
Display_DrawGlyph
(
mixmode,
x + (short)glyph->offset,
y + (short)glyph->baseline,
glyph->width,
glyph->height,
glyph->pixmap,
0,
0,
bgcolour,
fgcolour
);
if(flags & TEXT2_IMPLICIT_X)
x += glyph->width;
}
}
void Display_DrawText
(
uint8 font,
uint8 flags,
uint8 opcode,
int mixmode,
int x,
int y,
int clipx,
int clipy,
int clipcx,
int clipcy,
int boxx,
int boxy,
int boxcx,
int boxcy,
BRUSH * brush,
int bgcolour,
int fgcolour,
uint8 * text,
uint8 length
)
{
int i, j;
DATABLOB *entry;
HBRUSH hbr = CreateSolidBrush(bgcolour);
HGDIOBJ holdbrush = SelectObject(m_displayBuffer, hbr);
HGDIOBJ holdpen = SelectObject(m_displayBuffer, GetStockObject(NULL_PEN));
if (boxcx > 1)
Rectangle(m_displayBuffer, boxx, boxy, boxx + boxcx + 1, boxy + boxcy + 1);
else if (mixmode == MIX_OPAQUE)
Rectangle(m_displayBuffer, clipx, clipy, clipx + clipcx + 1, clipy + clipcy + 1);
SelectObject(m_displayBuffer, holdpen);
SelectObject(m_displayBuffer, holdbrush);
DeleteObject(hbr);
if(boxcx > 1)
Display_RepaintArea(boxx, boxy, boxcx, boxcy);
else
Display_RepaintArea(clipx, clipy, clipcx, clipcy);
/* Paint text, character by character */
for (i = 0; i < length;)
{
switch (text[i])
{
case 0xff:
/* At least two bytes needs to follow */
if (i + 3 > length)
{
warning("Skipping short 0xff command:");
for (j = 0; j < length; j++)
fprintf(stderr, "%02x ", text[j]);
fprintf(stderr, "\n");
i = length = 0;
break;
}
cache_put_text(NULL /* TODO */, text[i + 1], text, text[i + 2]);
i += 3;
length -= i;
/* this will move pointer from start to first character after FF command */
text = &(text[i]);
i = 0;
break;
case 0xfe:
/* At least one byte needs to follow */
if (i + 2 > length)
{
warning("Skipping short 0xfe command:");
for (j = 0; j < length; j++)
fprintf(stderr, "%02x ", text[j]);
fprintf(stderr, "\n");
i = length = 0;
break;
}
entry = cache_get_text(/*This*/NULL, text[i + 1]);
if (entry->data != NULL)
{
if ((((uint8 *) (entry->data))[1] == 0)
&& (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
{
if (flags & TEXT2_VERTICAL)
y += text[i + 2];
else
x += text[i + 2];
}
for (j = 0; j < entry->size; j++)
Display_DoGlyph(font, flags, mixmode, x, y, bgcolour, fgcolour, ((uint8 *) (entry->data)), j);
}
if (i + 2 < length)
i += 3;
else
i += 2;
length -= i;
/* this will move pointer from start to first character after FE command */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -