#ifdef __GNUG__
#pragma implementation
#endif

#include "wx_setup.h"

#if USE_EXTENDED_STATICS

#include <wx_stat.h>
#include <wx_panel.h>
#include <wx_obj.h>
#include <wx_utils.h>
#include <wx_dcpan.h>
#include <math.h>
#include <../../utils/image/src/wx_image.h>

IMPLEMENT_CLASS(wxBasicColors, wxObject)

wxBasicColors::wxBasicColors(wxPanel *the_panel,COLORREF base_color)
   {
     panel = the_panel;
     if (!panel)
        {
          cout << "The NULL pointer passed to wxBasicColors!\n";
          exit(1);
        }
#ifdef wx_motif
     Colormap cmap;
     unsigned long sel;
     XtVaGetValues((Widget) panel -> panelWidget, 
                   XmNcolormap, &cmap, NULL);
     Display *display = panel -> GetXDisplay();

     if (base_color != wxDefColor)
        {
          XColor xcolor;
          xcolor.red   = GetRValue(base_color) << 8;
          xcolor.green = GetGValue(base_color) << 8;
          xcolor.blue  = GetBValue(base_color) << 8;
          xcolor.flags = DoRed | DoGreen | DoBlue;
          if (!XAllocColor(display,cmap,&xcolor))
             {
               cout << "wxWindows warning : Can not allocate color; use panel background color !\n";
               XtVaGetValues((Widget) panel -> panelWidget,
                             XmNbackground, &back1, NULL);
             }
          else back1 = xcolor.pixel;
        }
     else XtVaGetValues((Widget) panel -> panelWidget,
                        XmNbackground, &back1, NULL);
     XmGetColors(XtScreen((Widget) panel -> panelWidget),
                 cmap, back1, &sel, &fore, &back3, &back2);
#endif
#ifdef wx_xview
     Cms cms = (Cms) xv_create(XV_NULL,CMS,
                               CMS_CONTROL_CMS, TRUE,
                               CMS_SIZE, CMS_CONTROL_COLORS,
                               NULL);
     fore  = (unsigned long) xv_get(cms, CMS_PIXEL, 3);
     back1 = (unsigned long) xv_get(cms, CMS_PIXEL, 0);
     back2 = (unsigned long) xv_get(cms, CMS_PIXEL, 1);
     back3 = (unsigned long) xv_get(cms, CMS_PIXEL, 2);
     xv_destroy((Cms) cms);
#endif
   }

wxBasicColors::~wxBasicColors(void)
   {
#ifdef wx_motif
     /*Display *display = panel -> GetXDisplay();
     Colormap cmp;
     XtVaGetValues((Widget) panel -> panelWidget, 
                   XmNcolormap, &cmp, NULL);
     XFreeColors(display, cmp, &fore, 1, 0L);
     XFreeColors(display, cmp, &back3, 1, 0L);
     XFreeColors(display, cmp, &back2, 1, 0L);
     XFreeColors(display, cmp, &back1, 1, 0L);*/
#endif
   }

IMPLEMENT_ABSTRACT_CLASS(wxStaticItem, wxItem)

wxStaticItem::wxStaticItem(void)
   {
   }

wxStaticItem::wxStaticItem(wxPanel *the_panel,int x, int y, int w, int h):
              wxbStaticItem(the_panel,x,y,w,h)
   {
     panel -> AddStaticItem(this);
   }

Bool wxStaticItem::Show(Bool show)
   {
     if (isShow != show)
        {
          isShow = show;
          XClearArea(dc -> display, dc -> pixmap,
                     x_draw,y_draw,w_draw,h_draw,True);
        }
     return TRUE;
   }

wxStaticItem::~wxStaticItem(void)
   {
     panel -> RemoveStaticItem(this);
   }

IMPLEMENT_CLASS(wxStaticBox, wxItem)

