/* DiaCanvas -- A technical drawing canvas.
 * Copyright (C) 1999, Arjan Molenaar
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/* diabasetext.h
 * -------------
 * This is the base class for text objects. It does not have handles and it
 * can not let other objects connect. This makes it very easy to add this
 * object to composite objects (like UML classes, cases, etc.).
 * Note that this objets supports the most simple type of text (= single line
 * text).
 */

#ifndef __DIA_BASE_TEXT_H__
#define __DIA_BASE_TEXT_H__

#include <diacanvas/diaobject.h> /* parent object */

DIA_OPEN

#define DIA_BASE_TEXT(x) ((DiaBaseText*) x)
#define DIA_TEXT_LINE(x) ((DiaTextLine*) x)

#define DIA_BASE_TEXT_TEXT_CURSOR GDK_XTERM

typedef struct _DiaBaseText DiaBaseText;
typedef struct _DiaTextLine DiaTextLine;

/* DiaTextLine: represents one line of text. */
struct _DiaTextLine
{
  GString *text;
  Point    pos;   /* position of the text on the canvas according to the text's
		   * alignment. */
  gfloat   width; /* in units */
  gint     update_width: 1; /* notify that the width has to be updated */
  
  /* Selection: (set both values to 0 (zero) to indicate that there is
   * no selection) */
  gint     selection_start;
  gint     selection_end;
};

DiaTextLine* dia_text_line_new (DiaBaseText *text, gchar *str);

void         dia_text_line_free (DiaTextLine *text);

gfloat       dia_text_line_calc_width (DiaTextLine *line, DiaBaseText *text,
				       DiaRenderer *renderer);


struct _DiaBaseText
{
  DiaObject object;

  GList *lines; /* list of DiaTextLine's */
  
  gint max_lines; /* the maximal amount of lines (-1 for no limit) */
  gint max_chars; /* the maximal amount of chars per line (-1 for no limit) */
  gfloat rowspacing; /* the amount of space between rows. */
  
  gint editable: 1; /* can text be edited? */

  /* Cursor pos: */
  Point cursor; /* exact cursor position calculated from the top of the text.
		 * (cursor.x, cursor,y) to (cursor.x, cursor.y + height)
		 * is the cursor. */
  gint cursor_col; /* cursor position calculated for text insertion */
  gint cursor_row;
  
  /* font stuff: */
  DiaFont *font;
  gfloat height;
  DiaColor color;
  DiaHAlignment halign;
  //DiaVAlignment valign;

  /* computed values: */
  gfloat ascent;
  gfloat descent;
};

DiaObjectType* dia_base_text_get_type ();

void dia_base_text_init (DiaBaseText *text);

/* A "new" funtion needs pointer parameters for use with the create tool... */
DiaObject* dia_base_text_new (Point *pos);

void dia_base_text_set_default_text (gchar *string);
void dia_base_text_set_default_height (gfloat height);

void dia_base_text_set_row_spacing (DiaBaseText *text, gfloat spacing);

/* STRING may contain newlines! */
void dia_base_text_set_string (DiaBaseText *text, gchar *string);

void dia_base_text_set_height (DiaBaseText *text, gfloat height);

void dia_base_text_set_font (DiaBaseText *text, DiaFont *font);

void dia_base_text_set_halign (DiaBaseText *text, DiaHAlignment halign);
//void dia_base_text_set_valign (DiaBaseText *text, DiaVAlignment valign);

//void dia_base_text_calculate_bounding_box (DiaBaseText *text);
void dia_base_text_calculate_ascent_descent (DiaBaseText *text);

/* protected: */
/* NOTE: in these functions no type checking is done (since they should
 * only be used in BaseText or an inherited variant)!!! */
void dia_base_text_insert_char (DiaBaseText *text, gint row, gint col,
				gchar chr);
void dia_base_text_delete_char (DiaBaseText *text, gint row, gint col);

void dia_base_line_split_line (DiaBaseText *text, gint row, gint col);
void dia_base_text_merge_lines (DiaBaseText *text, gint firstrow);

void dia_base_text_draw_cursor (DiaBaseText* text, DiaRenderer* renderer,
				gfloat text_bottom);

gint dia_base_text_find_cursor_col (DiaBaseText *text, gint row, gfloat xpos);
gfloat dia_base_text_find_cursor_xpos (DiaBaseText *text, gint row, gint col);
gint dia_base_text_find_cursor_row (DiaBaseText *text, gfloat ypos);
gfloat dia_base_text_find_cursor_ypos (DiaBaseText *text, gint row);
/* The all in one solution: (returns FALSE if POS is not in text. */
gboolean dia_base_text_find_cursor_pos (DiaBaseText *text, Point *pos);

/* This function is used to get the width of a string. It tries to do that
 * by retreiving the last edited display and using its renderer to get the
 * exact width. */
gfloat dia_base_text_string_width (DiaBaseText *text, const gchar *string,
				   gint length);

DIA_CLOSE

#endif /* __DIA_BASE_TEXT_H__ */



