- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1273 lines
32 KiB
C++
1273 lines
32 KiB
C++
//----------------------------------------------------------------------------
|
|
// ObjectWindows - (C) Copyright 1991, 1993 by Borland International
|
|
// Example paint program
|
|
//----------------------------------------------------------------------------
|
|
#include <owl\owlpch.h>
|
|
#include <owl\applicat.h>
|
|
#include <owl\dc.h>
|
|
#include <owl\gdiobjec.h>
|
|
#include <owl\decframe.h>
|
|
#include <owl\chooseco.h>
|
|
#include <owl\choosefo.h>
|
|
#include <owl\opensave.h>
|
|
#include <owl\printdia.h>
|
|
#include <owl\scroller.h>
|
|
#include <owl\controlb.h>
|
|
#include <owl\floatfra.h>
|
|
#include <owl\toolbox.h>
|
|
#include <owl\buttonga.h>
|
|
#include <owl\editfile.rh>
|
|
#include <stdio.h>
|
|
#include <dir.h>
|
|
#include "paint.rh"
|
|
#include "dibattr.h"
|
|
|
|
DIAG_DEFINE_GROUP(PaintDrw,1,0); // drawing tracing (set level to 1 for mouse)
|
|
DIAG_DEFINE_GROUP(PaintCmd,1,0); // command tracing
|
|
|
|
|
|
//#define USE_TOOLBAR // comment out for floating palette
|
|
#define PARALLEL_PEN // to enable parallel line drawing with pen tool
|
|
|
|
const int DefWidth = 640;
|
|
const int DefHeight = 480;
|
|
int DefNColors= 0; // fill in with screen device info
|
|
const int DefPenSize= 3;
|
|
const TColor DefPalette[] = {
|
|
0x000000L, 0xFFFFFFL, 0x7F7F7FL, 0xC0C0C0L,
|
|
0x00007FL, 0x007F00L, 0x007F7FL, 0x7F0000L, 0x7F007FL, 0x7F7F00L,
|
|
0x0000FFL, 0x00FF00L, 0x00FFFFL, 0xFF0000L, 0xFF00FFL, 0xFFFF00L,
|
|
};
|
|
|
|
const int CM_TOOL = 300;
|
|
const int CM_LINE = 400;
|
|
const int ToolCount = 6;
|
|
|
|
const int ID_CANVAS = 101;
|
|
const int ID_PALETTE= 102;
|
|
|
|
#if defined(USE_LINEBAR)
|
|
const int LineCount = 8;
|
|
const int LineBarWidth = LineCount * 4 + 6 + (1 + 2 + 3 + 4 + 5 + 7 + 9 + 12);
|
|
const int LineWidth[LineCount] = { 1, 2, 3, 4, 5, 7, 9, 12 };
|
|
#endif
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class TDrawTool;
|
|
|
|
struct TState {
|
|
TDrawTool* DrawTool;
|
|
TDC* DC;
|
|
TPalette* Palette;
|
|
TDib* Dib;
|
|
TBitmap* Bitmap;
|
|
int PenSize;
|
|
int FgColor;
|
|
int BgColor;
|
|
string Name;
|
|
string Title;
|
|
BOOL Modified;
|
|
};
|
|
|
|
class TDrawTool {
|
|
public:
|
|
TDrawTool(const char* name);
|
|
|
|
void MouseDown(TWindow& window, const TPoint& point, TState* state);
|
|
void MouseMove(const TPoint& Point);
|
|
void MouseUp();
|
|
|
|
virtual void DrawBegin(const TPoint& point) {}
|
|
virtual void DrawTo(const TPoint& point) {}
|
|
virtual void DrawEnd() {}
|
|
|
|
const char* GetName() {return Name;}
|
|
|
|
protected:
|
|
TCursor* Cursor;
|
|
TIcon* Icon;
|
|
TState* State;
|
|
TWindow* Window;
|
|
TPen* Pen;
|
|
TBrush* Brush;
|
|
TDC* DC;
|
|
TPoint LastPoint;
|
|
TRect Bounds;
|
|
|
|
private:
|
|
const char* Name;
|
|
};
|
|
|
|
class TPenTool : public TDrawTool {
|
|
public:
|
|
TPenTool(const char* name) : TDrawTool(name) {}
|
|
|
|
virtual void DrawBegin(const TPoint& point);
|
|
virtual void DrawTo(const TPoint& point);
|
|
virtual void DrawEnd();
|
|
|
|
protected:
|
|
#if defined(PARALLEL_PEN)
|
|
TPalette* TmpPalette;
|
|
#endif
|
|
};
|
|
|
|
class TFillTool : public TDrawTool {
|
|
public:
|
|
TFillTool(const char* name) : TDrawTool(name) {}
|
|
virtual void DrawBegin(const TPoint& point);
|
|
};
|
|
|
|
class TBoxTool : public TDrawTool {
|
|
public:
|
|
TBoxTool(const char* name, BOOL filled)
|
|
: TDrawTool(name), Filled(filled) {}
|
|
|
|
virtual void DrawBegin(const TPoint& point);
|
|
virtual void DrawTo(const TPoint& point);
|
|
virtual void DrawEnd();
|
|
virtual void DrawObject(TDC& dc) {}
|
|
|
|
protected:
|
|
BOOL Filled;
|
|
int X1;
|
|
int Y1;
|
|
int X2;
|
|
int Y2;
|
|
};
|
|
|
|
class TRectTool : public TBoxTool {
|
|
public:
|
|
TRectTool(const char* name, BOOL filled) : TBoxTool(name, filled) {}
|
|
virtual void DrawObject(TDC& dc);
|
|
};
|
|
|
|
class TEllipseTool : public TBoxTool {
|
|
public:
|
|
TEllipseTool(const char* name, BOOL filled) : TBoxTool(name, filled) {}
|
|
virtual void DrawObject(TDC& dc);
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class TPaletteWindow : public TWindow {
|
|
public:
|
|
TPaletteWindow(TWindow* parent, TState* state);
|
|
void SelectColor(TPoint& point, int& color);
|
|
|
|
protected:
|
|
void Paint(TDC&, BOOL, TRect&);
|
|
|
|
void EvSize(UINT, TSize&);
|
|
void EvLButtonDown(UINT modKeys, TPoint& point);
|
|
void EvLButtonDblClk(UINT modKeys, TPoint&);
|
|
void EvRButtonDown(UINT modKeys, TPoint& point);
|
|
void EvRButtonDblClk(UINT modKeys, TPoint& point);
|
|
LRESULT EvSetRGB(WPARAM, LPARAM);
|
|
|
|
private:
|
|
TState* State;
|
|
BOOL Horz;
|
|
int Cx; // Count of panes in the X direction
|
|
int Cy; // Count of panes in the Y direction
|
|
int Dx; // Size of a pane in the X direction
|
|
int Dy; // Size of a pane in the Y direction
|
|
|
|
DECLARE_RESPONSE_TABLE(TPaletteWindow);
|
|
};
|
|
|
|
DEFINE_RESPONSE_TABLE1(TPaletteWindow, TWindow)
|
|
EV_WM_SIZE,
|
|
EV_WM_LBUTTONDOWN,
|
|
EV_WM_LBUTTONDBLCLK,
|
|
EV_WM_RBUTTONDOWN,
|
|
EV_WM_RBUTTONDBLCLK,
|
|
EV_REGISTERED(SETRGBSTRING, EvSetRGB),
|
|
END_RESPONSE_TABLE;
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
// A slightly customized floating frame for use as our tool & style button
|
|
// palettes.
|
|
//
|
|
class TButtonPalette : public TFloatingFrame {
|
|
public:
|
|
TButtonPalette(TWindow* parent,
|
|
char* title = 0,
|
|
TWindow* clientWnd = 0,
|
|
TModule* module = 0);
|
|
|
|
private:
|
|
void SetupWindow();
|
|
void CleanupWindow();
|
|
void EvClose();
|
|
|
|
DECLARE_RESPONSE_TABLE(TButtonPalette);
|
|
};
|
|
|
|
DEFINE_RESPONSE_TABLE1(TButtonPalette, TFloatingFrame)
|
|
EV_WM_CLOSE,
|
|
END_RESPONSE_TABLE;
|
|
TButtonPalette::TButtonPalette(TWindow* parent, char* title, TWindow* clientWnd,
|
|
TModule* module)
|
|
: TFloatingFrame(parent, title, clientWnd, TRUE, DefaultCaptionHeight, TRUE, module)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Supply a reasonable startup position relative to our Parent (owner actually)
|
|
//
|
|
void
|
|
TButtonPalette::SetupWindow()
|
|
{
|
|
TFloatingFrame::SetupWindow();
|
|
|
|
if (Attr.X < 0 || Attr.Y < 0) {
|
|
TRect parentRect;
|
|
Parent->GetWindowRect(parentRect);
|
|
SetWindowPos(0, parentRect.left+10, parentRect.top+10, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Remember latest position when we are destroyed
|
|
//
|
|
void
|
|
TButtonPalette::CleanupWindow()
|
|
{
|
|
TRect rect;
|
|
GetWindowRect(rect);
|
|
Attr.X = rect.left;
|
|
Attr.Y = rect.top;
|
|
|
|
TFloatingFrame::CleanupWindow();
|
|
}
|
|
|
|
//
|
|
// Override EvClose to keep TWindow from having us deleted
|
|
//
|
|
void
|
|
TButtonPalette::EvClose()
|
|
{
|
|
CloseWindow();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if defined(USE_LINEBAR)
|
|
class TLineBar : public TWindow {
|
|
public:
|
|
TLineBar(TWindow* parent, TState* state);
|
|
|
|
void Paint(TDC&, BOOL, TRect&);
|
|
void EvLButtonDown(UINT modKeys, TPoint& point);
|
|
|
|
private:
|
|
TState* State;
|
|
void Notch(TDC& dc, int x, int w, int y, int dy);
|
|
|
|
DECLARE_RESPONSE_TABLE(TLineBar);
|
|
};
|
|
|
|
DEFINE_RESPONSE_TABLE1(TLineBar, TWindow)
|
|
EV_WM_LBUTTONDOWN,
|
|
END_RESPONSE_TABLE;
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class TCanvas : public TWindow {
|
|
public:
|
|
TCanvas();
|
|
~TCanvas();
|
|
|
|
TState State;
|
|
|
|
protected:
|
|
// Override TWindow virtuals
|
|
//
|
|
void SetupWindow();
|
|
BOOL CanClose();
|
|
|
|
BOOL AbandonOk();
|
|
void SetupDib(TDib* dib, const char* fileName, const char* fileTitle);
|
|
void NewDib(int width, int height, int nColors);
|
|
void OpenDib(const char* fileName, const char* fileTitle);
|
|
BOOL SaveDib(const char* fileName);
|
|
|
|
void UpdateCaption();
|
|
void AdjustScroller();
|
|
void Paint(TDC&, BOOL, TRect&);
|
|
|
|
void EvSize(UINT, TSize&);
|
|
BOOL EvEraseBkgnd(HDC hDC);
|
|
void EvLButtonDown(UINT modKeys, TPoint& point);
|
|
void EvLButtonUp(UINT modKeys, TPoint& point);
|
|
void EvMouseMove(UINT modKeys, TPoint& point);
|
|
void EvDropFiles(TDropInfo dropInfo);
|
|
void EvSysColorChange();
|
|
|
|
void CmFileNew();
|
|
void CmFileOpen();
|
|
void CmFileSave();
|
|
void CmFileSaveAs();
|
|
void CmFilePrint();
|
|
void CmFilePrintSetup();
|
|
|
|
void CmViewTools();
|
|
void CeViewTools(TCommandEnabler& ce);
|
|
void CmViewLines();
|
|
void CeViewLines(TCommandEnabler& ce);
|
|
|
|
void CmTool(WPARAM);
|
|
void CmLine(WPARAM);
|
|
|
|
TPrintDialog::TData PrintData;
|
|
|
|
private:
|
|
BOOL Drawing;
|
|
TBrush* BkBrush;
|
|
TDrawTool* Tools[ToolCount];
|
|
|
|
TButtonPalette* ToolsPal;
|
|
TButtonPalette* LinesPal;
|
|
|
|
DECLARE_RESPONSE_TABLE(TCanvas);
|
|
};
|
|
|
|
DEFINE_RESPONSE_TABLE1(TCanvas, TWindow)
|
|
EV_WM_ERASEBKGND,
|
|
EV_WM_SIZE,
|
|
EV_WM_LBUTTONDOWN,
|
|
EV_WM_LBUTTONUP,
|
|
EV_WM_MOUSEMOVE,
|
|
EV_WM_DROPFILES,
|
|
EV_WM_SYSCOLORCHANGE,
|
|
EV_COMMAND_AND_ID(CM_TOOL+0, CmTool),
|
|
EV_COMMAND_AND_ID(CM_TOOL+1, CmTool),
|
|
EV_COMMAND_AND_ID(CM_TOOL+2, CmTool),
|
|
EV_COMMAND_AND_ID(CM_TOOL+3, CmTool),
|
|
EV_COMMAND_AND_ID(CM_TOOL+4, CmTool),
|
|
EV_COMMAND_AND_ID(CM_TOOL+5, CmTool),
|
|
EV_COMMAND_AND_ID(CM_LINE+1, CmLine),
|
|
EV_COMMAND_AND_ID(CM_LINE+3, CmLine),
|
|
EV_COMMAND_AND_ID(CM_LINE+5, CmLine),
|
|
EV_COMMAND_AND_ID(CM_LINE+7, CmLine),
|
|
EV_COMMAND_AND_ID(CM_LINE+9, CmLine),
|
|
EV_COMMAND_AND_ID(CM_LINE+11, CmLine),
|
|
EV_COMMAND(CM_FILENEW, CmFileNew),
|
|
EV_COMMAND(CM_FILEOPEN, CmFileOpen),
|
|
EV_COMMAND(CM_FILESAVE, CmFileSave),
|
|
EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
|
|
EV_COMMAND(CM_FILEPRINT, CmFilePrint),
|
|
EV_COMMAND(CM_FILEPRINTERSETUP, CmFilePrintSetup),
|
|
EV_COMMAND(CM_VIEWTOOLS, CmViewTools),
|
|
EV_COMMAND_ENABLE(CM_VIEWTOOLS, CeViewTools),
|
|
EV_COMMAND(CM_VIEWLINES, CmViewLines),
|
|
EV_COMMAND_ENABLE(CM_VIEWLINES, CeViewLines),
|
|
END_RESPONSE_TABLE;
|
|
|
|
// --------------- TDrawTool ------------------------
|
|
|
|
TDrawTool::TDrawTool(const char* name)
|
|
: State(0), Window(0), Pen(0), Brush(0), DC(0)
|
|
{
|
|
Name = name;
|
|
}
|
|
|
|
void
|
|
TDrawTool::MouseDown(TWindow& window, const TPoint& point, TState* state)
|
|
{
|
|
TRACEX(PaintDrw,0,"Draw " << GetName() <<
|
|
" started at (" << point.x << "," << point.y << ")");
|
|
Window = &window;
|
|
State = state;
|
|
Window->SetCapture();
|
|
|
|
DC = new TClientDC(window);
|
|
Pen = new TPen(TColor(State->FgColor), State->PenSize);
|
|
Brush = new TBrush(TColor(State->BgColor));
|
|
|
|
State->DC->SelectObject(*State->Palette);
|
|
State->DC->RealizePalette();
|
|
State->DC->SelectObject(*Pen);
|
|
State->DC->SelectObject(*Brush);
|
|
|
|
LastPoint = point;
|
|
Bounds = TRect(point, point);
|
|
DrawBegin(point);
|
|
}
|
|
|
|
void
|
|
TDrawTool::MouseMove(const TPoint& point)
|
|
{
|
|
TRACEX(PaintDrw,1,"Draw " << GetName() <<
|
|
" extends to (" << point.x << "," << point.y << ")");
|
|
Bounds |= TRect(point.x, point.y, point.x, point.y);
|
|
DrawTo(point);
|
|
LastPoint = point;
|
|
}
|
|
|
|
void
|
|
TDrawTool::MouseUp()
|
|
{
|
|
TRACEX(PaintDrw,1,"Draw " << GetName() << " finished");
|
|
DrawEnd();
|
|
|
|
Window->ReleaseCapture();
|
|
State->DC->RestoreObjects();
|
|
|
|
delete Brush; Brush = 0;
|
|
delete Pen; Pen = 0;
|
|
delete DC; DC = 0;
|
|
|
|
State->Modified = TRUE;
|
|
Window->InvalidateRect(Bounds.
|
|
InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2), FALSE);
|
|
Window->UpdateWindow();
|
|
}
|
|
|
|
|
|
// --------------- TPenTool ------------------------
|
|
|
|
void
|
|
TPenTool::DrawBegin(const TPoint& point)
|
|
{
|
|
State->DC->MoveTo(point);
|
|
|
|
// Do parallel update onto screen
|
|
//
|
|
#if defined(PARALLEL_PEN)
|
|
// can't select a palette into to different device DCs
|
|
TmpPalette = new TPalette(*State->Dib);
|
|
DC->IntersectClipRect(TRect(TPoint(0,0), State->Dib->Size()));
|
|
DC->SelectObject(*TmpPalette);
|
|
DC->RealizePalette();
|
|
|
|
DC->SelectObject(*Pen);
|
|
DC->MoveTo(point);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
TPenTool::DrawTo(const TPoint& point)
|
|
{
|
|
State->DC->LineTo(point);
|
|
#if defined(PARALLEL_PEN)
|
|
DC->LineTo(point);
|
|
#else
|
|
Window->InvalidateRect(TRect(LastPoint, point).Normalized().
|
|
InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2),FALSE);
|
|
Window->UpdateWindow();
|
|
#endif
|
|
}
|
|
|
|
void
|
|
TPenTool::DrawEnd()
|
|
{
|
|
State->DC->RestorePen();
|
|
#if defined(PARALLEL_PEN)
|
|
DC->RestorePen();
|
|
delete TmpPalette; TmpPalette = 0;
|
|
#endif
|
|
}
|
|
|
|
// --------------- TFillTool ------------------------
|
|
|
|
void
|
|
TFillTool::DrawBegin(const TPoint& point)
|
|
{
|
|
TBrush fgBrush(State->FgColor);
|
|
State->DC->SelectObject(fgBrush);
|
|
TColor surfaceColor(State->DC->GetPixel(point));
|
|
State->DC->ExtFloodFill(point, surfaceColor, FLOODFILLSURFACE);
|
|
Bounds = Window->GetClientRect();
|
|
State->DC->RestoreBrush();
|
|
}
|
|
|
|
|
|
// --------------- TBoxTool ------------------------
|
|
|
|
void
|
|
TBoxTool::DrawBegin(const TPoint& point)
|
|
{
|
|
X1 = X2 = point.x;
|
|
Y1 = Y2 = point.y;
|
|
DC->SelectStockObject(BLACK_PEN);
|
|
DC->SelectStockObject(NULL_BRUSH);
|
|
DC->SetROP2(R2_NOT);
|
|
DrawObject(*DC);
|
|
}
|
|
|
|
void
|
|
TBoxTool::DrawTo(const TPoint& point)
|
|
{
|
|
DrawObject(*DC);
|
|
X2 = point.x;
|
|
Y2 = point.y;
|
|
DrawObject(*DC);
|
|
}
|
|
|
|
void
|
|
TBoxTool::DrawEnd()
|
|
{
|
|
DrawObject(*DC);
|
|
DC->SetROP2(R2_COPYPEN);
|
|
State->DC->SelectObject(*Pen);
|
|
if (Filled)
|
|
State->DC->SelectObject(*Brush);
|
|
else
|
|
State->DC->SelectStockObject(NULL_BRUSH);
|
|
DrawObject(*State->DC);
|
|
}
|
|
|
|
// --------------- TRectTool ------------------------
|
|
|
|
void
|
|
TRectTool::DrawObject(TDC& dc)
|
|
{
|
|
dc.Rectangle(X1, Y1, X2, Y2);
|
|
}
|
|
|
|
// --------------- TEllipseTool ------------------------
|
|
|
|
void
|
|
TEllipseTool::DrawObject(TDC& dc)
|
|
{
|
|
dc.Ellipse(X1, Y1, X2, Y2);
|
|
}
|
|
|
|
// --------------- TPaletteWindow ------------------------
|
|
|
|
TPaletteWindow::TPaletteWindow(TWindow* parent, TState* state)
|
|
: TWindow(parent),
|
|
State(state)
|
|
{
|
|
Attr.Style |= WS_BORDER;
|
|
Attr.W = 50;
|
|
Attr.H = 50;
|
|
Attr.Id = ID_PALETTE;
|
|
}
|
|
|
|
void
|
|
TPaletteWindow::EvSize(UINT, TSize&)
|
|
{
|
|
TRect rect = GetClientRect();
|
|
Horz = TRUE; // Location==Top || Location==Bottom;
|
|
Cx = (Horz ? 17 : 3);
|
|
Cy = (Horz ? 3 : 17);
|
|
Dx = rect.right / Cx;
|
|
Dy = rect.bottom / Cy;
|
|
if (Horz)
|
|
Cx--;
|
|
else
|
|
Cy--;
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void
|
|
TPaletteWindow::Paint(TDC& dc, BOOL, TRect&)
|
|
{
|
|
dc.SelectObject(*State->Palette);
|
|
dc.RealizePalette();
|
|
|
|
TRect rect = GetClientRect();
|
|
|
|
dc.SelectStockObject(BLACK_PEN);
|
|
|
|
// Paint color selection cells, each with a black frame
|
|
//
|
|
for (int i = 0; i < 16; i++)
|
|
for (int j = 0; j < 3; j++) {
|
|
TBrush brush(TColor(j*16+i));
|
|
dc.SelectObject(brush);
|
|
TPoint p = Horz ? TPoint(i*Dx, j*Dy) : TPoint(j*Dx, i*Dy);
|
|
dc.Rectangle(p, TSize(Dx+1, Dy+1));
|
|
dc.RestoreBrush();
|
|
}
|
|
|
|
// Paint pen & brush color display, frame first
|
|
//
|
|
dc.SelectStockObject(NULL_BRUSH);
|
|
TPoint p = Horz ? TPoint(Dx*16, 0) : TPoint(0, Dy*16);
|
|
dc.Rectangle(p, rect.BottomRight());
|
|
|
|
TPen pen(TColor(State->BgColor), 5);
|
|
dc.SelectObject(pen);
|
|
TBrush brush(TColor(State->FgColor));
|
|
dc.SelectObject(brush);
|
|
p += TSize(3,3);
|
|
dc.Rectangle(p, TPoint(rect.right-3, rect.bottom-3));
|
|
|
|
dc.RestoreObjects();
|
|
}
|
|
|
|
void
|
|
TPaletteWindow::SelectColor(TPoint& point, int& color)
|
|
{
|
|
point.x /= Dx;
|
|
point.y /= Dy;
|
|
if (point.x < Cx && point.y < Cy) {
|
|
int newColor = Horz ? point.x + point.y*Cx : point.x*Cy + point.y;
|
|
if (color != newColor) {
|
|
TColor c = State->Dib->GetColor(newColor);
|
|
|
|
InvalidateRect(Horz ? TRect(TPoint(Dx*Cx, 0), GetClientRect().BottomRight()) :
|
|
TRect(TPoint(0, Dy*Cy), GetClientRect().BottomRight()),
|
|
FALSE);
|
|
color = newColor;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
TPaletteWindow::EvLButtonDown(UINT, TPoint& point)
|
|
{
|
|
SelectColor(point, State->FgColor);
|
|
}
|
|
|
|
void
|
|
TPaletteWindow::EvLButtonDblClk(UINT, TPoint& point)
|
|
{
|
|
static TColor CustColors[32];
|
|
|
|
int editColor = -1;
|
|
SelectColor(point, editColor);
|
|
if (editColor < 0)
|
|
return;
|
|
TChooseColorDialog::TData choose;
|
|
choose.Flags = CC_RGBINIT;
|
|
PALETTEENTRY pe;
|
|
State->Palette->GetPaletteEntry((WORD)editColor, pe);
|
|
choose.Color = pe;
|
|
choose.CustColors = CustColors;
|
|
|
|
if (TChooseColorDialog(this, choose).Execute() == IDOK) {
|
|
State->Dib->SetColor(editColor, choose.Color);
|
|
delete State->Palette;
|
|
State->Palette = new TPalette(*State->Dib);
|
|
Invalidate(FALSE);
|
|
TWindow* canvas = Parent->ChildWithId(ID_CANVAS);
|
|
if (canvas && canvas->HWindow)
|
|
canvas->Invalidate(FALSE);
|
|
}
|
|
}
|
|
|
|
void
|
|
TPaletteWindow::EvRButtonDown(UINT, TPoint& point)
|
|
{
|
|
SelectColor(point, State->BgColor);
|
|
}
|
|
|
|
void
|
|
TPaletteWindow::EvRButtonDblClk(UINT modKeys, TPoint& point)
|
|
{
|
|
EvLButtonDblClk(modKeys, point);
|
|
}
|
|
|
|
LRESULT
|
|
TPaletteWindow::EvSetRGB(WPARAM, LPARAM)
|
|
{
|
|
Invalidate(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
#if defined(USE_LINEBAR)
|
|
// --------------- TLineBar ------------------------
|
|
|
|
TLineBar::TLineBar(TWindow* parent, TState* state)
|
|
: TWindow(parent),
|
|
State(state)
|
|
{
|
|
Attr.Style |= WS_BORDER;
|
|
Attr.W = 32;
|
|
Attr.H = 32;
|
|
}
|
|
|
|
void
|
|
TLineBar::Notch(TDC& dc, int x, int w, int y, int dy)
|
|
{
|
|
for (int l = 3; l >= 0; l--) {
|
|
dc.MoveTo(TPoint(x + w / 2 - l, y));
|
|
dc.LineTo(TPoint(x + w / 2 + l + 1, y));
|
|
y += dy;
|
|
}
|
|
}
|
|
|
|
void
|
|
TLineBar::Paint(TDC& dc, BOOL, TRect&)
|
|
{
|
|
int x = 4;
|
|
dc.SelectStockObject(WHITE_BRUSH);
|
|
dc.PatBlt(TRect(0, 0, Attr.W, Attr.H));
|
|
dc.SelectStockObject(BLACK_BRUSH);
|
|
for (int i = 0; i < LineCount; i++) {
|
|
int w = LineWidth[i];
|
|
dc.PatBlt(TRect(x, 5, x + w, 25));
|
|
if (w == State->PenSize) {
|
|
Notch(dc, x, w, 0, 1);
|
|
Notch(dc, x, w, 29, -1);
|
|
}
|
|
x += w + 4;
|
|
}
|
|
}
|
|
|
|
void
|
|
TLineBar::EvLButtonDown(UINT, TPoint& point)
|
|
{
|
|
int x = 2;
|
|
for (int i = 0; i < LineCount; i++) {
|
|
int w = LineWidth[i];
|
|
if (point.x >= x && point.x < x+w+4) {
|
|
TRACEX(PaintCmd,0,"Width = " << w);
|
|
State->PenSize = w;
|
|
Invalidate(FALSE);
|
|
return;
|
|
}
|
|
x += w + 4;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
// --------------- TCanvas ------------------------
|
|
|
|
TCanvas::TCanvas()
|
|
: TWindow(0, 0, 0),
|
|
Drawing(FALSE)
|
|
{
|
|
BkBrush = 0;
|
|
EvSysColorChange();
|
|
|
|
State.DrawTool = 0;
|
|
State.Dib = 0;
|
|
State.Bitmap = 0;
|
|
State.DC = 0;
|
|
State.Palette = 0;
|
|
State.PenSize = DefPenSize;
|
|
State.FgColor = 0;
|
|
State.BgColor = 1;
|
|
State.Name = State.Title = "";
|
|
|
|
Scroller = 0;
|
|
|
|
Tools[0] = new TPenTool("Pen");
|
|
Tools[1] = new TFillTool("Fill");
|
|
Tools[2] = new TRectTool("Rect", FALSE);
|
|
Tools[3] = new TRectTool("FillRect", TRUE);
|
|
Tools[4] = new TEllipseTool("Ellipse", FALSE);
|
|
Tools[5] = new TEllipseTool("FillEllipse", TRUE);
|
|
State.DrawTool = Tools[0];
|
|
|
|
Attr.Id = ID_CANVAS;
|
|
|
|
#if !defined(USE_TOOLBAR)
|
|
TToolBox* tb = new TToolBox(0);
|
|
tb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive,
|
|
TRUE, TButtonGadget::Down));
|
|
tb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive, TRUE));
|
|
ToolsPal = new TButtonPalette(this, "", tb);
|
|
|
|
tb = new TToolBox(0);
|
|
tb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive,
|
|
TRUE, TButtonGadget::Down));
|
|
tb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive, TRUE));
|
|
tb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive, TRUE));
|
|
LinesPal = new TButtonPalette(this, "", tb);
|
|
#else
|
|
ToolsPal = LinesPal = 0;
|
|
#endif
|
|
}
|
|
|
|
TCanvas::~TCanvas()
|
|
{
|
|
delete State.DC;
|
|
delete State.Palette;
|
|
delete State.Dib;
|
|
delete State.Bitmap;
|
|
delete BkBrush;
|
|
|
|
for (int i = 0; i < ToolCount; i++)
|
|
delete Tools[i];
|
|
}
|
|
|
|
void
|
|
TCanvas::SetupWindow()
|
|
{
|
|
TWindow::SetupWindow();
|
|
NewDib(DefWidth, DefHeight, DefNColors);
|
|
DragAcceptFiles(TRUE);
|
|
|
|
//
|
|
// A scroller on the client area would be nice...
|
|
//
|
|
//Scroller = new TScroller(this,1,1, State.Dib->Width(), State.Dib->Height());
|
|
SetFocus();
|
|
}
|
|
|
|
BOOL
|
|
TCanvas::CanClose()
|
|
{
|
|
return AbandonOk();
|
|
}
|
|
|
|
BOOL
|
|
TCanvas::AbandonOk()
|
|
{
|
|
if (!State.Modified)
|
|
return TRUE;
|
|
const char msgFrmt[] = "%s\nThe image has changed.\n\n"
|
|
"Do you want to save current changes?";
|
|
char msg[sizeof(msgFrmt)+20];
|
|
sprintf(msg, msgFrmt, State.Name.c_str());
|
|
int resp = MessageBox(msg, GetApplication()->GetName(),
|
|
MB_ICONEXCLAMATION|MB_YESNOCANCEL);
|
|
if (resp == IDYES)
|
|
CmFileSave();
|
|
|
|
return resp != IDCANCEL;
|
|
}
|
|
|
|
//
|
|
// Setup state info given a new dib. Assumes ownership of the dib.
|
|
//
|
|
void
|
|
TCanvas::SetupDib(TDib* dib, const char* name, const char* title)
|
|
{
|
|
//
|
|
// Make sure we can get the Dib DC and palette before we commit to this dib.
|
|
// Revert to a DDB and a memory DC if we can't create a DIB DC.
|
|
//
|
|
TDC* newDC;
|
|
TBitmap* newBM = 0;
|
|
TPalette* newPalette;
|
|
try {
|
|
newDC = new TDibDC(*dib);
|
|
}
|
|
catch (TGdiObject::TXGdi&) {
|
|
newDC = new TMemoryDC;
|
|
newBM = new TBitmap(TScreenDC(), *dib);
|
|
((TMemoryDC*)newDC)->SelectObject(*newBM);
|
|
newDC->SetDIBits(*newBM, *dib);
|
|
if (dib->NumColors() > NColors(WORD(newBM->Planes()*newBM->BitsPixel())))
|
|
MessageBox("Colors may have been lost during bitmap conversion.",
|
|
GetApplication()->GetName(), MB_ICONEXCLAMATION|MB_OK);
|
|
}
|
|
newPalette = new TPalette(*dib);
|
|
delete State.DC;
|
|
delete State.Palette;
|
|
delete State.Dib;
|
|
delete State.Bitmap;
|
|
State.DC = newDC;
|
|
State.Palette = newPalette;
|
|
State.Dib = dib;
|
|
State.Bitmap = newBM;
|
|
|
|
State.Name = name;
|
|
State.Title = title;
|
|
State.Modified = FALSE;
|
|
UpdateCaption();
|
|
AdjustScroller();
|
|
TWindow* palette = Parent->ChildWithId(ID_PALETTE);
|
|
if (palette && palette->HWindow)
|
|
palette->Invalidate(FALSE);
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
//
|
|
// Create a new dib & setup state info
|
|
//
|
|
void
|
|
TCanvas::NewDib(int width, int height, int nColors)
|
|
{
|
|
//
|
|
// Construct the dib, catching any exptions that might occur & displaying a
|
|
// warning
|
|
//
|
|
TDib* dib;
|
|
try {
|
|
dib = new TDib(width, height, nColors);
|
|
}
|
|
catch (TGdiObject::TXGdi& x) {
|
|
MessageBox("Could Not Create DIB", GetApplication()->GetName(), MB_OK);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Setup a nice palette
|
|
//
|
|
for (int i = 0; i < min(nColors, int(sizeof DefPalette)); i++)
|
|
dib->SetColor(i, DefPalette[i]);
|
|
|
|
SetupDib(dib, "", "(Untitled)");
|
|
|
|
TBrush brush(TColor(State.BgColor));
|
|
State.DC->SelectObject(*State.Palette);
|
|
State.DC->RealizePalette();
|
|
State.DC->SelectObject(brush);
|
|
State.DC->PatBlt(TRect(TPoint(0,0), State.Dib->Size()));
|
|
State.DC->RestoreObjects();
|
|
}
|
|
|
|
//
|
|
// Open a dib & setup state info given a dib filename & title
|
|
//
|
|
void
|
|
TCanvas::OpenDib(const char* fileName, const char* fileTitle)
|
|
{
|
|
TDib* dib;
|
|
try {
|
|
dib = new TDib(fileName);
|
|
}
|
|
catch (TGdiObject::TXGdi& x) {
|
|
MessageBox("Invalid Bitmap File", GetApplication()->GetName(), MB_OK);
|
|
return;
|
|
}
|
|
|
|
SetupDib(dib, fileName, fileTitle);
|
|
}
|
|
|
|
BOOL
|
|
TCanvas::SaveDib(const char* fileName)
|
|
{
|
|
if (State.Bitmap) {
|
|
delete State.Dib;
|
|
State.Dib = new TDib(*State.Bitmap, State.Palette);
|
|
}
|
|
if (State.Dib->WriteFile(fileName))
|
|
return TRUE;
|
|
MessageBox("Disk error saving bitmap!", GetApplication()->GetName(), MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
TCanvas::UpdateCaption()
|
|
{
|
|
char captionBuffer[70];
|
|
if (State.Dib)
|
|
wsprintf(captionBuffer, "%s - %s [%dx%dx%d]", GetApplication()->GetName(),
|
|
(LPCSTR)State.Title.c_str(),
|
|
State.Dib->Width(), State.Dib->Height(), State.Dib->NumColors());
|
|
else
|
|
sprintf(captionBuffer, "%s - (Bad Dib!)", GetApplication()->GetName());
|
|
Parent->SetCaption(captionBuffer);
|
|
}
|
|
|
|
void
|
|
TCanvas::AdjustScroller()
|
|
{
|
|
if (!Scroller)
|
|
return;
|
|
|
|
TRect clientRect = GetClientRect();
|
|
|
|
// only show scrollbars when image is larger than
|
|
// the client area and we are not stretching to fit.
|
|
//
|
|
TPoint range(Max(State.Dib->Width()-clientRect.Width(), 0),
|
|
Max(State.Dib->Height()-clientRect.Height(), 0));
|
|
Scroller->SetRange(range.x, range.y);
|
|
Scroller->ScrollTo(0, 0);
|
|
if (!GetUpdateRect(clientRect, FALSE))
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void
|
|
TCanvas::EvSize(UINT SizeType, TSize& Size)
|
|
{
|
|
TWindow::EvSize(SizeType, Size);
|
|
if (SizeType != SIZEICONIC)
|
|
AdjustScroller();
|
|
}
|
|
|
|
BOOL
|
|
TCanvas::EvEraseBkgnd(HDC /*hDC*/)
|
|
{
|
|
// Wait until paint to erase as we blit
|
|
//::FillRect(hDC, GetClientRect(), *BkBrush);
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
TCanvas::Paint(TDC& dc, BOOL, TRect&)
|
|
{
|
|
TRect drect(TPoint(0,0), State.Dib->Size());
|
|
TRect crect = GetClientRect();
|
|
if (Scroller)
|
|
crect += TPoint((int)Scroller->XPos, (int)Scroller->YPos);
|
|
|
|
// optimize this painting!
|
|
//TRect prect(rect);
|
|
//drect &= prect;
|
|
dc.SelectObject(*State.Palette);
|
|
dc.RealizePalette();
|
|
|
|
// Blit the DDB or DIB from the working DC to the screen
|
|
//
|
|
if (State.Bitmap)
|
|
dc.BitBlt(drect, *State.DC, TPoint(0,0));
|
|
else
|
|
dc.SetDIBitsToDevice(drect, TPoint(0,0), *State.Dib);
|
|
|
|
// Paint around the canvas
|
|
//
|
|
dc.SelectObject(*BkBrush);
|
|
dc.PatBlt(TRect(drect.right, 0, crect.right, crect.bottom));
|
|
dc.PatBlt(TRect(0, drect.bottom, crect.right, crect.bottom));
|
|
|
|
dc.RestoreObjects();
|
|
}
|
|
|
|
void
|
|
TCanvas::EvLButtonDown(UINT modKeys, TPoint& point)
|
|
{
|
|
TWindow::EvLButtonDown(modKeys, point);
|
|
if (!Drawing) {
|
|
Drawing = TRUE;
|
|
State.DrawTool->MouseDown(*this, point, &State);
|
|
}
|
|
}
|
|
|
|
void
|
|
TCanvas::EvMouseMove(UINT, TPoint& point)
|
|
{
|
|
if (Drawing)
|
|
State.DrawTool->MouseMove(point);
|
|
}
|
|
|
|
void
|
|
TCanvas::EvLButtonUp(UINT, TPoint& point)
|
|
{
|
|
if (Drawing) {
|
|
State.DrawTool->MouseMove(point);
|
|
State.DrawTool->MouseUp();
|
|
Drawing = FALSE;
|
|
}
|
|
}
|
|
|
|
void
|
|
TCanvas::EvDropFiles(TDropInfo dropInfo)
|
|
{
|
|
int totalNumberOfFiles = dropInfo.DragQueryFileCount();
|
|
if (totalNumberOfFiles == 1 && AbandonOk()) {
|
|
char filePath[MAXPATH+1];
|
|
char fileTitle[MAXFILE];
|
|
dropInfo.DragQueryFile(0, filePath, MAXPATH + 1);
|
|
fnsplit(filePath, 0, 0, fileTitle, 0);
|
|
OpenDib(filePath, fileTitle);
|
|
}
|
|
dropInfo.DragFinish();
|
|
}
|
|
|
|
void
|
|
TCanvas::EvSysColorChange()
|
|
{
|
|
delete BkBrush;
|
|
BkBrush = new TBrush(::GetSysColor(COLOR_APPWORKSPACE)); //COLOR_WINDOW
|
|
}
|
|
|
|
void
|
|
TCanvas::CmTool(WPARAM toolCmd)
|
|
{
|
|
int i = toolCmd - CM_TOOL;
|
|
TRACEX(PaintCmd,0, "Tool = " << Tools[i]->GetName());
|
|
State.DrawTool = Tools[i];
|
|
|
|
SetCursor(GetModule(), toolCmd);
|
|
}
|
|
|
|
void
|
|
TCanvas::CmLine(WPARAM lineCmd)
|
|
{
|
|
State.PenSize = lineCmd - CM_LINE;
|
|
}
|
|
|
|
void
|
|
TCanvas::CmFileNew()
|
|
{
|
|
TRACEX(PaintCmd,0,"CmFileNew()");
|
|
if (!AbandonOk())
|
|
return;
|
|
|
|
static int width = DefWidth;
|
|
static int height = DefHeight;
|
|
static int ncolors = DefNColors;
|
|
if (TDibAttrDialog(this, width, height, ncolors).Execute() == IDOK)
|
|
NewDib(width, height, ncolors);
|
|
}
|
|
|
|
void
|
|
TCanvas::CmFileOpen()
|
|
{
|
|
TRACEX(PaintCmd,0,"CmFileOpen()");
|
|
if (!AbandonOk())
|
|
return;
|
|
|
|
TOpenSaveDialog::TData data (
|
|
OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOREADONLYRETURN,
|
|
"Bitmap Files (*.BMP)|*.bmp|",
|
|
0,
|
|
"",
|
|
"BMP"
|
|
);
|
|
if (TFileOpenDialog(this, data).Execute() == IDOK) {
|
|
char fileTitle[MAXPATH];
|
|
TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
|
|
OpenDib(data.FileName, fileTitle);
|
|
}
|
|
}
|
|
|
|
void
|
|
TCanvas::CmFileSave()
|
|
{
|
|
TRACEX(PaintCmd,0,"CmFileSave()");
|
|
if (State.Modified) {
|
|
if (!State.Name.length()) {
|
|
CmFileSaveAs();
|
|
return;
|
|
}
|
|
|
|
if (SaveDib(State.Name.c_str()))
|
|
State.Modified = FALSE;
|
|
}
|
|
}
|
|
|
|
void
|
|
TCanvas::CmFileSaveAs()
|
|
{
|
|
TRACEX(PaintCmd,0,"CmFileSaveAs()");
|
|
TOpenSaveDialog::TData data (
|
|
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
|
|
"Bitmap Files (*.BMP)|*.bmp|",
|
|
0,
|
|
"",
|
|
"BMP"
|
|
);
|
|
if (TFileSaveDialog(this, data).Execute() == IDOK) {
|
|
if (SaveDib(data.FileName)) {
|
|
State.Name = data.FileName;
|
|
State.Modified = FALSE;
|
|
char fileTitle[MAXPATH];
|
|
TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
|
|
State.Title = fileTitle;
|
|
UpdateCaption();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
TCanvas::CmFilePrint()
|
|
{
|
|
TRACEX(PaintCmd, 0, "CmFilePrint()");
|
|
PrintData.Flags &= ~PD_PRINTSETUP;
|
|
if (TPrintDialog(this, PrintData).Execute() == IDOK) {
|
|
MessageBox("No File|Print yet...", GetApplication()->GetName(), MB_OK);
|
|
}
|
|
}
|
|
|
|
void
|
|
TCanvas::CmFilePrintSetup()
|
|
{
|
|
TRACEX(PaintCmd, 0, "CmFilePrintSetup()");
|
|
PrintData.Flags |= PD_PRINTSETUP;
|
|
TPrintDialog(this, PrintData, 0).Execute();
|
|
}
|
|
|
|
void
|
|
TCanvas::CmViewTools()
|
|
{
|
|
if (ToolsPal->HWindow)
|
|
ToolsPal->Destroy();
|
|
else
|
|
ToolsPal->Create();
|
|
}
|
|
|
|
void
|
|
TCanvas::CeViewTools(TCommandEnabler& ce)
|
|
{
|
|
ce.SetCheck(ToolsPal->HWindow ?
|
|
TCommandEnabler::Checked : TCommandEnabler::Unchecked);
|
|
}
|
|
|
|
void
|
|
TCanvas::CmViewLines()
|
|
{
|
|
if (LinesPal->HWindow)
|
|
LinesPal->Destroy();
|
|
else
|
|
LinesPal->Create();
|
|
}
|
|
|
|
void
|
|
TCanvas::CeViewLines(TCommandEnabler& ce)
|
|
{
|
|
ce.SetCheck(LinesPal->HWindow ?
|
|
TCommandEnabler::Checked : TCommandEnabler::Unchecked);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class TPaintApp : public TApplication {
|
|
public:
|
|
TPaintApp() : TApplication("OWL Paint") {}
|
|
void InitMainWindow();
|
|
};
|
|
|
|
void TPaintApp::InitMainWindow()
|
|
{
|
|
TCanvas& client = *new TCanvas;
|
|
TDecoratedFrame* frame = new TDecoratedFrame(0, Name, &client);
|
|
MainWindow = frame;
|
|
|
|
#if defined(USE_TOOLBAR)
|
|
TControlBar* cb = new TControlBar(frame);
|
|
cb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive,
|
|
FALSE, TButtonGadget::Down));
|
|
cb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive));
|
|
#if !defined(USE_LINEBAR)
|
|
cb->Insert(*new TSeparatorGadget);
|
|
cb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive,
|
|
FALSE, TButtonGadget::Down));
|
|
cb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive));
|
|
cb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive));
|
|
#endif
|
|
frame->Insert(*cb, TDecoratedFrame::Top);
|
|
#endif
|
|
|
|
frame->Insert(*new TPaletteWindow(frame, &client.State), TDecoratedFrame::Bottom);
|
|
#if defined(USE_LINEBAR)
|
|
frame->Insert(*new TLineBar(frame, &client.State), TDecoratedFrame::Bottom);
|
|
#endif
|
|
|
|
MainWindow->AssignMenu("PaintMenu");
|
|
MainWindow->Attr.AccelTable = "PaintAccels";
|
|
MainWindow->SetIcon(this, "PaintIcon");
|
|
}
|
|
|
|
int
|
|
OwlMain(int /*argc*/, char* /*argv*/ [])
|
|
{
|
|
TScreenDC screenDC;
|
|
DefNColors = (int)NColors(WORD(screenDC.GetDeviceCaps(BITSPIXEL)*screenDC.GetDeviceCaps(PLANES)));
|
|
return TPaintApp().Run();
|
|
}
|