wxStaticBox::wxStaticBox(wxPanel *the_panel,int x,int y,int w,int h,
                          int the_shadow,
                          COLORREF box,
                          COLORREF border,
                          unsigned int the_mask,
                          wx_box_style the_style):
              wxStaticItem(the_panel,x,y,w,h),
              shadow(the_shadow),
              box_ref(box),
              border_ref(border),
              style(the_style),
              box_color(NULL),
              border_color(NULL),
              box_base(NULL),
              border_base(NULL),
              mask(the_mask),
              pen(NULL),
              brush(NULL)
   {
     if (shadow < 1) shadow = 1;
     if (shadow > 8) shadow = 8;

     x_draw -= (shadow / 2 + 1);
     y_draw -= (shadow / 2 + 1);
     w_draw += (shadow + 2);
     h_draw += (shadow + 2);

     box_color = new wxColour(GetRValue(box_ref),
                              GetGValue(box_ref),
                              GetBValue(box_ref));
     border_color = new wxColour(GetRValue(border_ref),
                                 GetGValue(border_ref),
                                 GetBValue(border_ref));
     box_base = new wxBasicColors(panel,box_ref);
     border_base = new wxBasicColors(panel,border_ref);

     box_color -> pixel = box_base -> back1;
     border_color -> pixel = border_base -> fore;

     pen = new wxPen(*border_color,0,wxSOLID);
     brush = new wxBrush(*box_color,wxSOLID);

     if ((mask & wxIS_BOX) == wxIS_BOX) brush -> SetStyle(wxSOLID);
     else brush -> SetStyle(wxTRANSPARENT);

     if ((mask & wxIS_BORDER) == wxIS_BORDER) pen -> SetStyle(wxSOLID);
     else pen -> SetStyle(wxTRANSPARENT);

     pen -> SetJoin(wxJOIN_MITER);
   }

wxStaticBox::~wxStaticBox(void)
   {
     Colormap cmp = DefaultColormap(dc -> display,
                    DefaultScreen(dc -> display));

     if (brush) delete brush;
     if (pen) delete  pen;
     if (box_color) delete box_color;
     if (border_color) delete border_color;
     if (box_base) delete box_base;
     if (border_base) delete border_base;
     pen = NULL;
     brush = NULL;
     box_color = NULL;
     border_color = NULL;
     box_base = NULL;
     border_base = NULL;
   }

void wxStaticBox::Draw(XRectangle *rect,int r_count)
   {
     dc -> SetBrush(brush);
     dc -> SetPen(pen);
     switch(style)
        {
        
          case wxBUMPED           :
          case wxDIPPED           : DrawSimpleBox();
                                    break;
          case wxRIZED_SOLID      :
          case wxRECESSED_SOLID   : DrawRecessedSolidBox(); 
                                    break;
          case wxRIZED_ROUNDED    :
          case wxRECESSED_ROUNDED : DrawRecessedRoundedBox(); 
                                    break;
          case wxBLACK_SOLID      :
          case wxWHITE_SOLID      : DrawBWSolidBox(); 
                                    break; 
          case wxBLACK_ROUNDED    :
          case wxWHITE_ROUNDED    : DrawBWRoundedBox(); 
                                    break;
          default :
               border_color -> pixel = border_base -> fore;
               box_color -> pixel = box_base -> back1;
               pen -> SetColour(*border_color);
               pen -> SetWidth(shadow);
               brush -> SetColour(*box_color);

               dc -> DrawRectangle(xpos,ypos,width,height);
               break;
        }
   }

void wxStaticBox::DrawBWSolidBox(void)
   {
     if (style == wxBLACK_SOLID)
          border_color -> pixel = border_base -> back3;
     else border_color -> pixel = border_base -> fore;
     box_color -> pixel = box_base -> back1;
     pen -> SetColour(*border_color);
     pen -> SetWidth(shadow);
     brush -> SetColour(*box_color);

     dc -> DrawRectangle(xpos,ypos,width,height);
   }

void wxStaticBox::DrawBWRoundedBox(void)
   {
     if (style == wxBLACK_SOLID)
          border_color -> pixel = border_base -> back3;
     else border_color -> pixel = border_base -> fore;
     box_color -> pixel = box_base -> back1;
     pen -> SetColour(*border_color);
     pen -> SetWidth(shadow);
     brush -> SetColour(*box_color);

     dc -> DrawRoundedRectangle(xpos,ypos,width,height,wxDefRadius);
   }

void wxStaticBox::DrawRecessedSolidBox(void)
   {
     int md = shadow / 2;
     int pd;
     if (shadow < 3) pd = - shadow / 2 + (shadow / 2) * 1;
     else pd = shadow / 2 - ((shadow % 2) ? 0 : 1);
     
     if (style == wxRECESSED_SOLID)
          border_color -> pixel = border_base -> back3;
     else border_color -> pixel = border_base -> fore;
     box_color -> pixel = box_base -> back1;
     pen -> SetColour(*border_color);
     pen -> SetWidth(shadow);
     brush -> SetColour(*box_color);
     
     dc -> DrawRectangle(xpos,ypos,width,height);
     
     pen -> SetWidth(0);
     int llp;
     for(llp = 0;llp < shadow;llp++)
        {
          dc -> IntDrawLine(xpos + 1 + llp - md, ypos + height - llp + pd, 
                            xpos + width - 1 - md, ypos + height - llp + pd);
          dc -> IntDrawLine(xpos + width - llp + pd, ypos + llp - md, 
                            xpos + width - llp + pd, ypos + height + pd);
        }
               
     if (style == wxRECESSED_SOLID)
          border_color -> pixel = border_base -> fore;
     else border_color -> pixel = border_base -> back3;
     pen -> SetColour(*border_color);
     pen -> SetWidth(0);
     for(llp = 0;llp < shadow;llp++)
        {
          dc -> IntDrawLine(xpos - md, ypos + llp - md, 
                            xpos + width - llp + pd, ypos + llp - md);
          dc -> IntDrawLine(xpos + llp - md, ypos - md, 
                            xpos + llp - md, ypos + height - llp + pd);
        }
     border_color -> pixel = border_base -> back2;
     pen -> SetColour(*border_color);
     dc -> IntDrawLine(xpos - md,ypos + height + pd,
                       xpos + shadow - 1 - md, ypos + height - shadow + 1 + pd);
     dc -> IntDrawLine(xpos + width + pd,ypos - md,
                       xpos + width - shadow + 1 + pd, ypos + shadow - 1 - md);

   }

void wxStaticBox::DrawSimpleBox(void)
   {
     if (style == wxDIPPED)
          border_color -> pixel = border_base -> back3;
     else border_color -> pixel = border_base -> fore;
     box_color -> pixel = box_base -> back1;
     pen -> SetColour( *border_color);
     pen -> SetWidth(0);
     brush -> SetColour(*box_color);
     
     dc -> DrawRectangle(xpos,ypos,width,height);
     
     dc -> IntDrawLine(xpos + 1,ypos + height,
                       xpos + 1,ypos + 1);
     dc -> IntDrawLine(xpos + 1,ypos + 1,
                       xpos + width - 2,ypos + 1);
     dc -> IntDrawLine(xpos + width,ypos,
                       xpos + width,ypos + height);
     dc -> IntDrawLine(xpos + 1,ypos + height,
                       xpos + width,ypos  + height);
     
     if (style == wxDIPPED)
          border_color -> pixel = border_base -> fore;
     else border_color -> pixel = border_base -> back3;
     pen -> SetColour(*border_color);
     dc -> IntDrawLine(xpos,ypos + height,
                       xpos,ypos );
     dc -> IntDrawLine(xpos,ypos,
                       xpos + width - 1,ypos);
     dc -> IntDrawLine(xpos + width - 1,ypos,
                       xpos + width - 1,ypos + height - 1);
     dc -> IntDrawLine(xpos + 2,ypos + height - 1,
                       xpos + width - 1,ypos  + height - 1);

     border_color -> pixel = border_base -> back2;
     pen -> SetColour(*border_color);

     dc -> DrawPoint(xpos,ypos + height);
     dc -> DrawPoint(xpos + width,ypos);
   }

