// Copyright (c) 2021 Giorgos Vougioukas
//
// The license can be found in the LICENSE file.

#include "mnemosyne/picture_wnd.h"
#include "mnemosyne/app_info.h"
#include "mnemosyne/main_wnd.h"

#include <math.h>

#include "WDL/fpcmp.h"
#include "WDL/wingui/wndsize.h"
#include "WDL/wdlstring.h"
#include "WDL/wdlcstring.h"
#include "WDL/filebrowse.h"

#define RSM_GIF_ANIMATION 200
#define RSM_MENUBAR 202
#define RSM_MENUBAR_MS 500

#define RSM_PI 3.1415926535897932384626433832795f

static LOGFONT lf =
{
#if defined(_WIN32)
  20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
  OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
  "Arial"
#else
  17, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
  OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
  "Arial"
#endif
};

#define RSM_OPEN_FILES \
  "All supported files\0*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.ico\0" \
  "JPEG files (*.JPEG)\0*.jpg;*.jpeg\0" \
  "PNG files (*.PNG)\0*.png\0" \
  "GIF files (*.GIF)\0*.gif\0" \
  "BMP files (*.BMP)\0*.bmp\0" \
  "ICO files (*.ICO)\0*.ico\0" \
  "All files (*.*)\0*.*\0\0"
#define RSM_OPEN_FILE_DEFEXT "jpg"

static void bwfunc(LICE_pixel *p, void *parm)
{
  LICE_pixel pix = *p;
  unsigned char s = (LICE_GETR(pix) + LICE_GETG(pix) + LICE_GETB(pix)) / 3;
  *p = LICE_RGBA(s, s, s, LICE_GETA(pix));
}

static void negfunc(LICE_pixel *p, void *parm)
{
  LICE_pixel pix = *p;
  unsigned char r = 255 - LICE_GETR(pix);
  unsigned char g = 255 - LICE_GETG(pix);
  unsigned char b = 255 - LICE_GETB(pix);
  *p = LICE_RGBA(r, g, b, LICE_GETA(pix));
}

static void logfunc(LICE_pixel *p, void *parm)
{
  LICE_pixel pix = *p;
  const double c = 255.0 / log(256.0);
  unsigned char r = (unsigned char)(c * log(1.0 + LICE_GETR(pix)));
  unsigned char g = (unsigned char)(c * log(1.0 + LICE_GETG(pix)));
  unsigned char b = (unsigned char)(c * log(1.0 + LICE_GETB(pix)));
  *p = LICE_RGBA(r, g, b, LICE_GETA(pix));
}

static void illinifyfunc(LICE_pixel *p, void *parm)
{
  LICE_pixel pix = *p;
  int h, s, v;
  int r, g, b;
  LICE_RGB2HSV(LICE_GETR(pix), LICE_GETG(pix), LICE_GETB(pix), &h, &s, &v);
  if (h >= 114 && h <= 293) LICE_HSV2RGB(216, s, v, &r, &g, &b);
  else LICE_HSV2RGB(11, s, v, &r, &g, &b);
  *p = LICE_RGBA(r, g, b, LICE_GETA(pix));
}

RSM_PictureWnd::RSM_PictureWnd(HWND hwnd)
  : m_hwnd(hwnd)
  , m_bm(NULL)
  , m_pic(NULL)
  , m_tmp(NULL)
  , m_font(NULL)
  , m_bgc(0)
  , m_txtc(0)
  , m_picidx(0)
  , m_gif(NULL)
  , m_bw(false)
  , m_blur(false)
  , m_degrees(0)
  , m_vert(false)
  , m_horz(false)
  , m_neg(false)
  , m_log(false)
  , m_illinify(false)
{}

RSM_PictureWnd::~RSM_PictureWnd()
{
  if (m_font) delete m_font;
}

