// * This makes emacs happy -*-Mode: C++;-*-
/****************************************************************************
 * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc.              *
 *                                                                          *
 * Permission is hereby granted, free of charge, to any person obtaining a  *
 * copy of this software and associated documentation files (the            *
 * "Software"), to deal in the Software without restriction, including      *
 * without limitation the rights to use, copy, modify, merge, publish,      *
 * distribute, distribute with modifications, sublicense, and/or sell       *
 * copies of the Software, and to permit persons to whom the Software is    *
 * furnished to do so, subject to the following conditions:                 *
 *                                                                          *
 * The above copyright notice and this permission notice shall be included  *
 * in all copies or substantial portions of the Software.                   *
 *                                                                          *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
 *                                                                          *
 * Except as contained in this notice, the name(s) of the above copyright   *
 * holders shall not be used in advertising or otherwise to promote the     *
 * sale, use or other dealings in this Software without prior written       *
 * authorization.                                                           *
 ****************************************************************************/

/****************************************************************************
 *   Author: Juergen Pfeifer, 1997                                          *
 ****************************************************************************/

// $Id: cursesapp.h,v 1.11 2005/05/28 21:57:44 tom Exp $

#ifndef NCURSES_CURSESAPP_H_incl
#define NCURSES_CURSESAPP_H_incl

#include <cursslk.h>

class NCURSES_IMPEXP NCursesApplication {
public:
  typedef struct _slk_link {          // This structure is used to maintain
    struct _slk_link* prev;           // a stack of SLKs
    Soft_Label_Key_Set* SLKs;
  } SLK_Link;
private:
  static int rinit(NCursesWindow& w); // Internal Init function for title
  static NCursesApplication* theApp;  // Global ref. to the application

  static SLK_Link* slk_stack;

protected:
  static NCursesWindow* titleWindow;  // The Title Window (if any)

  bool b_Colors;                      // Is this a color application?
  NCursesWindow* Root_Window;         // This is the stdscr equiv.

  // Initialization of attributes;
  // Rewrite this in your derived class if you prefer other settings
  virtual void init(bool bColors);

  // The number of lines for the title window. Default is no title window
  // You may rewrite this in your derived class
  virtual int titlesize() const {
    return 0;
  }

  // This method is called to put something into the title window initially
  // You may rewrite this in your derived class
  virtual void title() {
  }

  // The layout used for the Soft Label Keys. Default is to have no SLKs.
  // You may rewrite this in your derived class
  virtual Soft_Label_Key_Set::Label_Layout useSLKs() const {
    return Soft_Label_Key_Set::None;
  }

  // This method is called to initialize the SLKs. Default is nothing.
  // You may rewrite this in your derived class
  virtual void init_labels(Soft_Label_Key_Set& S) const {
  }

  // Your derived class must implement this method. The return value must
  // be the exit value of your application.
  virtual int run() = 0;

  // The constructor is protected, so you may use it in your derived
  // class constructor. The argument tells whether or not you want colors.
  NCursesApplication(bool wantColors = FALSE);

  NCursesApplication& operator=(const NCursesApplication& rhs)
  {
    if (this != &rhs) {
      *this = rhs;
    }
    return *this;
  }

  NCursesApplication(const NCursesApplication& rhs)
    : b_Colors(rhs.b_Colors),
      Root_Window(rhs.Root_Window)
  {
  }

public:
  virtual ~NCursesApplication();

  // Get a pointer to the current application object
  static NCursesApplication* getApplication() {
    return theApp;
  }

  // This method runs the application and returns its exit value
  int operator()(void);

  // Process the commandline arguments. The default implementation simply
  // ignores them. Your derived class may rewrite this.
  virtual void handleArgs(int argc, char* argv[]) {
  }

  // Does this application use colors?
  inline bool useColors() const {
    return b_Colors;
  }

  // Push the Key Set S onto the SLK Stack. S then becomes the current set
  // of Soft Labelled Keys.
  void push(Soft_Label_Key_Set& S);

  // Throw away the current set of SLKs and make the previous one the
  // new current set.
  bool pop();

  // Retrieve the current set of Soft Labelled Keys.
  Soft_Label_Key_Set* top() const;

  // Attributes to use for menu and forms foregrounds
  virtual chtype foregrounds() const {
    return b_Colors ? COLOR_PAIR(1) : A_BOLD;
  }

  // Attributes to use for menu and forms backgrounds
  virtual chtype backgrounds() const {
    return b_Colors ? COLOR_PAIR(2) : A_NORMAL;
  }

  // Attributes to use for inactive (menu) elements
  virtual chtype inactives() const {
    return b_Colors ? (COLOR_PAIR(3)|A_DIM) : A_DIM;
  }

  // Attributes to use for (form) labels and SLKs
  virtual chtype labels() const {
    return b_Colors ? COLOR_PAIR(4) : A_NORMAL;
  }

  // Attributes to use for form backgrounds
  virtual chtype dialog_backgrounds() const {
    return b_Colors ? COLOR_PAIR(4) : A_NORMAL;
  }

  // Attributes to use as default for (form) window backgrounds
  virtual chtype window_backgrounds() const {
    return b_Colors ? COLOR_PAIR(5) : A_NORMAL;
  }

  // Attributes to use for the title window
  virtual chtype screen_titles() const {
    return b_Colors ? COLOR_PAIR(6) : A_BOLD;
  }

};
 
#endif /* NCURSES_CURSESAPP_H_incl */
