// This may look like C code, but it is really -*- C++ -*-

//<copyright>
// 
// Copyright (c) 1994,95
// Institute for Information Processing and Computer Supported New Media (IICM),
// Graz University of Technology, Austria.
// original version:
// Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University
// Copyright (c) 1991 Silicon Graphics, Inc.
// 
//</copyright>
/*
 * Permission to use, copy, modify, distribute, and sell this software and 
 * its documentation for any purpose is hereby granted without fee, provided
 * that (i) the above copyright notices and this permission notice appear in
 * all copies of the software and related documentation, and (ii) the names of
 * Stanford and Silicon Graphics may not be used in any advertising or
 * publicity relating to the software without the specific, prior written
 * permission of Stanford and Silicon Graphics.
 * 
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 *
 * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
 * OF THIS SOFTWARE.
 */

/*
 * Label - ASCII text glyph with font
 */


#ifndef harmony_widgets_labelpatch_h
#define harmony_widgets_labelpatch_h


//<file>
//
// File:        editlabel.h - interface to editable lable
//
// Created:     10 Mar 94   Michael Pichler
//
// Changed:     12 Jan 95   Michael Pichler
//
//
//</file>


#include <hyperg/widgets/lineeditor.h>

#include <InterViews/glyph.h>
class Brush;
class Color;
class Font;
class String;


//<class>
//
// Name: EditLabel
//
// Purpose: label which can be edited
//          manages a lineeditor,
//          displays label but does not care for redraw
//
//
//</class>


class EditLabel: public Glyph
{
  public:
    EditLabel(
      const char*,                      // initial string
      const Font*,                      // font
      const Color* color,               // character color (foreground)
      const Color* csrcol,              // cursor color
      const Color* selcol,              // selection color
      const Color* invcol,              // selected characters (inverse)
      const Color* chgcol,              // background for modified string (may be nil)
      int hide,                         // hiding flag
      char hidechar                     // character for hiding (when hide is nonzero)
    );
    virtual ~EditLabel();

    // Glyph
    virtual void request(Requisition&) const;
    virtual void allocate(Canvas*, const Allocation&, Extension&);
    void do_allocate(Canvas*, const Allocation&, Extension&);  // basic parts of allocate
    virtual void draw(Canvas*, const Allocation&) const;
    virtual void pick(Canvas*, const Allocation&, int depth, Hit&);

    int hitIndex (float x);  // picking; x = hit.left relative to allocation    

    const char* string()  { return text_.string (); }  // current string (NULL-terminated)
    int strlen()  { return text_.length (); }          // and its length (without NULL)

    void setString(const char*);  // change string; caller responsible for redraw

    int hidden() const  { return hide_; }  // get hide flag

    // cursor positioning
    // when selection flag is set the selection is expanded
    void cursorPosition(int pos, int sel);
    int cursorPosition() const  { return cursorposition_; }
    int markPosition() const    { return markposition_; }
    int selecting() const  { return selecting_; }
    void stopSelecting()   { selecting_ = 0;  markposition_ = cursorposition_; }
    int inSelection(int pos) const;  // is pos inside selection

    void scroll(float x);       // scroll by fixed amount
    void scrollToCursor();      // scroll label such that cursor is visible
    void scrollToMark();        // scroll label such that mark is visible
    void setOffset(float x)     // set scrolling offset (to the left; no value restriction)
    { horoffset_ = -x; }
    float getOffset() const     // return scrolling offset
    { return -horoffset_; }
    void attractMark(int pos);  // if cursor is nearer to pos, swap pos and cursor

    void cursorLeft(int sel);
    void cursorRight(int sel);
    void cursorHome(int sel);
    void cursorEnd(int sel);
    void cursorWordLeft(int sel);
    void cursorWordRight(int sel);
    void selectAll();
    void selectWord(int pos);

    // insert/overwrite mode, cursor display
    void insertMode(int onoff)  { insertmode_ = onoff; }
    void toggleInsert()         { insertmode_ = !insertmode_; }
    void showCursor(int onoff)  { showcursor_ = onoff; }

    void fillSelection(int onoff)  // when turned on, selections to end of string
    { fillselection_ = onoff; }    //   will show selection bar up to right end

    // editing (at current position)
    void insertChar(char);
    void insertString(const char*, int len);
    void deleteChar();  // deletes selection (if set)
    void deleteBackward();
    void deleteToEndOfLine();

    // modification flag (for 2nd background)
    int modified() const    { return modified_; }
    void modify(int onoff)  { modified_ = onoff; }

    // geometry specification (proposal)
    // void setNaturalSize(float nat)  { naturalwidth_ = nat; }
    // void setNaturalSize()  { naturalwith_ = width_ + 2 * hmargin_; }

    Coord width () const { return width_ + hmargin_ + 4.0; }

  private:
    // cannot copy EditLabel when cannot copy for LineEditor
    // (this observation was made by GNU CC)
    EditLabel (const EditLabel&);
    EditLabel& operator = (const EditLabel&);

    LineEditor text_;
    const Font* font_;
    const Color* color_;
    const Color* csrcolor_;
    const Color* selcolor_;
    const Color* invcolor_;
    const Color* chgcolor_;
    int hide_;
    int hidechar_;
    Coord ascent_;
    Coord descent_;
    Coord width_;     // string width
    Coord allwidth_;  // allocation width (excluding hmargin)
    Coord naturalwidth_;
    Coord* chrwidthsum_;
    Brush* brush_;
    float horoffset_;
    float hmargin_;
    int insertmode_;
    int showcursor_;
    int cursorposition_;
    int selecting_;
    int fillselection_;
    int markposition_;  // current selection: between cursor and mark position
    int modified_;

    void compute_metrics();
    void drawCursor(Canvas*, float left, float base, float right) const;
    void drawSelection(Canvas*, float left, float bottom, float right, float top) const;
    void deleteSelection();
};  // class EditLabel


#endif