void RSM_PictureWnd::OpenFiles()
{
  char *fl = NULL;

  fl = WDL_ChooseFileForOpen(g_mainwnd->Handle(), "Open files", NULL, NULL,
    RSM_OPEN_FILES, RSM_OPEN_FILE_DEFEXT, true, true);

  if (fl)
  {
    m_piclist.Empty(true);

    const char *only_one = fl;

    while (*only_one++);

    if (*only_one == '\0' && *(only_one + 1) == '\0')
    {
      m_piclist.Add(new WDL_FastString(fl));
    }
    else
    {
      WDL_FastString path(fl);

      char *s = fl;
      while (*s++);

      do
      {
        WDL_FastString *fn = new WDL_FastString();

        if (fn)
        {
          fn->Set(path.Get());
          fn->Append(WDL_DIRCHAR_STR);
          fn->Append(s);
          m_piclist.Add(fn);
        }

        while (*s++);
      } while (*s != '\0' && *(s + 1) != '\0');
    }

    if (m_piclist.GetSize())
    {
      m_picidx = 0;
      WDL_FastString *fn = m_piclist.Get(m_picidx);
      if (m_gif) { LICE_GIF_Close(m_gif); m_gif = NULL; }
      if (m_pic) { delete m_pic; m_pic = NULL; }

      if ((!strcmp(WDL_get_fileext(fn->Get()), ".jpg")) ||
        (!strcmp(WDL_get_fileext(fn->Get()), ".jpeg")))
      {
        m_pic = LICE_LoadJPG(fn->Get());
      }
      else if (!strcmp(WDL_get_fileext(fn->Get()), ".png"))
      {
        m_pic = LICE_LoadPNG(fn->Get());
      }
      else if (!strcmp(WDL_get_fileext(fn->Get()), ".gif"))
      {
        m_pic = LICE_LoadGIF(fn->Get());
        m_gif = LICE_GIF_LoadEx(fn->Get());
        int ms = LICE_GIF_UpdateFrame(m_gif, m_pic);
        if (ms > 0) SetTimer(m_hwnd, RSM_GIF_ANIMATION, ms, NULL);
        else { LICE_GIF_Close(m_gif); m_gif = NULL; }
      }
      else if (!strcmp(WDL_get_fileext(fn->Get()), ".bmp"))
      {
        m_pic = LICE_LoadBMP(fn->Get());
      }
      else if (!strcmp(WDL_get_fileext(fn->Get()), ".ico"))
      {
        m_pic = LICE_LoadIcon(fn->Get());
      }

      InvalidateRect(m_hwnd, NULL, FALSE);
    }

    free(fl);
  }
}

void RSM_PictureWnd::NextImage()
{
  if (m_piclist.GetSize())
  {
    m_picidx++;

    if (m_picidx > m_piclist.GetSize() - 1)
    {
      m_picidx = m_piclist.GetSize() - 1;
      return;
    }

    WDL_FastString *fn = m_piclist.Get(m_picidx);
    if (m_gif) { LICE_GIF_Close(m_gif); m_gif = NULL; }
    if (m_pic) { delete m_pic; m_pic = NULL; }

    if ((!strcmp(WDL_get_fileext(fn->Get()), ".jpg")) ||
      (!strcmp(WDL_get_fileext(fn->Get()), ".jpeg")))
    {
      m_pic = LICE_LoadJPG(fn->Get());
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".png"))
    {
      m_pic = LICE_LoadPNG(fn->Get());
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".gif"))
    {
      m_pic = LICE_LoadGIF(fn->Get());
      m_gif = LICE_GIF_LoadEx(fn->Get());
      int ms = LICE_GIF_UpdateFrame(m_gif, m_pic);
      if (ms > 0) SetTimer(m_hwnd, RSM_GIF_ANIMATION, ms, NULL);
      else { LICE_GIF_Close(m_gif); m_gif = NULL; }
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".bmp"))
    {
      m_pic = LICE_LoadBMP(fn->Get());
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".ico"))
    {
      m_pic = LICE_LoadIcon(fn->Get());
    }

    InvalidateRect(m_hwnd, NULL, FALSE);
  }
}

void RSM_PictureWnd::PreviousImage()
{
  if (m_piclist.GetSize())
  {
    m_picidx--;

    if (m_picidx < 0)
    {
      m_picidx = 0;
      return;
    }

    WDL_FastString *fn = m_piclist.Get(m_picidx);
    if (m_gif) { LICE_GIF_Close(m_gif); m_gif = NULL; }
    if (m_pic) { delete m_pic; m_pic = NULL; }

    if ((!strcmp(WDL_get_fileext(fn->Get()), ".jpg")) ||
      (!strcmp(WDL_get_fileext(fn->Get()), ".jpeg")))
    {
      m_pic = LICE_LoadJPG(fn->Get());
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".png"))
    {
      m_pic = LICE_LoadPNG(fn->Get());
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".gif"))
    {
      m_pic = LICE_LoadGIF(fn->Get());
      m_gif = LICE_GIF_LoadEx(fn->Get());
      int ms = LICE_GIF_UpdateFrame(m_gif, m_pic);
      if (ms > 0) SetTimer(m_hwnd, RSM_GIF_ANIMATION, ms, NULL);
      else { LICE_GIF_Close(m_gif); m_gif = NULL; }
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".bmp"))
    {
      m_pic = LICE_LoadBMP(fn->Get());
    }
    else if (!strcmp(WDL_get_fileext(fn->Get()), ".ico"))
    {
      m_pic = LICE_LoadIcon(fn->Get());
    }

    InvalidateRect(m_hwnd, NULL, FALSE);
  }
}

