summaryrefslogtreecommitdiff
path: root/gtk/gtktextlayout.h
blob: 200b13e128ac8627491c0de8c08ab193aca09034 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#ifndef GTK_TEXT_LAYOUT_H
#define GTK_TEXT_LAYOUT_H

#include <gtk/gtktextbuffer.h>
#include <gtk/gtktextiter.h>
#include <gtk/gtktextbtree.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* This is a "semi-private" header; it is intended for
 * use by the text widget, and the text canvas item,
 * but that's all. We may have to install it so the
 * canvas item can use it, but users are not supposed
 * to use it. 
 */

#define GTK_TYPE_TEXT_LAYOUT             (gtk_text_layout_get_type())
#define GTK_TEXT_LAYOUT(obj)             (GTK_CHECK_CAST ((obj), GTK_TYPE_TEXT_LAYOUT, GtkTextLayout))
#define GTK_TEXT_LAYOUT_CLASS(klass)     (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TEXT_LAYOUT, GtkTextLayoutClass))
#define GTK_IS_TEXT_LAYOUT(obj)          (GTK_CHECK_TYPE ((obj), GTK_TYPE_TEXT_LAYOUT))
#define GTK_IS_TEXT_LAYOUT_CLASS(klass)  (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT_LAYOUT))
#define GTK_TEXT_LAYOUT_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_TEXT_LAYOUT, GtkTextLayoutClass))

typedef struct _GtkTextLayoutClass GtkTextLayoutClass;
typedef struct _GtkTextLineDisplay GtkTextLineDisplay;
typedef struct _GtkTextCursorDisplay GtkTextCursorDisplay;
typedef struct _GtkTextAttrAppearance GtkTextAttrAppearance;

struct _GtkTextLayout
{
  GtkObject parent_instance;

  /* width of the display area on-screen,
   * i.e. pixels we should wrap to fit inside. */
  gint screen_width;

  /* width/height of the total logical area being layed out */
  gint width;
  gint height;

  GtkTextBuffer *buffer;

  /* Default style used if no tags override it */
  GtkTextStyleValues *default_style;

  /* Pango contexts used for creating layouts */
  PangoContext *ltr_context;
  PangoContext *rtl_context;

  /* A cache of one style; this is used to ensure
   * we don't constantly regenerate the style
   * over long runs with the same style. */
  GtkTextStyleValues *one_style_cache;

  /* A cache of one line display. Getting the same line
   * many times in a row is the most common case.
   */
  GtkTextLineDisplay *one_display_cache;
  
  /* Whether we are allowed to wrap right now */
  gint wrap_loop_count;
};

struct _GtkTextLayoutClass
{
  GtkObjectClass parent_class;

  /* Some portion of the layout was invalidated
   */
  void (* invalidated) (GtkTextLayout *layout);

  /* A range of the layout changed appearance and possibly height
   */
  void (* changed)  (GtkTextLayout *layout,
		     gint           y,
		     gint           old_height,
		     gint           new_height);

  
  GtkTextLineData *(* wrap) (GtkTextLayout *layout,
                             GtkTextLine *line,
                             /* may be NULL */
                             GtkTextLineData *line_data);
  
  void (* get_log_attrs) (GtkTextLayout  *layout,
			  GtkTextLine    *line,
			  PangoLogAttr  **attrs,
			  gint           *n_attrs);
  void  (* invalidate)      (GtkTextLayout *layout,
                             const GtkTextIter *start,
                             const GtkTextIter *end);
  void  (* free_line_data) (GtkTextLayout   *layout,
			    GtkTextLine     *line,
			    GtkTextLineData *line_data);
};

struct _GtkTextAttrAppearance
{
  PangoAttribute attr;
  GtkTextAppearance appearance;
};

struct _GtkTextCursorDisplay
{
  gint x;
  gint y;
  gint height;
  guint is_strong : 1;
  guint is_weak : 1;
};

struct _GtkTextLineDisplay
{
  PangoLayout *layout;
  GSList *cursors;
  GSList *pixmaps;

  GtkTextDirection direction;

  gint width;			/* Width of layout */
  gint total_width;		/* width - margins, if no width set on layout, if width set on layout, -1 */
  gint height;
  gint x_offset;		/* Amount layout is shifted from left edge */
  gint left_margin;
  gint right_margin;
  gint top_margin;
  gint bottom_margin;

  gboolean size_only;
  GtkTextLine *line;
};

extern PangoAttrType gtk_text_attr_appearance_type;

GtkType        gtk_text_layout_get_type (void);
GtkTextLayout *gtk_text_layout_new      (void);

