home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / PAINT.PAK / PAINT.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  33KB  |  1,273 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //   Example paint program
  4. //----------------------------------------------------------------------------
  5. #include <owl\owlpch.h>
  6. #include <owl\applicat.h>
  7. #include <owl\dc.h>
  8. #include <owl\gdiobjec.h>
  9. #include <owl\decframe.h>
  10. #include <owl\chooseco.h>
  11. #include <owl\choosefo.h>           
  12. #include <owl\opensave.h>
  13. #include <owl\printdia.h>
  14. #include <owl\scroller.h>               
  15. #include <owl\controlb.h>               
  16. #include <owl\floatfra.h>               
  17. #include <owl\toolbox.h>               
  18. #include <owl\buttonga.h>               
  19. #include <owl\editfile.rh>
  20. #include <stdio.h>
  21. #include <dir.h>
  22. #include "paint.rh"
  23. #include "dibattr.h"
  24.  
  25. DIAG_DEFINE_GROUP(PaintDrw,1,0);  // drawing tracing (set level to 1 for mouse)
  26. DIAG_DEFINE_GROUP(PaintCmd,1,0);  // command tracing
  27.  
  28.  
  29. //#define USE_TOOLBAR       // comment out for floating palette
  30. #define PARALLEL_PEN      // to enable parallel line drawing with pen tool
  31.  
  32. const int DefWidth  = 640;
  33. const int DefHeight = 480;
  34.       int DefNColors= 0;        // fill in with screen device info
  35. const int DefPenSize= 3;
  36. const TColor DefPalette[] = {
  37.   0x000000L, 0xFFFFFFL, 0x7F7F7FL, 0xC0C0C0L, 
  38.   0x00007FL, 0x007F00L, 0x007F7FL, 0x7F0000L, 0x7F007FL, 0x7F7F00L,
  39.   0x0000FFL, 0x00FF00L, 0x00FFFFL, 0xFF0000L, 0xFF00FFL, 0xFFFF00L,
  40. };
  41.  
  42. const int CM_TOOL   = 300;
  43. const int CM_LINE   = 400;
  44. const int ToolCount = 6;
  45.  
  46. const int ID_CANVAS = 101;
  47. const int ID_PALETTE= 102;
  48.  
  49. #if defined(USE_LINEBAR)
  50. const int LineCount = 8;
  51. const int LineBarWidth = LineCount * 4 + 6 + (1 + 2 + 3 + 4 + 5 + 7 + 9 + 12);
  52. const int LineWidth[LineCount] = { 1, 2, 3, 4, 5, 7, 9, 12 };
  53. #endif
  54.  
  55.  
  56. //----------------------------------------------------------------------------
  57.  
  58. class TDrawTool;
  59.  
  60. struct TState {
  61.     TDrawTool*  DrawTool;
  62.     TDC*        DC;
  63.     TPalette*   Palette;
  64.     TDib*       Dib;
  65.     TBitmap*    Bitmap;
  66.     int         PenSize;
  67.     int         FgColor;
  68.     int         BgColor;
  69.     string      Name;
  70.     string      Title;
  71.     BOOL        Modified;
  72. };
  73.  
  74. class TDrawTool {
  75.   public:
  76.     TDrawTool(const char* name);
  77.  
  78.     void      MouseDown(TWindow& window, const TPoint& point, TState* state);
  79.     void      MouseMove(const TPoint& Point);
  80.     void      MouseUp();
  81.  
  82.     virtual void DrawBegin(const TPoint& point) {}
  83.     virtual void DrawTo(const TPoint& point) {}
  84.     virtual void DrawEnd() {}
  85.  
  86.     const char*  GetName() {return Name;}
  87.  
  88.   protected:
  89.     TCursor*     Cursor;
  90.     TIcon*       Icon;
  91.     TState*      State;
  92.     TWindow*     Window;
  93.     TPen*        Pen;
  94.     TBrush*      Brush;
  95.     TDC*         DC;
  96.     TPoint       LastPoint;
  97.     TRect        Bounds;
  98.  
  99.   private:
  100.     const char*  Name;
  101. };
  102.  
  103. class TPenTool : public TDrawTool {
  104.   public:
  105.     TPenTool(const char* name) : TDrawTool(name) {}
  106.  
  107.     virtual void    DrawBegin(const TPoint& point);
  108.     virtual void    DrawTo(const TPoint& point);
  109.     virtual void    DrawEnd();
  110.  
  111.   protected:
  112. #if defined(PARALLEL_PEN)
  113.     TPalette*       TmpPalette;
  114. #endif
  115. };
  116.  
  117. class TFillTool : public TDrawTool {
  118.   public:
  119.     TFillTool(const char* name) : TDrawTool(name) {}
  120.     virtual void    DrawBegin(const TPoint& point);
  121. };
  122.  
  123. class TBoxTool : public TDrawTool {
  124.   public:
  125.     TBoxTool(const char* name, BOOL filled)
  126.              : TDrawTool(name), Filled(filled) {}
  127.  
  128.     virtual void    DrawBegin(const TPoint& point);
  129.     virtual void    DrawTo(const TPoint& point);
  130.     virtual void    DrawEnd();
  131.     virtual void    DrawObject(TDC& dc) {}
  132.  
  133.   protected:
  134.     BOOL        Filled;
  135.     int         X1;
  136.     int         Y1;
  137.     int         X2;
  138.     int         Y2;
  139. };
  140.  
  141. class TRectTool : public TBoxTool {
  142.   public:
  143.     TRectTool(const char* name, BOOL filled) : TBoxTool(name, filled) {}
  144.     virtual void DrawObject(TDC& dc);
  145. };
  146.  
  147. class TEllipseTool : public TBoxTool {
  148.   public:
  149.     TEllipseTool(const char* name, BOOL filled) : TBoxTool(name, filled) {}
  150.     virtual void DrawObject(TDC& dc);
  151. };
  152.  
  153. //----------------------------------------------------------------------------
  154.  
  155. class TPaletteWindow : public TWindow {
  156.   public:
  157.     TPaletteWindow(TWindow* parent, TState* state);
  158.     void         SelectColor(TPoint& point, int& color);
  159.  
  160.   protected:
  161.     void         Paint(TDC&, BOOL, TRect&);
  162.  
  163.     void         EvSize(UINT, TSize&);
  164.     void         EvLButtonDown(UINT modKeys, TPoint& point);
  165.     void         EvLButtonDblClk(UINT modKeys, TPoint&);
  166.     void         EvRButtonDown(UINT modKeys, TPoint& point);
  167.     void         EvRButtonDblClk(UINT modKeys, TPoint& point);
  168.     LRESULT      EvSetRGB(WPARAM, LPARAM);
  169.  
  170.   private:
  171.     TState*      State;
  172.     BOOL         Horz;
  173.     int          Cx;      // Count of panes in the X direction
  174.     int          Cy;      // Count of panes in the Y direction
  175.     int          Dx;      // Size of a pane in the X direction
  176.     int          Dy;      // Size of a pane in the Y direction
  177.  
  178.   DECLARE_RESPONSE_TABLE(TPaletteWindow);
  179. };
  180.  
  181. DEFINE_RESPONSE_TABLE1(TPaletteWindow, TWindow)
  182.   EV_WM_SIZE,
  183.   EV_WM_LBUTTONDOWN,
  184.   EV_WM_LBUTTONDBLCLK,
  185.   EV_WM_RBUTTONDOWN,
  186.   EV_WM_RBUTTONDBLCLK,
  187.   EV_REGISTERED(SETRGBSTRING, EvSetRGB),
  188. END_RESPONSE_TABLE;
  189.  
  190. //----------------------------------------------------------------------------
  191.  
  192. //
  193. // A slightly customized floating frame for use as our tool & style button
  194. // palettes.
  195. //
  196. class TButtonPalette : public TFloatingFrame {
  197.   public:
  198.     TButtonPalette(TWindow*        parent,
  199.                    char*           title = 0,
  200.                    TWindow*        clientWnd = 0,
  201.                    TModule*        module = 0);
  202.  
  203.   private:
  204.     void SetupWindow();
  205.     void CleanupWindow();
  206.     void EvClose();
  207.  
  208.   DECLARE_RESPONSE_TABLE(TButtonPalette);
  209. };
  210.  
  211. DEFINE_RESPONSE_TABLE1(TButtonPalette, TFloatingFrame)
  212.   EV_WM_CLOSE,
  213. END_RESPONSE_TABLE;
  214. TButtonPalette::TButtonPalette(TWindow* parent, char* title, TWindow* clientWnd,
  215.                                TModule* module)
  216.   : TFloatingFrame(parent, title, clientWnd, TRUE, DefaultCaptionHeight, TRUE, module)
  217. {
  218. }
  219.  
  220. //
  221. // Supply a reasonable startup position relative to our Parent (owner actually)
  222. //
  223. void
  224. TButtonPalette::SetupWindow()
  225. {
  226.   TFloatingFrame::SetupWindow();
  227.  
  228.   if (Attr.X < 0 || Attr.Y < 0) {
  229.     TRect parentRect;
  230.     Parent->GetWindowRect(parentRect);
  231.     SetWindowPos(0, parentRect.left+10, parentRect.top+10, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  232.   }
  233. }
  234.  
  235. //
  236. // Remember latest position when we are destroyed
  237. //
  238. void
  239. TButtonPalette::CleanupWindow()
  240. {
  241.   TRect rect;
  242.   GetWindowRect(rect);
  243.   Attr.X = rect.left;
  244.   Attr.Y = rect.top;
  245.   
  246.   TFloatingFrame::CleanupWindow();
  247. }
  248.  
  249. //
  250. // Override EvClose to keep TWindow from having us deleted
  251. //
  252. void 
  253. TButtonPalette::EvClose()
  254. {
  255.   CloseWindow();
  256. }
  257.  
  258.  
  259. //----------------------------------------------------------------------------
  260.  
  261. #if defined(USE_LINEBAR)
  262. class TLineBar : public TWindow {
  263.   public:
  264.     TLineBar(TWindow* parent, TState* state);
  265.  
  266.     void         Paint(TDC&, BOOL, TRect&);
  267.     void         EvLButtonDown(UINT modKeys, TPoint& point);
  268.  
  269.   private:
  270.     TState*     State;
  271.     void        Notch(TDC& dc, int x, int w, int y, int dy);
  272.  
  273.   DECLARE_RESPONSE_TABLE(TLineBar);
  274. };
  275.  
  276. DEFINE_RESPONSE_TABLE1(TLineBar, TWindow)
  277.   EV_WM_LBUTTONDOWN,
  278. END_RESPONSE_TABLE;
  279. #endif
  280.  
  281. //----------------------------------------------------------------------------
  282.  
  283. class TCanvas : public TWindow {
  284.   public:
  285.     TCanvas();
  286.    ~TCanvas();
  287.  
  288.     TState       State;
  289.  
  290.   protected:
  291.     // Override TWindow virtuals
  292.     //
  293.     void         SetupWindow();
  294.     BOOL         CanClose();
  295.  
  296.     BOOL         AbandonOk();
  297.     void         SetupDib(TDib* dib, const char* fileName, const char* fileTitle);
  298.     void         NewDib(int width, int height, int nColors);
  299.     void         OpenDib(const char* fileName, const char* fileTitle);
  300.     BOOL         SaveDib(const char* fileName);
  301.  
  302.     void         UpdateCaption();
  303.     void         AdjustScroller();
  304.     void         Paint(TDC&, BOOL, TRect&);
  305.  
  306.     void         EvSize(UINT, TSize&);
  307.     BOOL         EvEraseBkgnd(HDC hDC);
  308.     void         EvLButtonDown(UINT modKeys, TPoint& point);
  309.     void         EvLButtonUp(UINT modKeys, TPoint& point);
  310.     void         EvMouseMove(UINT modKeys, TPoint& point);
  311.     void         EvDropFiles(TDropInfo dropInfo);
  312.     void         EvSysColorChange();
  313.  
  314.     void         CmFileNew();
  315.     void         CmFileOpen();
  316.     void         CmFileSave();
  317.     void         CmFileSaveAs();
  318.     void         CmFilePrint();
  319.     void         CmFilePrintSetup();
  320.  
  321.     void         CmViewTools();
  322.     void         CeViewTools(TCommandEnabler& ce);
  323.     void         CmViewLines();
  324.     void         CeViewLines(TCommandEnabler& ce);
  325.     
  326.     void         CmTool(WPARAM);
  327.     void         CmLine(WPARAM);
  328.  
  329.     TPrintDialog::TData PrintData;
  330.     
  331.   private:
  332.     BOOL         Drawing;
  333.     TBrush*      BkBrush;
  334.     TDrawTool*   Tools[ToolCount];
  335.     
  336.     TButtonPalette* ToolsPal;
  337.     TButtonPalette* LinesPal;
  338.  
  339.   DECLARE_RESPONSE_TABLE(TCanvas);
  340. };
  341.  
  342. DEFINE_RESPONSE_TABLE1(TCanvas, TWindow)
  343.   EV_WM_ERASEBKGND,
  344.   EV_WM_SIZE,
  345.   EV_WM_LBUTTONDOWN,
  346.   EV_WM_LBUTTONUP,
  347.   EV_WM_MOUSEMOVE,
  348.   EV_WM_DROPFILES,
  349.   EV_WM_SYSCOLORCHANGE,
  350.   EV_COMMAND_AND_ID(CM_TOOL+0, CmTool),
  351.   EV_COMMAND_AND_ID(CM_TOOL+1, CmTool),
  352.   EV_COMMAND_AND_ID(CM_TOOL+2, CmTool),
  353.   EV_COMMAND_AND_ID(CM_TOOL+3, CmTool),
  354.   EV_COMMAND_AND_ID(CM_TOOL+4, CmTool),
  355.   EV_COMMAND_AND_ID(CM_TOOL+5, CmTool),
  356.   EV_COMMAND_AND_ID(CM_LINE+1, CmLine),
  357.   EV_COMMAND_AND_ID(CM_LINE+3, CmLine),
  358.   EV_COMMAND_AND_ID(CM_LINE+5, CmLine),
  359.   EV_COMMAND_AND_ID(CM_LINE+7, CmLine),
  360.   EV_COMMAND_AND_ID(CM_LINE+9, CmLine),
  361.   EV_COMMAND_AND_ID(CM_LINE+11, CmLine),
  362.   EV_COMMAND(CM_FILENEW, CmFileNew),
  363.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  364.   EV_COMMAND(CM_FILESAVE, CmFileSave),
  365.   EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
  366.   EV_COMMAND(CM_FILEPRINT, CmFilePrint),
  367.   EV_COMMAND(CM_FILEPRINTERSETUP, CmFilePrintSetup),
  368.   EV_COMMAND(CM_VIEWTOOLS, CmViewTools),
  369.   EV_COMMAND_ENABLE(CM_VIEWTOOLS, CeViewTools),
  370.   EV_COMMAND(CM_VIEWLINES, CmViewLines),
  371.   EV_COMMAND_ENABLE(CM_VIEWLINES, CeViewLines),
  372. END_RESPONSE_TABLE;
  373.  
  374. // --------------- TDrawTool ------------------------
  375.  
  376. TDrawTool::TDrawTool(const char* name)
  377.   : State(0), Window(0), Pen(0), Brush(0), DC(0)
  378. {
  379.   Name = name;
  380. }
  381.  
  382. void
  383. TDrawTool::MouseDown(TWindow& window, const TPoint& point, TState* state)
  384. {
  385.   TRACEX(PaintDrw,0,"Draw " << GetName() <<
  386.     " started at (" << point.x << "," << point.y << ")");
  387.   Window = &window;
  388.   State = state;
  389.   Window->SetCapture();
  390.  
  391.   DC = new TClientDC(window);
  392.   Pen = new TPen(TColor(State->FgColor), State->PenSize);
  393.   Brush = new TBrush(TColor(State->BgColor));
  394.  
  395.   State->DC->SelectObject(*State->Palette);
  396.   State->DC->RealizePalette();
  397.   State->DC->SelectObject(*Pen);
  398.   State->DC->SelectObject(*Brush);
  399.  
  400.   LastPoint = point;
  401.   Bounds = TRect(point, point);
  402.   DrawBegin(point);
  403. }
  404.  
  405. void
  406. TDrawTool::MouseMove(const TPoint& point)
  407. {
  408.   TRACEX(PaintDrw,1,"Draw " << GetName() <<
  409.     " extends to (" << point.x << "," << point.y << ")");
  410.   Bounds |= TRect(point.x, point.y, point.x, point.y);
  411.   DrawTo(point);
  412.   LastPoint = point;
  413. }
  414.  
  415. void
  416. TDrawTool::MouseUp()
  417. {
  418.   TRACEX(PaintDrw,1,"Draw " << GetName() << " finished");
  419.   DrawEnd();
  420.  
  421.   Window->ReleaseCapture();
  422.   State->DC->RestoreObjects();
  423.  
  424.   delete Brush; Brush = 0;
  425.   delete Pen; Pen = 0;
  426.   delete DC; DC = 0;
  427.  
  428.   State->Modified = TRUE;
  429.   Window->InvalidateRect(Bounds.
  430.               InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2), FALSE);
  431.   Window->UpdateWindow();
  432. }
  433.  
  434.  
  435. // --------------- TPenTool ------------------------
  436.  
  437. void
  438. TPenTool::DrawBegin(const TPoint& point)
  439. {
  440.   State->DC->MoveTo(point);
  441.  
  442.   // Do parallel update onto screen
  443.   //
  444. #if defined(PARALLEL_PEN)
  445.   // can't select a palette into to different device DCs
  446.   TmpPalette = new TPalette(*State->Dib);
  447.   DC->IntersectClipRect(TRect(TPoint(0,0), State->Dib->Size()));
  448.   DC->SelectObject(*TmpPalette);
  449.   DC->RealizePalette();
  450.  
  451.   DC->SelectObject(*Pen);
  452.   DC->MoveTo(point);
  453. #endif
  454. }
  455.  
  456. void
  457. TPenTool::DrawTo(const TPoint& point)
  458. {
  459.   State->DC->LineTo(point);
  460. #if defined(PARALLEL_PEN)
  461.   DC->LineTo(point);
  462. #else
  463.   Window->InvalidateRect(TRect(LastPoint, point).Normalized().
  464.                  InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2),FALSE);
  465.   Window->UpdateWindow();
  466. #endif
  467. }
  468.  
  469. void
  470. TPenTool::DrawEnd()
  471. {
  472.   State->DC->RestorePen();
  473. #if defined(PARALLEL_PEN)
  474.   DC->RestorePen();
  475.   delete TmpPalette; TmpPalette = 0;
  476. #endif
  477. }
  478.  
  479. // --------------- TFillTool ------------------------
  480.  
  481. void
  482. TFillTool::DrawBegin(const TPoint& point)
  483. {
  484.   TBrush fgBrush(State->FgColor);
  485.   State->DC->SelectObject(fgBrush);
  486.   TColor surfaceColor(State->DC->GetPixel(point));
  487.   State->DC->ExtFloodFill(point, surfaceColor, FLOODFILLSURFACE);
  488.   Bounds = Window->GetClientRect();
  489.   State->DC->RestoreBrush();
  490. }
  491.  
  492.  
  493. // --------------- TBoxTool ------------------------
  494.  
  495. void
  496. TBoxTool::DrawBegin(const TPoint& point)
  497. {
  498.   X1 = X2 = point.x;
  499.   Y1 = Y2 = point.y;
  500.   DC->SelectStockObject(BLACK_PEN);
  501.   DC->SelectStockObject(NULL_BRUSH);
  502.   DC->SetROP2(R2_NOT);
  503.   DrawObject(*DC);
  504. }
  505.  
  506. void
  507. TBoxTool::DrawTo(const TPoint& point)
  508. {
  509.   DrawObject(*DC);
  510.   X2 = point.x;
  511.   Y2 = point.y;
  512.   DrawObject(*DC);
  513. }
  514.  
  515. void
  516. TBoxTool::DrawEnd()
  517. {
  518.   DrawObject(*DC);
  519.   DC->SetROP2(R2_COPYPEN);
  520.   State->DC->SelectObject(*Pen);
  521.   if (Filled)
  522.     State->DC->SelectObject(*Brush);
  523.   else
  524.     State->DC->SelectStockObject(NULL_BRUSH);
  525.   DrawObject(*State->DC);
  526. }
  527.  
  528. // --------------- TRectTool ------------------------
  529.  
  530. void
  531. TRectTool::DrawObject(TDC& dc)
  532. {
  533.   dc.Rectangle(X1, Y1, X2, Y2);
  534. }
  535.  
  536. // --------------- TEllipseTool ------------------------
  537.  
  538. void
  539. TEllipseTool::DrawObject(TDC& dc)
  540. {
  541.   dc.Ellipse(X1, Y1, X2, Y2);
  542. }
  543.  
  544. // --------------- TPaletteWindow ------------------------
  545.  
  546. TPaletteWindow::TPaletteWindow(TWindow* parent, TState* state)
  547.   : TWindow(parent),
  548.     State(state)
  549. {
  550.   Attr.Style |= WS_BORDER;
  551.   Attr.W = 50;
  552.   Attr.H = 50;
  553.   Attr.Id = ID_PALETTE;
  554. }
  555.  
  556. void
  557. TPaletteWindow::EvSize(UINT, TSize&)
  558. {
  559.   TRect rect = GetClientRect();
  560.   Horz = TRUE;  // Location==Top || Location==Bottom;
  561.   Cx = (Horz ? 17 : 3);
  562.   Cy = (Horz ? 3 : 17);
  563.   Dx = rect.right / Cx;
  564.   Dy = rect.bottom / Cy;
  565.   if (Horz)
  566.     Cx--;
  567.   else
  568.     Cy--;
  569.   Invalidate(FALSE);
  570. }
  571.  
  572. void
  573. TPaletteWindow::Paint(TDC& dc, BOOL, TRect&)
  574. {
  575.   dc.SelectObject(*State->Palette);
  576.   dc.RealizePalette();
  577.   
  578.   TRect rect = GetClientRect();
  579.  
  580.   dc.SelectStockObject(BLACK_PEN);
  581.  
  582.   // Paint color selection cells, each with a black frame
  583.   //
  584.   for (int i = 0; i < 16; i++)
  585.     for (int j = 0; j < 3; j++) {
  586.       TBrush brush(TColor(j*16+i));
  587.       dc.SelectObject(brush);
  588.       TPoint p = Horz ? TPoint(i*Dx, j*Dy) : TPoint(j*Dx, i*Dy);
  589.       dc.Rectangle(p, TSize(Dx+1, Dy+1));
  590.       dc.RestoreBrush();
  591.     }
  592.  
  593.   // Paint pen & brush color display, frame first
  594.   //
  595.   dc.SelectStockObject(NULL_BRUSH);
  596.   TPoint p = Horz ? TPoint(Dx*16, 0) : TPoint(0, Dy*16);
  597.   dc.Rectangle(p, rect.BottomRight());
  598.  
  599.   TPen pen(TColor(State->BgColor), 5);
  600.   dc.SelectObject(pen);
  601.   TBrush brush(TColor(State->FgColor));
  602.   dc.SelectObject(brush);
  603.   p += TSize(3,3);
  604.   dc.Rectangle(p, TPoint(rect.right-3, rect.bottom-3));
  605.  
  606.   dc.RestoreObjects();
  607. }
  608.  
  609. void
  610. TPaletteWindow::SelectColor(TPoint& point, int& color)
  611. {
  612.   point.x /= Dx;
  613.   point.y /= Dy;
  614.   if (point.x < Cx && point.y < Cy) {
  615.     int newColor = Horz ? point.x + point.y*Cx : point.x*Cy + point.y;
  616.     if (color != newColor) {
  617.       TColor c = State->Dib->GetColor(newColor);
  618.  
  619.       InvalidateRect(Horz ? TRect(TPoint(Dx*Cx, 0), GetClientRect().BottomRight()) :
  620.                             TRect(TPoint(0, Dy*Cy), GetClientRect().BottomRight()), 
  621.                      FALSE);
  622.       color = newColor;
  623.     }
  624.   }
  625. }
  626.  
  627. void
  628. TPaletteWindow::EvLButtonDown(UINT, TPoint& point)
  629. {
  630.   SelectColor(point, State->FgColor);
  631. }
  632.  
  633. void
  634. TPaletteWindow::EvLButtonDblClk(UINT, TPoint& point)
  635. {
  636.   static TColor CustColors[32];
  637.   
  638.   int editColor = -1;
  639.   SelectColor(point, editColor);
  640.   if (editColor < 0)
  641.     return;
  642.   TChooseColorDialog::TData choose;
  643.   choose.Flags = CC_RGBINIT;
  644.   PALETTEENTRY pe;
  645.   State->Palette->GetPaletteEntry((WORD)editColor, pe);
  646.   choose.Color = pe;
  647.   choose.CustColors = CustColors;
  648.  
  649.   if (TChooseColorDialog(this, choose).Execute() == IDOK) {
  650.     State->Dib->SetColor(editColor, choose.Color);
  651.     delete State->Palette;
  652.     State->Palette = new TPalette(*State->Dib);
  653.     Invalidate(FALSE);
  654.     TWindow* canvas = Parent->ChildWithId(ID_CANVAS);
  655.     if (canvas && canvas->HWindow)
  656.       canvas->Invalidate(FALSE);
  657.   }
  658. }
  659.  
  660. void
  661. TPaletteWindow::EvRButtonDown(UINT, TPoint& point)
  662. {
  663.   SelectColor(point, State->BgColor);
  664. }
  665.  
  666. void
  667. TPaletteWindow::EvRButtonDblClk(UINT modKeys, TPoint& point)
  668. {
  669.   EvLButtonDblClk(modKeys, point);
  670. }
  671.  
  672. LRESULT
  673. TPaletteWindow::EvSetRGB(WPARAM, LPARAM)
  674. {
  675.   Invalidate(FALSE);
  676.   return 0;
  677. }
  678.  
  679. #if defined(USE_LINEBAR)
  680. // --------------- TLineBar ------------------------
  681.  
  682. TLineBar::TLineBar(TWindow* parent, TState* state)
  683.   : TWindow(parent),
  684.     State(state)
  685. {
  686.   Attr.Style |= WS_BORDER;
  687.   Attr.W = 32;
  688.   Attr.H = 32;
  689. }
  690.  
  691. void
  692. TLineBar::Notch(TDC& dc, int x, int w, int y, int dy)
  693. {
  694.   for (int l = 3; l >= 0; l--) {
  695.     dc.MoveTo(TPoint(x + w / 2 - l, y));
  696.     dc.LineTo(TPoint(x + w / 2 + l + 1, y));
  697.     y += dy;
  698.   }
  699. }
  700.  
  701. void
  702. TLineBar::Paint(TDC& dc, BOOL, TRect&)
  703. {
  704.   int x = 4;
  705.   dc.SelectStockObject(WHITE_BRUSH);
  706.   dc.PatBlt(TRect(0, 0, Attr.W, Attr.H));
  707.   dc.SelectStockObject(BLACK_BRUSH);
  708.   for (int i = 0; i < LineCount; i++) {
  709.     int w = LineWidth[i];
  710.     dc.PatBlt(TRect(x, 5, x + w, 25));
  711.     if (w == State->PenSize) {
  712.       Notch(dc, x, w, 0, 1);
  713.       Notch(dc, x, w, 29, -1);
  714.     }
  715.     x += w + 4;
  716.   }
  717. }
  718.  
  719. void
  720. TLineBar::EvLButtonDown(UINT, TPoint& point)
  721. {
  722.   int x = 2;
  723.   for (int i = 0; i < LineCount; i++) {
  724.     int w = LineWidth[i];
  725.     if (point.x >= x && point.x < x+w+4) {
  726.       TRACEX(PaintCmd,0,"Width = " << w);
  727.       State->PenSize = w;
  728.       Invalidate(FALSE);
  729.       return;
  730.     }
  731.     x += w + 4;
  732.   }
  733. }
  734. #endif
  735.  
  736.  
  737. // --------------- TCanvas ------------------------
  738.  
  739. TCanvas::TCanvas()
  740.   : TWindow(0, 0, 0),
  741.     Drawing(FALSE)
  742. {
  743.   BkBrush = 0;
  744.   EvSysColorChange();
  745.  
  746.   State.DrawTool = 0;
  747.   State.Dib = 0;
  748.   State.Bitmap = 0;
  749.   State.DC = 0;
  750.   State.Palette = 0;
  751.   State.PenSize = DefPenSize;
  752.   State.FgColor = 0;
  753.   State.BgColor = 1;
  754.   State.Name = State.Title = "";
  755.  
  756.   Scroller = 0;
  757.  
  758.   Tools[0] = new TPenTool("Pen");
  759.   Tools[1] = new TFillTool("Fill");
  760.   Tools[2] = new TRectTool("Rect", FALSE);
  761.   Tools[3] = new TRectTool("FillRect", TRUE);
  762.   Tools[4] = new TEllipseTool("Ellipse", FALSE);
  763.   Tools[5] = new TEllipseTool("FillEllipse", TRUE);
  764.   State.DrawTool = Tools[0];
  765.   
  766.   Attr.Id = ID_CANVAS;
  767.  
  768. #if !defined(USE_TOOLBAR)
  769.   TToolBox* tb = new TToolBox(0);
  770.   tb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive, 
  771.                                 TRUE, TButtonGadget::Down));
  772.   tb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive, TRUE));
  773.   tb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive, TRUE));
  774.   tb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive, TRUE));
  775.   tb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive, TRUE));
  776.   tb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive, TRUE));
  777.   ToolsPal = new TButtonPalette(this, "", tb);
  778.  
  779.   tb = new TToolBox(0);
  780.   tb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive, 
  781.                                 TRUE, TButtonGadget::Down));
  782.   tb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive, TRUE));
  783.   tb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive, TRUE));
  784.   tb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive, TRUE));
  785.   tb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive, TRUE));
  786.   tb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive, TRUE));
  787.   LinesPal = new TButtonPalette(this, "", tb);
  788. #else
  789.   ToolsPal = LinesPal = 0;
  790. #endif
  791. }
  792.  
  793. TCanvas::~TCanvas()
  794. {
  795.   delete State.DC;
  796.   delete State.Palette;
  797.   delete State.Dib;
  798.   delete State.Bitmap;
  799.   delete BkBrush;
  800.  
  801.   for (int i = 0; i < ToolCount; i++)
  802.     delete Tools[i];
  803. }
  804.  
  805. void
  806. TCanvas::SetupWindow()
  807. {
  808.   TWindow::SetupWindow();
  809.   NewDib(DefWidth, DefHeight, DefNColors);
  810.   DragAcceptFiles(TRUE);
  811.   
  812.   //
  813.   // A scroller on the client area would be nice...
  814.   //
  815.   //Scroller = new TScroller(this,1,1, State.Dib->Width(), State.Dib->Height());
  816.   SetFocus();
  817. }
  818.  
  819. BOOL
  820. TCanvas::CanClose()
  821. {
  822.   return AbandonOk();
  823. }
  824.  
  825. BOOL
  826. TCanvas::AbandonOk()
  827. {
  828.   if (!State.Modified)
  829.     return TRUE;
  830.   const char msgFrmt[] = "%s\nThe image has changed.\n\n"
  831.                          "Do you want to save current changes?";
  832.   char msg[sizeof(msgFrmt)+20];
  833.   sprintf(msg, msgFrmt, State.Name.c_str());
  834.   int resp = MessageBox(msg, GetApplication()->GetName(), 
  835.                         MB_ICONEXCLAMATION|MB_YESNOCANCEL);
  836.   if (resp == IDYES)
  837.     CmFileSave();
  838.  
  839.   return resp != IDCANCEL;
  840. }
  841.  
  842. //
  843. // Setup state info given a new dib. Assumes ownership of the dib.
  844. //
  845. void
  846. TCanvas::SetupDib(TDib* dib, const char* name, const char* title)
  847. {
  848.   //
  849.   // Make sure we can get the Dib DC and palette before we commit to this dib.
  850.   // Revert to a DDB and a memory DC if we can't create a DIB DC.
  851.   //
  852.   TDC*      newDC;
  853.   TBitmap*  newBM = 0;
  854.   TPalette* newPalette;
  855.   try {
  856.     newDC = new TDibDC(*dib);
  857.   }
  858.   catch (TGdiObject::TXGdi&) {
  859.     newDC = new TMemoryDC;
  860.     newBM = new TBitmap(TScreenDC(), *dib);
  861.     ((TMemoryDC*)newDC)->SelectObject(*newBM);
  862.     newDC->SetDIBits(*newBM, *dib);
  863.     if (dib->NumColors() > NColors(WORD(newBM->Planes()*newBM->BitsPixel())))
  864.       MessageBox("Colors may have been lost during bitmap conversion.",
  865.                  GetApplication()->GetName(), MB_ICONEXCLAMATION|MB_OK);
  866.   }
  867.   newPalette = new TPalette(*dib);
  868.   delete State.DC;
  869.   delete State.Palette;
  870.   delete State.Dib;
  871.   delete State.Bitmap;
  872.   State.DC = newDC;
  873.   State.Palette = newPalette;
  874.   State.Dib = dib;
  875.   State.Bitmap = newBM;
  876.  
  877.   State.Name = name;
  878.   State.Title = title;
  879.   State.Modified = FALSE;
  880.   UpdateCaption();
  881.   AdjustScroller();
  882.   TWindow* palette = Parent->ChildWithId(ID_PALETTE);
  883.   if (palette && palette->HWindow)
  884.     palette->Invalidate(FALSE);
  885.   Invalidate(FALSE);
  886. }
  887.  
  888. //
  889. // Create a new dib & setup state info
  890. //
  891. void
  892. TCanvas::NewDib(int width, int height, int nColors)
  893. {
  894.   //
  895.   // Construct the dib, catching any exptions that might occur & displaying a
  896.   // warning
  897.   //
  898.   TDib* dib;
  899.   try {
  900.     dib = new TDib(width, height, nColors);
  901.   }
  902.   catch (TGdiObject::TXGdi& x) {
  903.     MessageBox("Could Not Create DIB", GetApplication()->GetName(), MB_OK);
  904.     return;
  905.   }
  906.  
  907.   //
  908.   // Setup a nice palette
  909.   //
  910.   for (int i = 0; i < min(nColors, int(sizeof DefPalette)); i++)
  911.     dib->SetColor(i, DefPalette[i]);
  912.  
  913.   SetupDib(dib, "", "(Untitled)");
  914.  
  915.   TBrush brush(TColor(State.BgColor));
  916.   State.DC->SelectObject(*State.Palette);
  917.   State.DC->RealizePalette();
  918.   State.DC->SelectObject(brush);
  919.   State.DC->PatBlt(TRect(TPoint(0,0), State.Dib->Size()));
  920.   State.DC->RestoreObjects();
  921. }
  922.  
  923. //
  924. // Open a dib & setup state info given a dib filename & title
  925. //
  926. void
  927. TCanvas::OpenDib(const char* fileName, const char* fileTitle)
  928. {
  929.   TDib* dib;
  930.   try {
  931.     dib = new TDib(fileName);
  932.   }
  933.   catch (TGdiObject::TXGdi& x) {
  934.     MessageBox("Invalid Bitmap File", GetApplication()->GetName(), MB_OK);
  935.     return;
  936.   }
  937.  
  938.   SetupDib(dib, fileName, fileTitle);
  939. }
  940.  
  941. BOOL
  942. TCanvas::SaveDib(const char* fileName)
  943. {
  944.   if (State.Bitmap) {
  945.     delete State.Dib;
  946.     State.Dib = new TDib(*State.Bitmap, State.Palette);
  947.   }
  948.   if (State.Dib->WriteFile(fileName))
  949.     return TRUE;
  950.   MessageBox("Disk error saving bitmap!", GetApplication()->GetName(), MB_OK);
  951.   return FALSE;
  952. }
  953.  
  954. void
  955. TCanvas::UpdateCaption()
  956. {
  957.   char captionBuffer[70];
  958.   if (State.Dib)
  959.     wsprintf(captionBuffer, "%s - %s [%dx%dx%d]", GetApplication()->GetName(),
  960.              (LPCSTR)State.Title.c_str(),
  961.              State.Dib->Width(), State.Dib->Height(), State.Dib->NumColors());
  962.   else
  963.     sprintf(captionBuffer, "%s - (Bad Dib!)", GetApplication()->GetName());
  964.   Parent->SetCaption(captionBuffer);
  965. }
  966.  
  967. void
  968. TCanvas::AdjustScroller()
  969. {
  970.   if (!Scroller)
  971.     return;
  972.  
  973.   TRect  clientRect = GetClientRect();
  974.  
  975.   // only show scrollbars when image is larger than
  976.   // the client area and we are not stretching to fit.
  977.   //
  978.   TPoint range(Max(State.Dib->Width()-clientRect.Width(), 0),
  979.                Max(State.Dib->Height()-clientRect.Height(), 0));
  980.   Scroller->SetRange(range.x, range.y);
  981.   Scroller->ScrollTo(0, 0);
  982.   if (!GetUpdateRect(clientRect, FALSE))
  983.     Invalidate(FALSE);
  984. }
  985.  
  986. void
  987. TCanvas::EvSize(UINT SizeType, TSize& Size)
  988. {
  989.   TWindow::EvSize(SizeType, Size);
  990.   if (SizeType != SIZEICONIC)
  991.     AdjustScroller();
  992. }
  993.  
  994. BOOL
  995. TCanvas::EvEraseBkgnd(HDC /*hDC*/)
  996. {
  997.   // Wait until paint to erase as we blit
  998.   //::FillRect(hDC, GetClientRect(), *BkBrush);
  999.   return TRUE;
  1000. }
  1001.  
  1002. void
  1003. TCanvas::Paint(TDC& dc, BOOL, TRect&)
  1004. {
  1005.   TRect drect(TPoint(0,0), State.Dib->Size());
  1006.   TRect crect = GetClientRect();
  1007.   if (Scroller)
  1008.     crect += TPoint((int)Scroller->XPos, (int)Scroller->YPos);
  1009.  
  1010.   // optimize this painting!
  1011.   //TRect prect(rect);
  1012.   //drect &= prect;
  1013.   dc.SelectObject(*State.Palette);
  1014.   dc.RealizePalette();
  1015.  
  1016.   // Blit the DDB or DIB from the working DC to the screen
  1017.   //
  1018.   if (State.Bitmap)
  1019.     dc.BitBlt(drect, *State.DC, TPoint(0,0));
  1020.   else
  1021.     dc.SetDIBitsToDevice(drect, TPoint(0,0), *State.Dib);
  1022.  
  1023.   // Paint around the canvas
  1024.   //
  1025.   dc.SelectObject(*BkBrush);
  1026.   dc.PatBlt(TRect(drect.right, 0, crect.right, crect.bottom));
  1027.   dc.PatBlt(TRect(0, drect.bottom, crect.right, crect.bottom));
  1028.  
  1029.   dc.RestoreObjects();
  1030. }
  1031.  
  1032. void
  1033. TCanvas::EvLButtonDown(UINT modKeys, TPoint& point)
  1034. {
  1035.   TWindow::EvLButtonDown(modKeys, point);
  1036.   if (!Drawing) {
  1037.     Drawing = TRUE;
  1038.     State.DrawTool->MouseDown(*this, point, &State);
  1039.   }
  1040. }
  1041.  
  1042. void
  1043. TCanvas::EvMouseMove(UINT, TPoint& point)
  1044. {
  1045.   if (Drawing)
  1046.     State.DrawTool->MouseMove(point);
  1047. }
  1048.  
  1049. void
  1050. TCanvas::EvLButtonUp(UINT, TPoint& point)
  1051. {
  1052.   if (Drawing) {
  1053.     State.DrawTool->MouseMove(point);
  1054.     State.DrawTool->MouseUp();
  1055.     Drawing = FALSE;
  1056.   }
  1057. }
  1058.  
  1059. void
  1060. TCanvas::EvDropFiles(TDropInfo dropInfo)
  1061. {
  1062.   int totalNumberOfFiles = dropInfo.DragQueryFileCount();
  1063.   if (totalNumberOfFiles == 1 && AbandonOk()) {
  1064.     char filePath[MAXPATH+1];
  1065.     char fileTitle[MAXFILE];
  1066.     dropInfo.DragQueryFile(0, filePath, MAXPATH + 1);
  1067.     fnsplit(filePath, 0, 0, fileTitle, 0);
  1068.     OpenDib(filePath, fileTitle);
  1069.   }
  1070.   dropInfo.DragFinish();
  1071. }
  1072.  
  1073. void
  1074. TCanvas::EvSysColorChange()
  1075. {
  1076.   delete BkBrush;
  1077.   BkBrush = new TBrush(::GetSysColor(COLOR_APPWORKSPACE)); //COLOR_WINDOW
  1078. }
  1079.  
  1080. void
  1081. TCanvas::CmTool(WPARAM toolCmd)
  1082. {
  1083.   int i = toolCmd - CM_TOOL;
  1084.   TRACEX(PaintCmd,0, "Tool = " << Tools[i]->GetName());
  1085.   State.DrawTool = Tools[i];
  1086.  
  1087.   SetCursor(GetModule(), toolCmd);
  1088. }
  1089.  
  1090. void
  1091. TCanvas::CmLine(WPARAM lineCmd)
  1092. {
  1093.   State.PenSize = lineCmd - CM_LINE;
  1094. }
  1095.  
  1096. void
  1097. TCanvas::CmFileNew()
  1098. {
  1099.   TRACEX(PaintCmd,0,"CmFileNew()");
  1100.   if (!AbandonOk())
  1101.     return;
  1102.  
  1103.   static int width = DefWidth;
  1104.   static int height = DefHeight;
  1105.   static int ncolors = DefNColors;
  1106.   if (TDibAttrDialog(this, width, height, ncolors).Execute() == IDOK)
  1107.     NewDib(width, height, ncolors);
  1108. }
  1109.  
  1110. void
  1111. TCanvas::CmFileOpen()
  1112. {
  1113.   TRACEX(PaintCmd,0,"CmFileOpen()");
  1114.   if (!AbandonOk())
  1115.     return;
  1116.  
  1117.   TOpenSaveDialog::TData data (
  1118.     OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOREADONLYRETURN,
  1119.     "Bitmap Files (*.BMP)|*.bmp|",
  1120.     0,
  1121.     "",
  1122.     "BMP"
  1123.   );
  1124.   if (TFileOpenDialog(this, data).Execute() == IDOK) {
  1125.     char fileTitle[MAXPATH];
  1126.     TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
  1127.     OpenDib(data.FileName, fileTitle);
  1128.   }
  1129. }
  1130.  
  1131. void
  1132. TCanvas::CmFileSave()
  1133. {
  1134.   TRACEX(PaintCmd,0,"CmFileSave()");
  1135.   if (State.Modified) {
  1136.     if (!State.Name.length()) {
  1137.       CmFileSaveAs();
  1138.       return;
  1139.     }
  1140.  
  1141.     if (SaveDib(State.Name.c_str()))
  1142.       State.Modified = FALSE;
  1143.   }
  1144. }
  1145.  
  1146. void
  1147. TCanvas::CmFileSaveAs()
  1148. {
  1149.   TRACEX(PaintCmd,0,"CmFileSaveAs()");
  1150.   TOpenSaveDialog::TData data (
  1151.     OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
  1152.     "Bitmap Files (*.BMP)|*.bmp|",
  1153.     0,
  1154.     "",
  1155.     "BMP"
  1156.   );
  1157.   if (TFileSaveDialog(this, data).Execute() == IDOK) {
  1158.     if (SaveDib(data.FileName)) {
  1159.       State.Name = data.FileName;
  1160.       State.Modified = FALSE;
  1161.       char fileTitle[MAXPATH];
  1162.       TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
  1163.       State.Title = fileTitle;
  1164.       UpdateCaption();
  1165.     }
  1166.   }
  1167. }
  1168.  
  1169. void
  1170. TCanvas::CmFilePrint()
  1171. {
  1172.   TRACEX(PaintCmd, 0, "CmFilePrint()");
  1173.   PrintData.Flags &= ~PD_PRINTSETUP;
  1174.   if (TPrintDialog(this, PrintData).Execute() == IDOK) {
  1175.     MessageBox("No File|Print yet...", GetApplication()->GetName(), MB_OK);
  1176.   }
  1177. }
  1178.  
  1179. void
  1180. TCanvas::CmFilePrintSetup()
  1181. {
  1182.   TRACEX(PaintCmd, 0, "CmFilePrintSetup()");
  1183.   PrintData.Flags |= PD_PRINTSETUP;
  1184.   TPrintDialog(this, PrintData, 0).Execute();
  1185. }
  1186.  
  1187. void
  1188. TCanvas::CmViewTools()
  1189. {
  1190.   if (ToolsPal->HWindow)
  1191.     ToolsPal->Destroy();
  1192.   else
  1193.     ToolsPal->Create();
  1194. }
  1195.  
  1196. void
  1197. TCanvas::CeViewTools(TCommandEnabler& ce)
  1198. {
  1199.   ce.SetCheck(ToolsPal->HWindow ?
  1200.               TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  1201. }
  1202.  
  1203. void
  1204. TCanvas::CmViewLines()
  1205. {
  1206.   if (LinesPal->HWindow)
  1207.     LinesPal->Destroy();
  1208.   else
  1209.     LinesPal->Create();
  1210. }
  1211.  
  1212. void
  1213. TCanvas::CeViewLines(TCommandEnabler& ce)
  1214. {
  1215.   ce.SetCheck(LinesPal->HWindow ?
  1216.               TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  1217. }
  1218.     
  1219.  
  1220. //----------------------------------------------------------------------------
  1221.  
  1222. class TPaintApp : public TApplication {
  1223.   public:
  1224.     TPaintApp() : TApplication("OWL Paint") {}
  1225.     void InitMainWindow();
  1226. };
  1227.  
  1228. void TPaintApp::InitMainWindow()
  1229. {
  1230.   TCanvas& client = *new TCanvas;
  1231.   TDecoratedFrame* frame = new TDecoratedFrame(0, Name, &client);
  1232.   MainWindow = frame;
  1233.  
  1234. #if defined(USE_TOOLBAR)
  1235.   TControlBar* cb = new TControlBar(frame);
  1236.   cb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive, 
  1237.                                 FALSE, TButtonGadget::Down));
  1238.   cb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive));
  1239.   cb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive));
  1240.   cb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive));
  1241.   cb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive));
  1242.   cb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive));
  1243. #if !defined(USE_LINEBAR)
  1244.   cb->Insert(*new TSeparatorGadget);
  1245.   cb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive));
  1246.   cb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive,
  1247.                                 FALSE, TButtonGadget::Down));
  1248.   cb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive));
  1249.   cb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive));
  1250.   cb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive));
  1251.   cb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive));
  1252. #endif
  1253.   frame->Insert(*cb, TDecoratedFrame::Top);
  1254. #endif
  1255.  
  1256.   frame->Insert(*new TPaletteWindow(frame, &client.State), TDecoratedFrame::Bottom);
  1257. #if defined(USE_LINEBAR)
  1258.   frame->Insert(*new TLineBar(frame, &client.State), TDecoratedFrame::Bottom);
  1259. #endif
  1260.  
  1261.   MainWindow->AssignMenu("PaintMenu");
  1262.   MainWindow->Attr.AccelTable = "PaintAccels";
  1263.   MainWindow->SetIcon(this, "PaintIcon");
  1264. }
  1265.  
  1266. int
  1267. OwlMain(int /*argc*/, char* /*argv*/ [])
  1268. {
  1269.   TScreenDC screenDC;
  1270.   DefNColors = (int)NColors(WORD(screenDC.GetDeviceCaps(BITSPIXEL)*screenDC.GetDeviceCaps(PLANES)));
  1271.   return TPaintApp().Run();
  1272. }
  1273.