void wxStaticBox::DrawRecessedRoundedBox(void)
   {

     if (style == wxRECESSED_ROUNDED)
          border_color -> pixel = border_base -> back3;
     else border_color -> pixel = border_base -> fore;
     box_color -> pixel = box_base -> back1;
     pen -> SetColour(*border_color);
     pen -> SetWidth(shadow);
     brush -> SetColour(*box_color);
     
     dc -> DrawRoundedRectangle(xpos,ypos,width,height,wxDefRadius);

     dc -> IntDrawLine(xpos,ypos + wxDefRadius,
                       xpos,ypos + height - wxDefRadius);
     dc -> IntDrawLine(xpos + wxDefRadius,ypos,
                       xpos + width - wxDefRadius,ypos);

     if (style == wxRECESSED_ROUNDED)
          border_color -> pixel = border_base -> fore;
     else border_color -> pixel = border_base -> back3;
     pen -> SetColour(*border_color);
     dc -> IntDrawLine(xpos + width,ypos + wxDefRadius,
                       xpos + width,ypos + height - wxDefRadius);
     dc -> IntDrawLine(xpos + wxDefRadius,ypos + height,
                       xpos + width - wxDefRadius,ypos + height);
     dc -> DrawArc(xpos + width - wxDefRadius, ypos + height,
                   xpos + width, ypos + height - wxDefRadius,
                   xpos + width - wxDefRadius, ypos + height - wxDefRadius);
     XDrawArc(dc -> display, dc -> pixmap, dc -> gc,
              xpos, ypos + height - 2 * wxDefRadius,
              wxDefRadius * 2, wxDefRadius * 2,
              218 * 64, 50 * 64);
     XDrawArc(dc -> display, dc -> pixmap, dc -> gc,
              xpos + width - 2 * wxDefRadius, ypos,
              wxDefRadius * 2, wxDefRadius * 2,
              0 * 64, 50 * 64);

     XSetForeground(dc -> display, dc -> gc, border_base -> back2);
     XDrawArc(dc -> display, dc -> pixmap, dc -> gc,
              xpos, ypos + height - 2 * wxDefRadius,
              wxDefRadius * 2, wxDefRadius * 2,
              218 * 64, 14 * 64);
     XDrawArc(dc -> display, dc -> pixmap, dc -> gc,
              xpos + width - 2 * wxDefRadius, ypos,
              wxDefRadius * 2, wxDefRadius * 2,
              35 * 64, 14 * 64);
   }

IMPLEMENT_CLASS(wxStaticSeparator, wxItem)

wxStaticSeparator::wxStaticSeparator(wxPanel *the_panel,int x,int y,int w,
                                     int the_layout,
                                     int the_shadow,
                                     COLORREF border,
                                     wx_box_style the_style):
              wxStaticItem(the_panel,x,y,w,the_shadow),
              layout(the_layout),
              shadow(the_shadow),
              border_ref(border),
              style(the_style),
              border_color(NULL),
              border_base(NULL),
              pen(NULL)
   {
     if (shadow < 1) shadow = 1;
     if (shadow > 8) shadow = 8;

     if ((layout != wxHORIZ_SEPARATOR) && (layout != wxVERT_SEPARATOR))
        layout = wxHORIZ_SEPARATOR;

     if ((style != wxDIPPED) && (style != wxBUMPED) &&
         (style != wxBLACK_SOLID) && (style != wxWHITE_SOLID))
          style = wxDIPPED;

     if ((style == wxBUMPED) || (style == wxDIPPED))
          shadow = 2;

     if (layout == wxHORIZ_SEPARATOR) 
        {
          height = shadow;
          x_draw -= (shadow / 2 + 1);
          y_draw -= (shadow / 2 + 1);
          w_draw = width + shadow + 2;
          h_draw = height + shadow + 2;
        }
     else
        {
          height = width;
          width = shadow;
          x_draw -= (shadow / 2 + 1);
          y_draw -= (shadow / 2 + 1);
          w_draw = width + shadow + 2;
          h_draw = height + shadow + 2;
        }

     border_color = new wxColour(GetRValue(border_ref),
                                 GetGValue(border_ref),
                                 GetBValue(border_ref));
     border_base = new wxBasicColors(panel,border_ref);
     border_color -> pixel = border_base -> back1;
     pen = new wxPen(*border_color,0,wxSOLID);
     pen -> SetStyle(wxSOLID);
   }

wxStaticSeparator::~wxStaticSeparator(void)
   {
     if (pen) delete pen;
     if (border_color) delete border_color;
     if (border_base) delete border_base;
     pen = NULL;
     border_color = NULL;
     border_base = NULL;
   }

