/*

Copyright (C) 2009-2011 John W. Eaton

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <cstdlib>

#if defined (OCTAVE_USE_WINDOWS_API)
#include <Windows.h>
#elif defined (HAVE_FRAMEWORK_CARBON)
#include <Carbon/Carbon.h>
#elif defined (HAVE_X_WINDOWS)
#include <X11/Xlib.h>
#endif

#include "display.h"
#include "error.h"

display_info *display_info::instance = 0;

void
display_info::init (bool query)
{
  if (query)
    {
#if defined (OCTAVE_USE_WINDOWS_API)

      HDC hdc = GetDC (0);

      if (hdc)
        {
          dp = GetDeviceCaps (hdc, BITSPIXEL);

          ht = GetDeviceCaps (hdc, VERTRES);
          wd = GetDeviceCaps (hdc, HORZRES);

          double ht_mm = GetDeviceCaps (hdc, VERTSIZE);
          double wd_mm = GetDeviceCaps (hdc, HORZSIZE);

          rx = wd * 25.4 / wd_mm;
          ry = ht * 25.4 / ht_mm;
        }
      else
        warning ("no graphical display found");

#elif defined (HAVE_FRAMEWORK_CARBON)

      CGDirectDisplayID display = CGMainDisplayID ();

      if (display)
        {
          dp = CGDisplayBitsPerPixel (display);

          ht = CGDisplayPixelsHigh (display);
          wd = CGDisplayPixelsWide (display);

          CGSize sz_mm = CGDisplayScreenSize (display);

          // On modern Mac systems (>= 10.5) CGSize is a struct keeping 2
          // CGFloat values, but the CGFloat typedef is not present on
          // older systems, so use double instead.
          double ht_mm = sz_mm.height;
          double wd_mm = sz_mm.width;

          rx = wd * 25.4 / wd_mm;
          ry = ht * 25.4 / ht_mm;
        }
      else
        warning ("no graphical display found");

#elif defined (HAVE_X_WINDOWS)

      const char *display_name = getenv ("DISPLAY");

      if (display_name && *display_name)
        {
          Display *display = XOpenDisplay (display_name);

          if (display)
            {
              Screen *screen = DefaultScreenOfDisplay (display);

              if (screen)
                {
                  dp = DefaultDepthOfScreen (screen);

                  ht = HeightOfScreen (screen);
                  wd = WidthOfScreen (screen);

                  int screen_number = XScreenNumberOfScreen (screen);

                  double ht_mm = DisplayHeightMM (display, screen_number);
                  double wd_mm = DisplayWidthMM (display, screen_number);

                  rx = wd * 25.4 / wd_mm;
                  ry = ht * 25.4 / ht_mm;
                }
              else
                warning ("X11 display has no default screen");
            }
          else
            warning ("unable to open X11 DISPLAY");
        }
      else
        warning ("X11 DISPLAY environment variable not set");
#else

      warning ("no graphical display found");

#endif
    }
}

bool
display_info::instance_ok (bool query)
{
  bool retval = true;

  if (! instance)
    instance = new display_info (query);

  if (! instance)
    {
      ::error ("unable to create display_info object!");

      retval = false;
    }

  return retval;
}