void RSM_PictureWnd::BlackAndWhite()
{
  m_bw = !m_bw;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::Blur()
{
  m_blur = !m_blur;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::FlipVertically()
{
  m_vert = !m_vert;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::FlipHorizontally()
{
  m_horz = !m_horz;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::Negative()
{
  m_neg = !m_neg;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::LogTransformation()
{
  m_log = !m_log;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::Illinify()
{
  m_illinify = !m_illinify;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::Rotate0()
{
  m_degrees = 0;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::Rotate90()
{
  m_degrees = 90;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::Rotate180()
{
  m_degrees = 180;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::Rotate270()
{
  m_degrees = 270;
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::OnCreate()
{
  g_picwnd = this;
  m_bm = NULL;
  m_pic = NULL;
  m_tmp = NULL;
  m_font = NULL;
  //m_contextmenu = (HMENU)GetSubMenu(LoadMenu(g_inst, MAKEINTRESOURCE(IDR_PICTURE_CONTEXT)), 0);
  SetTimer(m_hwnd, RSM_MENUBAR, RSM_MENUBAR_MS, NULL);
}

void RSM_PictureWnd::OnDestroy()
{
  g_picwnd = NULL;
  if (m_gif) { LICE_GIF_Close(m_gif); m_gif = NULL; }
  if (m_pic) { delete m_pic; m_pic = NULL; }
  if (m_tmp) { delete m_tmp; m_tmp = NULL; }
  if (m_bm) { delete m_bm; m_bm = NULL; }
  m_piclist.Empty(true);
  KillTimer(m_hwnd, RSM_GIF_ANIMATION);
  KillTimer(m_hwnd, RSM_MENUBAR);
}

void RSM_PictureWnd::OnPaint()
{
  PAINTSTRUCT ps;
  HWND cstm = GetDlgItem(g_mainwnd->Handle(), IDC_CUSTOM1);
  RECT r; GetWindowRect(cstm, &r);
  ScreenToClient(m_hwnd, (LPPOINT)&r);
  ScreenToClient(m_hwnd, ((LPPOINT)&r)+1);

  if (!m_bm) m_bm = new LICE_SysBitmap(r.right - r.left, r.bottom - r.top);
  if (!m_tmp) m_tmp = new LICE_SysBitmap(r.right - r.left, r.bottom - r.top);

  m_bm->resize(r.right - r.left, r.bottom - r.top);
  m_tmp->resize(r.right - r.left, r.bottom - r.top);

  LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));

  if (m_pic)
  {
    int wndheight = r.bottom - r.top;
    int wndwidth = r.right - r.left;
    int picheight = m_pic->getHeight();
    int picwidth = m_pic->getWidth();
    int newheight = 0;
    int newwidth = 0;
    int offheight = 0;
    int offwidth = 0;

    double rwnd = (double)wndwidth / (double)wndheight;
    double rpic = (double)picwidth / (double)picheight;

    if (WDL_DefinitelyGreaterThan(rwnd, rpic))
    {
      newheight = wndheight;
      newwidth = picwidth * wndheight / picheight;
    }
    else
    {
      newheight = picheight * wndwidth / picwidth;
      newwidth = wndwidth;
    }

    offheight = (wndheight - newheight) / 2;
    offwidth = (wndwidth - newwidth) / 2;

    LICE_ScaledBlit(m_bm, m_pic, offwidth, offheight, newwidth, newheight, 0.0f, 0.0f,
      (float)m_pic->getWidth(), (float)m_pic->getHeight(), 1.0f, LICE_BLIT_MODE_COPY);

    if (m_bw)
    {
      LICE_ProcessRect(m_bm, offwidth, offheight, newwidth, newheight, bwfunc, NULL);
    }

    if (m_blur)
    {
      LICE_Blur(m_bm, m_bm, 0, 0, 0, 0, m_bm->getWidth(), m_bm->getHeight());
    }

    if (m_vert)
    {
      LICE_Copy(m_tmp, m_bm);
      LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
      LICE_ScaledBlit(m_bm, m_tmp, 0, m_bm->getHeight(),
        m_bm->getWidth(), -m_bm->getHeight(), 0.0f, 0.0f,
        (float)m_tmp->getWidth(), (float)m_tmp->getHeight(),
        1.0f, LICE_BLIT_MODE_COPY);
    }

    if (m_horz)
    {
      LICE_Copy(m_tmp, m_bm);
      LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
      LICE_ScaledBlit(m_bm, m_tmp, m_bm->getWidth(), 0,
        -m_bm->getWidth(), m_bm->getHeight(), 0.0f, 0.0f,
        (float)m_tmp->getWidth(), (float)m_tmp->getHeight(),
        1.0f, LICE_BLIT_MODE_COPY);
    }

    if (m_neg)
    {
      LICE_ProcessRect(m_bm, offwidth, offheight, newwidth, newheight, negfunc, NULL);
    }

    if (m_log)
    {
      LICE_ProcessRect(m_bm, offwidth, offheight, newwidth, newheight, logfunc, NULL);
    }

    if (m_illinify)
    {
      LICE_ProcessRect(m_bm, offwidth, offheight, newwidth, newheight, illinifyfunc, NULL);
    }

    switch (m_degrees)
    {
    case 90:
      {
        LICE_Copy(m_tmp, m_bm);
        LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
        LICE_RotatedBlit(m_bm, m_tmp, 0, 0, m_bm->getWidth(), m_bm->getHeight(),
          0.0f, 0.0f, (float)m_tmp->getWidth(), (float)m_tmp->getHeight(), RSM_PI / 2.0f,
          true, 1.0f, LICE_BLIT_MODE_COPY);
      } break;
    case 180:
      {
        LICE_Copy(m_tmp, m_bm);
        LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
        LICE_RotatedBlit(m_bm, m_tmp, 0, 0, m_bm->getWidth(), m_bm->getHeight(),
          0.0f, 0.0f, (float)m_tmp->getWidth(), (float)m_tmp->getHeight(), RSM_PI,
          true, 1.0f, LICE_BLIT_MODE_COPY);
      } break;
    case 270:
      {
        LICE_Copy(m_tmp, m_bm);
        LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
        LICE_RotatedBlit(m_bm, m_tmp, 0, 0, m_bm->getWidth(), m_bm->getHeight(),
          0.0f, 0.0f, (float)m_tmp->getWidth(), (float)m_tmp->getHeight(), 3.0f * RSM_PI / 2.0f,
          true, 1.0f, LICE_BLIT_MODE_COPY);
      } break;
    }

#if 0
    if (0)
    {
      const int divw = 2;
      const int divh = 2;
      float srcpts[divw * divh * 2] =
      {
        (float)m_bm->getHeight(), 0.0f,
        (float)m_bm->getHeight(), (float)m_bm->getWidth(),
        0.0f, 0.0f,
        0.0f, (float)m_bm->getWidth()
      };

      // Blits to destination at (destx,desty), size (destw,desth). 
      // div_w and div_h should be 2..64, and table should point to
      // a table of 2*div_w*div_h values (this table must not cross
      // a 65536 item boundary). Each pair in the table represents 
      // a S,T coordinate in the source image, and the table is treated
      // as a left-right, top-bottom list of texture coordinates, which
      // will then be rendered to the destination.
      LICE_TransformBlit(m_bm, m_tmp, 0, 0, m_bm->getWidth(), m_bm->getHeight(),
        srcpts, divw, divh, 1.0f, LICE_BLIT_MODE_COPY);
    }

    if (0)
    {
      LICE_Copy(m_tmp, m_bm);
      LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));

      // Blits from srcimg(srcx,srcy,srcw,srch) to destination (destx,desty,destw,desth).
      // Source texture coordinates are s/t, dsdx represents the change in s coordinate
      // for each x pixel, dtdy represents the change in t coordinate for each y pixel, etc.
      // dsdxdy represents the change in dsdx for each line. If usecliprect is specified and 0,
      // then srcw/srch are ignored.
      LICE_DeltaBlit(m_bm, m_tmp, 0, 0, m_bm->getWidth(), m_bm->getHeight(),
        0.0f, 0.0f, (float)m_tmp->getWidth(), (float)m_tmp->getHeight(),
        1.0, 0.0, 0.0, 1.0, 0.0, 0.0, false, 1.0f, LICE_BLIT_MODE_COPY);
    }
#endif
  }

  HDC dc = BeginPaint(cstm, &ps);

  BitBlt(dc, r.left, r.top, r.right - r.left, r.bottom - r.top, m_bm->getDC(), 0, 0, SRCCOPY);

  EndPaint(cstm, &ps);

#if 0
  int xo, yo;
  m_painter.PaintBegin(m_hwnd, RGB(0, 0, 0));
  m_bm = m_painter.GetBuffer(&xo, &yo);
  LICE_Clear(m_bm, LICE_RGBA((m_bgc >> 16) & 0xFF,
    (m_bgc >> 8) & 0xFF, m_bgc & 0xFF, 255));
  //LICE_Line(m_bm, w/2, 0, w/2, h, LICE_RGBA(255, 255, 128, 255), 1.0f, LICE_BLIT_MODE_ADD);
  //LICE_Line(m_bm, 0, h/2, w, h/2, LICE_RGBA(255, 255, 128, 255), 1.0f, LICE_BLIT_MODE_ADD);

  if (!m_font) m_font = new LICE_CachedFont;

  if (!m_font->GetHFont())
  {
    m_font->SetFromHFont(CreateFontIndirect(&lf), LICE_FONT_FLAG_OWNS_HFONT);
  }

  m_font->SetBkMode(TRANSPARENT);
  m_font->SetTextColor(LICE_RGBA((m_txtc >> 16) & 0xFF,
    (m_txtc >> 8) & 0xFF, m_txtc & 0xFF, 255));

  RECT r;
  GetClientRect(m_hwnd, &r);

  int w = r.right - r.left;
  int h = r.bottom - r.top;
  int hw, hh, space, cntr;
  hw = (w > 0) ? w / 2 : 0;
  hh = (h > 0) ? h / 2 : 0;
  space = 20;
  cntr = hw - space;

  int fw = 0, fh = 0, fl = 0;
  int strt = 0, end = 0, margin = 0;

  //POINT pt;
  //GetCursorPos(&pt);
  //ScreenToClient(m_hwnd, &pt);

  m_painter.PaintEnd();
#endif
}

void RSM_PictureWnd::OnLButtonUp()
{

}

void RSM_PictureWnd::OnSize()
{
  InvalidateRect(m_hwnd, NULL, FALSE);
}

void RSM_PictureWnd::OnTimer()
{
  if (m_wparam == RSM_GIF_ANIMATION)
  {
    if (m_gif)
    {
      int ms = LICE_GIF_UpdateFrame(m_gif, m_pic);
      if (ms > 0)
      {
        KillTimer(m_hwnd, RSM_GIF_ANIMATION);
        SetTimer(m_hwnd, RSM_GIF_ANIMATION, ms, NULL);
      }
      else LICE_GIF_Rewind(m_gif);
      InvalidateRect(m_hwnd, NULL, FALSE);
    }
  }

  if (m_wparam == RSM_MENUBAR)
  {
    if (m_piclist.GetSize())
    {
      EnableMenuItem(GetMenu(g_mainwnd->Handle()), ID_FILE_NEXT, MF_ENABLED);
      EnableMenuItem(GetMenu(g_mainwnd->Handle()), ID_FILE_PREVIOUS, MF_ENABLED);
      if (m_picidx == 0) EnableMenuItem(GetMenu(g_mainwnd->Handle()), ID_FILE_PREVIOUS, MF_GRAYED);
      if (m_picidx == m_piclist.GetSize() - 1) EnableMenuItem(GetMenu(g_mainwnd->Handle()), ID_FILE_NEXT, MF_GRAYED);
    }
    else
    {
      EnableMenuItem(GetMenu(g_mainwnd->Handle()), ID_FILE_NEXT, MF_GRAYED);
      EnableMenuItem(GetMenu(g_mainwnd->Handle()), ID_FILE_PREVIOUS, MF_GRAYED);
    }

    if (m_bw) CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_BW, MF_CHECKED);
    else CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_BW, MF_UNCHECKED);

    if (m_blur) CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_BLUR, MF_CHECKED);
    else CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_BLUR, MF_UNCHECKED);

    if (m_vert) CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_FLIPVERTICALLY, MF_CHECKED);
    else CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_FLIPVERTICALLY, MF_UNCHECKED);

    if (m_horz) CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_FLIPHORIZONTALLY, MF_CHECKED);
    else CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_FLIPHORIZONTALLY, MF_UNCHECKED);

    if (m_neg) CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_NEGATIVE, MF_CHECKED);
    else CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_NEGATIVE, MF_UNCHECKED);

    if (m_log) CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_LOGTRANSFORMATION, MF_CHECKED);
    else CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_LOGTRANSFORMATION, MF_UNCHECKED);

    if (m_illinify) CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ILLINIFY, MF_CHECKED);
    else CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ILLINIFY, MF_UNCHECKED);

    switch (m_degrees)
    {
    case 0:
      {
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY0DEGREES, MF_CHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY90DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY180DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY270DEGREES, MF_UNCHECKED);
      } break;
    case 90:
      {
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY0DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY90DEGREES, MF_CHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY180DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY270DEGREES, MF_UNCHECKED);
      } break;
    case 180:
      {
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY0DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY90DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY180DEGREES, MF_CHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY270DEGREES, MF_UNCHECKED);
      } break;
    case 270:
      {
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY0DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY90DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY180DEGREES, MF_UNCHECKED);
        CheckMenuItem(GetMenu(g_mainwnd->Handle()), ID_EDIT_ROTATEBY270DEGREES, MF_CHECKED);
      } break;
    }
  }
}