void wxStaticSeparator::Draw(XRectangle *rect,int r_count)
   {
     pen -> SetJoin(wxJOIN_MITER);
     dc -> SetPen(pen);
     switch(style)
        {
        
          case wxBUMPED :
          case wxDIPPED : 
               if (style == wxBUMPED)
                   border_color -> pixel = border_base -> fore;
               else border_color -> pixel = border_base -> back3;
               pen -> SetColour(*border_color);
               pen -> SetWidth(0);
               if (layout == wxHORIZ_SEPARATOR)
                  {
                    dc -> IntDrawLine(xpos,ypos,xpos + width,ypos);
                    dc -> DrawPoint(xpos, ypos + 1);
                  }
               else 
                  { 
                    dc -> IntDrawLine(xpos,ypos,xpos,ypos + height);
                    dc -> DrawPoint(xpos + 1, ypos);
                  }
               if (style == wxBUMPED)
                   border_color -> pixel = border_base -> back3;
               else border_color -> pixel = border_base -> fore;
               pen -> SetColour(*border_color);
               if (layout == wxHORIZ_SEPARATOR)
                  {
                    dc -> IntDrawLine(xpos + 1,ypos + 1,xpos + width,ypos + 1);
                    dc -> DrawPoint(xpos + width, ypos);
                  }
               else 
                  { 
                    dc -> IntDrawLine(xpos + 1,ypos + 1,xpos + 1,ypos + height);
                    dc -> DrawPoint(xpos, ypos + height);
                  }
               break;
          case wxWHITE_SOLID  :
          case wxBLACK_SOLID  :
               if (style == wxWHITE_SOLID)
                   border_color -> pixel = border_base -> fore;
               else border_color -> pixel = border_base -> back3;
               pen -> SetColour(*border_color);
               pen -> SetWidth(shadow);
               pen -> SetJoin(wxJOIN_MITER);
               if (layout == wxHORIZ_SEPARATOR)
                         dc -> IntDrawLine(xpos,ypos,xpos + width,ypos);
               else dc -> IntDrawLine(xpos,ypos,xpos,ypos + height);
               break;
        }
   }

IMPLEMENT_CLASS(wxStaticBitmap, wxItem)

wxStaticBitmap::wxStaticBitmap(wxPanel *the_panel,int x,int y,
                          wxBitmap *the_bitmap,
                          COLORREF fg, COLORREF bg):
              wxStaticItem(the_panel,x,y,0,0),
              bitmap(the_bitmap),
              fore_ref(fg),
              back_ref(bg),
              fore(NULL),
              back(NULL),
              pixmap(0)
   {
     if (!bitmap)
        {
          cout << "Null bitmap passed!\n";
          exit(1);
        }
     fore = new wxBasicColors(panel,fore_ref);
     back = new wxBasicColors(panel,back_ref);
     h_draw = height = bitmap -> GetHeight();
     w_draw = width = bitmap -> GetWidth();
     depth = bitmap -> GetDepth();
     pixmap = bitmap -> x_pixmap;
   }

wxStaticBitmap::wxStaticBitmap(wxPanel *the_panel,int x,int y,
                               char *fname):
              wxStaticItem(the_panel,x,y,0,0),
              bitmap(NULL),
              fore_ref(wxDefColor),
              back_ref(wxDefColor),
              fore(NULL),
              back(NULL),
              pixmap(0)
   {
     if (!fname)
        {
          cout << "Null fname passed!\n";
          exit(1);
        }
     fore = new wxBasicColors(panel,fore_ref);
     back = new wxBasicColors(panel,back_ref);
     wxImage *img = new wxImage;
     if (FileExists(fname) && img -> Load(fname))
        {
          w_draw = width = img -> eWIDE;
          h_draw = height = img -> eHIGH;
          depth = img -> dispDEEP;
          bitmap = new wxBitmap(width,height,depth);
          wxColourMap *cmp = img -> GetColourMap();
          img -> Resize(width,height);
          GC gc = XCreateGC(dc -> display, bitmap -> x_pixmap, 0, NULL);
          bitmap -> free_colors_num = img -> nfcols;
          bitmap -> free_colors = new unsigned long [img -> nfcols];
          long llp;
          XColor xcol;
          for(llp = 0;llp < img -> nfcols;llp++)
             {
               xcol.pixel = bitmap -> free_colors[llp] = img -> freecols[llp];
               XQueryColor(dc -> display, img -> theCmap, &xcol); 
               XAllocColor(dc -> display, img -> theCmap, &xcol); 
             }
          XPutImage(dc -> display, bitmap -> x_pixmap, gc,
                    img -> theImage, 0,0,0,0,width,height);
          XFreeGC(dc -> display, gc);
          delete img;
          delete cmp;
        }
     else 
        {
          cout << "Can not to create Image for file " << fname << " !\n";
          exit(1);
        }
     pixmap = bitmap -> x_pixmap;
   }

