/* 
 *  Yudit Unicode Editor Source File
 *
 *  GNU Copyright (C) 1997-2023  Gaspar Sinai <gaspar@yudit.org>  
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License, version 2,
 *  dated June 1991. See file COPYYING for details.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef STextView_h
#define STextView_h

#include "stoolkit/STextIndex.h"
#include "stoolkit/SCursorIndex.h"
#include "stoolkit/STextData.h"
#include "stoolkit/STypes.h"
#include "swidget/SComponent.h"
#include "swindow/SFont.h"
#include "swindow/SWindow.h"
#include "swindow/SSyntaxColors.h"
#include "stoolkit/syntax/SSyntax.h"

typedef SBinHashtable<SS_UINT> SH_UINT;

/**
 * Provide a widget view to STextData
 */
class STextView : public SComponent, STextDataListener
{
public:
  STextView (bool scaleable=true);
  STextView (const SString& utf8, bool scaleable=true);
  virtual ~STextView ();

  /* Every component has this. */
  virtual void redraw (SCanvas *canvas, int x, int y, 
        unsigned int width, unsigned int height);

  void setFont (const SString& font, double fontSize=0.0);
  void setFontSize (double fontSize);

  void setForeground (const SColor& lrfg, const SColor& rlfg);
  virtual void setBackground (const SColor& bg);

  const SColor& getBackground ();
  const SColor& getForeground (bool lr);

  void setAlignment (bool align);
  void setMultiline (bool multiline);
  bool isMultiline () const;

  void setViewPort (const SLocation& viewPort);
  const SLocation& getViewPort();

  virtual void resize (const SDimension& d);

  SCursorIndex getCursorIndex (const SLocation& l);
  SLocation  getCursorLocation (const SCursorIndex& cursorIndex);
 
  SCursorIndex leftOf (const SCursorIndex& ci);
  SCursorIndex rightOf (const SCursorIndex& ci);

  void setLineEndMark (bool lineend);
  bool getLineEndMark () const;

  unsigned int getDocumentHeight () const;

  void setSyntax (const SString& hlMode);
  const SString&  getSyntax () const;

  void setSyntaxColors (const SSyntaxColors& attr);
  const SSyntaxColors&  getSyntaxColors () const;

  void setWordWrap (bool lbm);
  bool getWordWrap () const;

  STextData textData;
  unsigned int lineHeight;
  unsigned int lineAscent;

  void setUnderlineColor (const SColor& c);
  void setClippingArea (int x, int y, 
          unsigned int width, unsigned int height);

  void addSyntaxListener (SSyntaxListener* _listener)
     { syntax.addSyntaxListener (_listener); }

  void setEditable (bool editable);
  void setText (const SString& text);

  SString getSyntaxName () const
  { 
     return syntax.getParser ();
  }
  SString getHighlightName () const
  { 
     return highlightMode;
  }

  void setPrinterPageSize (unsigned int _ps)
   { printerPageSize = _ps; }

  void setHideText(bool is);
  bool isHideText();


private:
  SSyntaxColors     syntaxColors;
  SString           highlightMode;
  SSyntax           syntax;
  bool              isWordWrapOn;
  bool              isEditable;
  bool              isHidingText;
  unsigned int      printerPageSize;
  bool              scaleable;

  SCursorIndex moveCursor (const SCursorIndex& ci, bool up);
   
  unsigned int getLineIndex (int locy);
  void internalRedraw (SCanvas *canvas, int x, int y, 
        unsigned int width, unsigned int height);
  void setVisible (unsigned int line);
  SLocation getTextLocation (const STextIndex& textIndex, bool before=true);

  void setPen();
  /* STextDataListener */
  void textChanged (void* src, const STextDataEvent& event);
  void textChangedInternal (void* src, const STextDataEvent& event);

  unsigned int drawParagraph (SCanvas* c, bool islr, unsigned int line, 
       const SLocation& l, const SLocation& lb, 
       const SLocation& le, bool iswindow=false);
  

  void drawGlyph (SCanvas* c, SLocation& l, unsigned int ext, STextIndex index);



  void syntaxHighlight(STextIndex index, SPen* pen, bool* isError);
  bool checktext(STextIndex index, const char* checkstring);


  void   setReordered();
  void   wrapAndPosition ();
  void   wrapAndPosition (unsigned int from, unsigned int until, int addcount);
  unsigned int  wrapAndPosition (unsigned int line, SH_UINT* cache);

  SFont                font;
  SPen                 lrpen;
  SPen                 rlpen;
  SLocation            viewPort;
  SColor               underlineColor;

  /* per line based arrays */
  SV_UINT              lineSpan; /* how many lines? */
  SVector<SV_UINT>     posBefore;  /* glyph locations */
  SVector<SV_UINT>     posAfter;  /* glyph locations */
  SVector<SV_UINT>     breaks;   /* linebreaks */

  double               fontSize;

  int clipx; int clipy;
  int clipw; int cliph;

  bool                 alignment;
  bool                 multiline;
  bool                 lineend;
};

#endif /* STextView_h */