void RSM_PictureWnd::OnContextMenu()
{
  //POINT pt;
  //GetCursorPos(&pt);
  //TrackPopupMenu(m_contextmenu, TPM_LEFTALIGN, pt.x, pt.y, 0, m_hwnd, NULL);
}

void RSM_PictureWnd::OnCommand()
{
  //switch (LOWORD(m_wparam))
  //{

  //}
}

WDL_DLGRET RSM_PictureWnd::PictureWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
  RSM_PictureWnd *picwnd = (RSM_PictureWnd *)GetWindowLongPtr(hwnd, GWLP_USERDATA);

  //if (!picwnd && msg == WM_INITDIALOG)
  if (!picwnd && msg == WM_NCCREATE)
  {
    picwnd = new RSM_PictureWnd(hwnd);
    SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR)picwnd);
    if (picwnd) picwnd->OnCreate();
    return (picwnd != NULL);
  }

  if (picwnd && msg == WM_NCDESTROY)
  {
    picwnd->OnDestroy();
    delete picwnd; picwnd = NULL;
  }

  if (WDL_likely(picwnd))
  {
    return picwnd->PictureWndLoop(msg, wparam, lparam);
  }
  else
  {
    return 0;
  }
}

WDL_DLGRET RSM_PictureWnd::PictureWndLoop(UINT msg, WPARAM wparam, LPARAM lparam)
{
  m_msg = msg;
  m_wparam = wparam;
  m_lparam = lparam;

  switch (msg)
  {
    case WM_CREATE: OnCreate(); break;
    case WM_DESTROY: OnDestroy(); break;
    case WM_PAINT: OnPaint(); break;
    case WM_LBUTTONUP: OnLButtonUp(); break;
    case WM_SIZE: OnSize(); break;
    case WM_TIMER: OnTimer(); break;
  }

  return DefWindowProc(m_hwnd, msg, wparam, lparam);
}