wxStaticBitmap::wxStaticBitmap(wxPanel *the_panel,int x,int y,
                               char **data, COLORREF bg):
              wxStaticItem(the_panel,x,y,0,0),
              bitmap(NULL),
              fore_ref(wxDefColor),
              back_ref(bg),
              fore(NULL),
              back(NULL),
              pixmap(0)
   {
     if (!data)
        {
          cout << "Null data passed!\n";
          exit(1);
        }
     fore = new wxBasicColors(panel,fore_ref);
     back = new wxBasicColors(panel,back_ref);

     int n_planes, n_colors;

     Display *display = dc -> display;
     int screen = DefaultScreen(display);

     depth = DefaultDepth(display,screen);
     
     sscanf(data[0],"%d %d %d %d", &width, &height, 
                                       &n_colors, &n_planes);

     w_draw = width; h_draw = height;

     bitmap = new wxBitmap(width,height,depth);
     XColor *xcolors = new XColor[n_colors];

     bitmap -> free_colors_num = n_colors;
     bitmap -> free_colors = new unsigned long [bitmap -> free_colors_num];
     
     int llp;
     int flag = 0;
     for(llp = 0;llp < n_colors;llp++)
        {
          char c1, str[50];
          XColor xc;

          if (sscanf(data[1 + llp],"%c c %s",&c1,str) != 2)
             {
               if (sscanf(data[1+llp],"%c s %s",&c1,str) == 2)
                    xcolors[llp].pixel = back -> back1;
               else
                  {
                    cout << "The XPM data is damaged in " << 1+llp << " line\n";
                    exit(0);
                  }
               bitmap -> free_colors_num --;
               flag++;
             }
          else
             {
               XLookupColor(display, DefaultColormap(display, screen),
                            str, &(xcolors[llp]),&xc);
               xcolors[llp].flags = DoRed | DoBlue | DoGreen;
               wxAllocColor(display, DefaultColormap(display, screen),
                           &(xcolors[llp]));
               bitmap -> free_colors[llp - flag] = xcolors[llp].pixel;
             }
        }

     pixmap = bitmap -> x_pixmap;

     GC gc = DefaultGC(display,screen);

     for(llp = 1 + n_colors; llp < 1 + n_colors + height;llp++)
        {
          int ppl;
          for(ppl = 0;ppl < width;ppl++)
             {
               int klf;
               for(klf = 0;klf < n_colors;klf++)
                  {
                    if (data[llp][ppl] == data[1 + klf][0])
                       {
                         XSetForeground(display,gc,xcolors[klf].pixel);
                         XDrawPoint(display,pixmap,gc,ppl,llp - 1 - n_colors);
                         break;
                       }
                  }
             }
        } 
     delete xcolors;
   }

wxStaticBitmap::~wxStaticBitmap(void)
   {
     Colormap cmp = DefaultColormap(dc -> display,
                    DefaultScreen(dc -> display));
     long llp,ppl;
     
     if (bitmap) delete bitmap;
     bitmap = NULL;
     if (fore) delete fore;
     fore = NULL;
     if (back) delete back;
     back = NULL;
   }

void wxStaticBitmap::Draw(XRectangle *rect,int r_count)
   {
     GC gc = dc -> gc;
     
     if (depth == 1)
        {
#ifdef wx_motif
          if (fore_ref == wxDefColor)
             XSetBackground(dc -> display, gc, fore -> fore);
          else
             XSetBackground(dc -> display, gc, fore -> back1);

          if (back_ref == wxDefColor)
             XSetForeground(dc -> display, gc, back -> back3);
          else
             XSetForeground(dc -> display, gc, back -> back1);
#endif
#ifdef wx_xview
          XSetBackground(dc -> display, gc, fore -> fore);
          XSetForeground(dc -> display, gc, back -> back3);
#endif

          XCopyPlane(dc -> display, pixmap, dc -> pixmap, gc,
                     0,0,width,height,xpos,ypos,1);
        }
     else
        {
          XCopyArea(dc -> display, pixmap, dc -> pixmap, gc,
                    0,0,width,height,xpos,ypos);
        }
   }

#endif