void gtk_text_layout_set_buffer            (GtkTextLayout      *layout,
					    GtkTextBuffer      *buffer);
void gtk_text_layout_set_default_style     (GtkTextLayout      *layout,
					    GtkTextStyleValues *values);
void gtk_text_layout_set_contexts          (GtkTextLayout      *layout,
					    PangoContext       *ltr_context,
					    PangoContext       *rtl_context);
void gtk_text_layout_default_style_changed (GtkTextLayout      *layout);
void gtk_text_layout_set_screen_width      (GtkTextLayout      *layout,
					    gint                width);

/* Getting the size or the lines potentially results in a call to
 * recompute, which is pretty massively expensive. Thus it should
 * basically only be done in an idle handler.
 * 
 * Long-term, we would really like to be able to do these without
 * a full recompute so they may get cheaper over time.
 */
void    gtk_text_layout_get_size (GtkTextLayout  *layout,
	  		          gint           *width,
			          gint           *height);


GSList *gtk_text_layout_get_lines (GtkTextLayout *layout,
				   /* [top_y, bottom_y) */
				   gint           top_y, 
				   gint           bottom_y,
				   gint          *first_line_y);

void gtk_text_layout_wrap_loop_start (GtkTextLayout  *layout);
void gtk_text_layout_wrap_loop_end   (GtkTextLayout  *layout);

GtkTextLineDisplay *gtk_text_layout_get_line_display  (GtkTextLayout      *layout,
						       GtkTextLine        *line,
						       gboolean            size_only);
void                gtk_text_layout_free_line_display (GtkTextLayout      *layout,
						       GtkTextLineDisplay *display);

void gtk_text_layout_get_line_at_y     (GtkTextLayout     *layout,
					GtkTextIter       *target_iter,
					gint               y,
					gint              *line_top);
void gtk_text_layout_get_iter_at_pixel (GtkTextLayout     *layout,
					GtkTextIter       *iter,
					gint               x,
					gint               y);
void gtk_text_layout_invalidate        (GtkTextLayout     *layout,
					const GtkTextIter *start,
					const GtkTextIter *end);
void gtk_text_layout_free_line_data    (GtkTextLayout     *layout,
					GtkTextLine       *line,
					GtkTextLineData   *line_data);

gboolean gtk_text_layout_is_valid        (GtkTextLayout *layout);
void     gtk_text_layout_validate_yrange (GtkTextLayout *layout,
					  GtkTextIter   *anchor_line,
					  gint           y0,
					  gint           y1);
void     gtk_text_layout_validate        (GtkTextLayout *layout,
					  gint           max_pixels);

      /* This function should return the passed-in line data,
         OR remove the existing line data from the line, and
         return a NEW line data after adding it to the line.
         That is, invariant after calling the callback is that
         there should be exactly one line data for this view
         stored on the btree line. */
GtkTextLineData *gtk_text_layout_wrap (GtkTextLayout   *layout,
				       GtkTextLine     *line,
                                         /* may be NULL */
				       GtkTextLineData *line_data);
void     gtk_text_layout_get_log_attrs (GtkTextLayout  *layout,
					GtkTextLine    *line,
					PangoLogAttr  **attrs,
					gint           *n_attrs);
void     gtk_text_layout_changed              (GtkTextLayout     *layout,
					       gint               y,
					       gint               old_height,
					       gint               new_height);
void     gtk_text_layout_get_iter_location    (GtkTextLayout     *layout,
					       const GtkTextIter *iter,
					       GdkRectangle      *rect);
gint     gtk_text_layout_get_line_y           (GtkTextLayout     *layout,
					       const GtkTextIter *iter);
void     gtk_text_layout_get_cursor_locations (GtkTextLayout     *layout,
					       GtkTextIter       *iter,
					       GdkRectangle      *strong_pos,
					       GdkRectangle      *weak_pos);
gboolean gtk_text_layout_clamp_iter_to_vrange (GtkTextLayout     *layout,
					       GtkTextIter       *iter,
					       gint               top,
					       gint               bottom);

void gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
						 GtkTextIter   *iter);
void gtk_text_layout_move_iter_to_next_line     (GtkTextLayout *layout,
						 GtkTextIter   *iter);
void gtk_text_layout_move_iter_to_x             (GtkTextLayout *layout,
						 GtkTextIter   *iter,
						 gint           x);
void gtk_text_layout_move_iter_visually         (GtkTextLayout *layout,
						 GtkTextIter   *iter,
						 gint           count);


void gtk_text_layout_spew (GtkTextLayout *layout);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif