Make the "editable" text attribute work properly

This commit is contained in:
Havoc Pennington
2000-06-30 20:23:21 +00:00
parent 44ea90db1d
commit dfc74e1264
13 changed files with 705 additions and 167 deletions

View File

@@ -2532,6 +2532,10 @@ gtk_text_btree_remove_mark (GtkTextBTree *tree,
if (segment->body.mark.name)
g_hash_table_remove(tree->mark_table, segment->body.mark.name);
mark_segment_unref(segment);
segment->body.mark.tree = NULL;
segment->body.mark.line = NULL;
segments_changed(tree);
}

View File

@@ -385,6 +385,44 @@ gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
gtk_text_buffer_insert(buffer, &iter, text, len);
}
gboolean
gtk_text_buffer_insert_interactive(GtkTextBuffer *buffer,
GtkTextIter *iter,
const gchar *text,
gint len,
gboolean editable_by_default)
{
g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), FALSE);
g_return_val_if_fail(text != NULL, FALSE);
if (gtk_text_iter_editable (iter, editable_by_default))
{
gtk_text_buffer_insert (buffer, iter, text, len);
return TRUE;
}
else
return FALSE;
}
gboolean
gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer,
const gchar *text,
gint len,
gboolean default_editable)
{
GtkTextIter iter;
g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), FALSE);
g_return_val_if_fail(text != NULL, FALSE);
gtk_text_buffer_get_iter_at_mark(buffer, &iter,
gtk_text_buffer_get_mark (buffer,
"insert"));
return gtk_text_buffer_insert_interactive (buffer, &iter, text, len,
default_editable);
}
/*
* Deletion
*/
@@ -397,7 +435,7 @@ gtk_text_buffer_real_delete_text(GtkTextBuffer *buffer,
g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
g_return_if_fail(start != NULL);
g_return_if_fail(end != NULL);
gtk_text_btree_delete(start, end);
/* may have deleted the selection... */
@@ -420,6 +458,8 @@ gtk_text_buffer_emit_delete(GtkTextBuffer *buffer,
if (gtk_text_iter_equal(start, end))
return;
gtk_text_iter_reorder (start, end);
gtk_signal_emit(GTK_OBJECT(buffer),
signals[DELETE_TEXT],
start, end);
@@ -437,6 +477,109 @@ gtk_text_buffer_delete (GtkTextBuffer *buffer,
gtk_text_buffer_emit_delete(buffer, start, end);
}
gboolean
gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
GtkTextIter *start_iter,
GtkTextIter *end_iter,
gboolean default_editable)
{
GtkTextMark *end_mark;
GtkTextMark *start_mark;
GtkTextIter iter;
gboolean current_state;
gboolean deleted_stuff = FALSE;
/* Delete all editable text in the range start_iter, end_iter */
g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), FALSE);
g_return_val_if_fail (start_iter != NULL, FALSE);
g_return_val_if_fail (end_iter != NULL, FALSE);
gtk_text_iter_reorder (start_iter, end_iter);
start_mark = gtk_text_buffer_create_mark (buffer, NULL,
start_iter, TRUE);
end_mark = gtk_text_buffer_create_mark (buffer, NULL,
end_iter, FALSE);
iter = *start_iter;
current_state = gtk_text_iter_editable (&iter, default_editable);
while (gtk_text_iter_forward_find_tag_toggle (&iter, NULL))
{
gboolean new_state;
gboolean done = FALSE;
GtkTextIter end;
gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark);
if (gtk_text_iter_compare (&iter, &end) >= 0)
{
done = TRUE;
iter = end; /* clamp to the last boundary */
}
new_state = gtk_text_iter_editable (&iter, default_editable);
if (current_state == new_state)
{
if (done)
{
if (current_state)
{
/* We're ending an editable region. Delete said region. */
GtkTextIter start;
gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
gtk_text_buffer_delete (buffer, &start, &iter);
deleted_stuff = TRUE;
}
break;
}
else
continue;
}
if (current_state && !new_state)
{
/* End of an editable region. Delete it. */
GtkTextIter start;
gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
gtk_text_buffer_delete (buffer, &start, &iter);
current_state = FALSE;
deleted_stuff = TRUE;
}
else
{
/* We are at the start of an editable region. We won't be deleting
* the previous region. Move start mark to start of this region.
*/
g_assert (!current_state && new_state);
gtk_text_buffer_move_mark (buffer, start_mark,
&iter);
current_state = TRUE;
}
if (done)
break;
}
gtk_text_buffer_delete_mark (buffer, start_mark);
gtk_text_buffer_delete_mark (buffer, end_mark);
return deleted_stuff;
}
/*
* Extracting textual buffer contents
*/
@@ -546,8 +689,6 @@ gtk_text_buffer_set_mark(GtkTextBuffer *buffer,
GtkTextIter location;
GtkTextMark *mark;
g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), NULL);
mark = gtk_text_btree_set_mark(buffer->tree,
existing_mark,
mark_name,
@@ -576,6 +717,8 @@ gtk_text_buffer_create_mark(GtkTextBuffer *buffer,
const GtkTextIter *where,
gboolean left_gravity)
{
g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), NULL);
return gtk_text_buffer_set_mark(buffer, NULL, mark_name, where,
left_gravity, FALSE);
}
@@ -586,6 +729,8 @@ gtk_text_buffer_move_mark(GtkTextBuffer *buffer,
const GtkTextIter *where)
{
g_return_if_fail (mark != NULL);
g_return_if_fail (!gtk_text_mark_deleted (mark));
g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
gtk_text_buffer_set_mark(buffer, mark, NULL, where, FALSE, TRUE);
}
@@ -595,6 +740,8 @@ gtk_text_buffer_get_iter_at_mark(GtkTextBuffer *buffer,
GtkTextIter *iter,
GtkTextMark *mark)
{
g_return_if_fail (mark != NULL);
g_return_if_fail (!gtk_text_mark_deleted (mark));
g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
gtk_text_btree_get_iter_at_mark(buffer->tree,
@@ -606,6 +753,8 @@ void
gtk_text_buffer_delete_mark(GtkTextBuffer *buffer,
GtkTextMark *mark)
{
g_return_if_fail (mark != NULL);
g_return_if_fail (!gtk_text_mark_deleted (mark));
g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
gtk_text_btree_remove_mark (buffer->tree, mark);
@@ -1186,8 +1335,12 @@ selection_received (GtkWidget *widget,
utf = gtk_text_latin1_to_utf((const gchar*)selection_data->data,
selection_data->length);
gtk_text_buffer_insert (buffer, &insert_point,
utf, -1);
if (buffer->paste_interactive)
gtk_text_buffer_insert_interactive (buffer, &insert_point,
utf, -1, buffer->paste_default_editable);
else
gtk_text_buffer_insert (buffer, &insert_point,
utf, -1);
g_free(utf);
}
break;
@@ -1216,8 +1369,13 @@ selection_received (GtkWidget *widget,
gchar *utf;
utf = gtk_text_latin1_to_utf(list[i], strlen(list[i]));
gtk_text_buffer_insert(buffer, &insert_point, utf, -1);
if (buffer->paste_interactive)
gtk_text_buffer_insert_interactive (buffer, &insert_point,
utf, -1, buffer->paste_default_editable);
else
gtk_text_buffer_insert (buffer, &insert_point,
utf, -1);
g_free(utf);
}
@@ -1306,9 +1464,14 @@ gtk_text_buffer_update_clipboard_selection(GtkTextBuffer *buffer)
}
static void
paste(GtkTextBuffer *buffer, GdkAtom selection, guint32 time)
paste (GtkTextBuffer *buffer, GdkAtom selection, guint32 time,
gboolean interactive,
gboolean default_editable)
{
ensure_handlers(buffer);
buffer->paste_interactive = interactive;
buffer->paste_default_editable = default_editable;
gtk_selection_convert (buffer->selection_widget, selection,
utf8_atom, time);
@@ -1317,25 +1480,31 @@ paste(GtkTextBuffer *buffer, GdkAtom selection, guint32 time)
void
gtk_text_buffer_paste_primary_selection(GtkTextBuffer *buffer,
GtkTextIter *override_location,
guint32 time)
guint32 time,
gboolean interactive,
gboolean default_editable)
{
if (override_location != NULL)
gtk_text_buffer_create_mark(buffer,
"__paste_point_override",
override_location, FALSE);
paste(buffer, GDK_SELECTION_PRIMARY, time);
paste(buffer, GDK_SELECTION_PRIMARY, time, interactive, default_editable);
}
void
gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
guint32 time)
guint32 time,
gboolean interactive,
gboolean default_editable)
{
paste(buffer, clipboard_atom, time);
paste(buffer, clipboard_atom, time, interactive, default_editable);
}
gboolean
gtk_text_buffer_delete_selection (GtkTextBuffer *buffer)
gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
gboolean interactive,
gboolean default_editable)
{
GtkTextIter start;
GtkTextIter end;
@@ -1346,7 +1515,11 @@ gtk_text_buffer_delete_selection (GtkTextBuffer *buffer)
}
else
{
gtk_text_buffer_delete(buffer, &start, &end);
if (interactive)
gtk_text_buffer_delete_interactive (buffer, &start, &end, default_editable);
else
gtk_text_buffer_delete (buffer, &start, &end);
gtk_text_buffer_update_primary_selection(buffer);
return TRUE; /* We deleted stuff */
}
@@ -1355,7 +1528,9 @@ gtk_text_buffer_delete_selection (GtkTextBuffer *buffer)
static void
cut_or_copy(GtkTextBuffer *buffer,
guint32 time,
gboolean delete_region_after)
gboolean delete_region_after,
gboolean interactive,
gboolean default_editable)
{
/* We prefer to cut the selected region between selection_bound and
insertion point. If that region is empty, then we cut the region
@@ -1389,22 +1564,29 @@ cut_or_copy(GtkTextBuffer *buffer,
set_clipboard_contents_nocopy(buffer, text);
if (delete_region_after)
gtk_text_buffer_delete(buffer, &start, &end);
{
if (interactive)
gtk_text_buffer_delete_interactive (buffer, &start, &end, default_editable);
else
gtk_text_buffer_delete (buffer, &start, &end);
}
}
}
void
gtk_text_buffer_cut (GtkTextBuffer *buffer,
guint32 time)
guint32 time,
gboolean interactive,
gboolean default_editable)
{
cut_or_copy(buffer, time, TRUE);
cut_or_copy(buffer, time, TRUE, interactive, default_editable);
}
void
gtk_text_buffer_copy (GtkTextBuffer *buffer,
guint32 time)
{
cut_or_copy(buffer, time, FALSE);
cut_or_copy(buffer, time, FALSE, FALSE, TRUE);
}

View File

@@ -42,6 +42,8 @@ struct _GtkTextBuffer {
GtkWidget *selection_widget;
gboolean have_selection;
gboolean selection_handlers_installed;
gboolean paste_interactive;
gboolean paste_default_editable;
};
struct _GtkTextBufferClass {
@@ -105,11 +107,27 @@ void gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
const gchar *text,
gint len);
/* Delete from the buffer */
gboolean gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer,
GtkTextIter *iter,
const gchar *text,
gint len,
gboolean default_editable);
gboolean gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer,
const gchar *text,
gint len,
gboolean default_editable);
/* Delete from the buffer */
void gtk_text_buffer_delete (GtkTextBuffer *buffer,
GtkTextIter *start_iter,
GtkTextIter *end_iter);
gboolean gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
GtkTextIter *start_iter,
GtkTextIter *end_iter,
gboolean default_editable);
void gtk_text_buffer_delete (GtkTextBuffer *buffer,
GtkTextIter *start_iter,
GtkTextIter *end_iter);
/* Obtain strings from the buffer */
gchar *gtk_text_buffer_get_text (GtkTextBuffer *buffer,
@@ -207,16 +225,26 @@ void gtk_text_buffer_set_modified (GtkTextBuffer *buffer,
void gtk_text_buffer_set_clipboard_contents (GtkTextBuffer *buffer,
const gchar *text);
const gchar *gtk_text_buffer_get_clipboard_contents (GtkTextBuffer *buffer);
void gtk_text_buffer_paste_primary_selection (GtkTextBuffer *buffer,
GtkTextIter *override_location,
guint32 time);
gboolean gtk_text_buffer_delete_selection (GtkTextBuffer *buffer);
guint32 time,
gboolean interactive,
gboolean default_editable);
gboolean gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
gboolean interactive,
gboolean default_editable);
void gtk_text_buffer_cut (GtkTextBuffer *buffer,
guint32 time);
guint32 time,
gboolean interactive,
gboolean default_editable);
void gtk_text_buffer_copy (GtkTextBuffer *buffer,
guint32 time);
void gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
guint32 time);
guint32 time,
gboolean interactive,
gboolean default_editable);
gboolean gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end);

View File

@@ -858,6 +858,26 @@ gtk_text_iter_has_tag (const GtkTextIter *iter,
}
}
gboolean
gtk_text_iter_editable (const GtkTextIter *iter,
gboolean default_setting)
{
GtkTextStyleValues *values;
gboolean retval;
values = gtk_text_style_values_new ();
values->editable = default_setting;
gtk_text_iter_get_style_values (iter, values);
retval = values->editable;
gtk_text_style_values_unref (values);
return retval;
}
gboolean
gtk_text_iter_starts_line (const GtkTextIter *iter)
{
@@ -933,6 +953,37 @@ gtk_text_iter_get_chars_in_line (const GtkTextIter *iter)
return count;
}
gboolean
gtk_text_iter_get_style_values (const GtkTextIter *iter,
GtkTextStyleValues *values)
{
GtkTextTag** tags;
gint tag_count = 0;
/* Get the tags at this spot */
tags = gtk_text_btree_get_tags (iter, &tag_count);
/* No tags, use default style */
if (tags == NULL || tag_count == 0)
{
if (tags)
g_free (tags);
return FALSE;
}
/* Sort tags in ascending order of priority */
gtk_text_tag_array_sort (tags, tag_count);
gtk_text_style_values_fill_from_tags (values,
tags,
tag_count);
g_free (tags);
return TRUE;
}
/*
* Increments/decrements
*/

View File

@@ -46,10 +46,12 @@ void gtk_text_iter_free (GtkTextIter *iter);
/*
* Convert to different kinds of index
*/
gint gtk_text_buffer_get_offset (const GtkTextIter *iter);
gint gtk_text_iter_get_line (const GtkTextIter *iter);
gint gtk_text_iter_get_line_offset (const GtkTextIter *iter);
gint gtk_text_iter_get_line_index (const GtkTextIter *iter);
gint gtk_text_buffer_get_offset (const GtkTextIter *iter);
gint gtk_text_iter_get_line (const GtkTextIter *iter);
gint gtk_text_iter_get_line_offset (const GtkTextIter *iter);
gint gtk_text_iter_get_line_index (const GtkTextIter *iter);
/*
* "Dereference" operators
@@ -72,19 +74,19 @@ gchar *gtk_text_iter_get_visible_text (const GtkTextIter *start,
/* Returns TRUE if the iterator pointed at a pixmap */
gboolean gtk_text_iter_get_pixmap (const GtkTextIter *iter,
GdkPixmap **pixmap,
GdkBitmap **mask);
GdkPixmap **pixmap,
GdkBitmap **mask);
/* Return list of tags toggled at this point (toggled_on determines
whether the list is of on-toggles or off-toggles) */
GSList *gtk_text_iter_get_toggled_tags (const GtkTextIter *iter,
gboolean toggled_on);
gboolean toggled_on);
gboolean gtk_text_iter_begins_tag (const GtkTextIter *iter,
GtkTextTag *tag);
GtkTextTag *tag);
gboolean gtk_text_iter_ends_tag (const GtkTextIter *iter,
GtkTextTag *tag);
GtkTextTag *tag);
gboolean gtk_text_iter_toggles_tag (const GtkTextIter *iter,
GtkTextTag *tag);
@@ -92,11 +94,17 @@ gboolean gtk_text_iter_toggles_tag (const GtkTextIter *iter,
gboolean gtk_text_iter_has_tag (const GtkTextIter *iter,
GtkTextTag *tag);
gboolean gtk_text_iter_editable (const GtkTextIter *iter,
gboolean default_setting);
gboolean gtk_text_iter_starts_line (const GtkTextIter *iter);
gboolean gtk_text_iter_ends_line (const GtkTextIter *iter);
gint gtk_text_iter_get_chars_in_line (const GtkTextIter *iter);
gboolean gtk_text_iter_get_style_values (const GtkTextIter *iter,
GtkTextStyleValues *values);
/*
* Moving around the buffer
*/
@@ -120,25 +128,24 @@ gboolean gtk_text_iter_backward_word_starts (GtkTextIter *iter,
gboolean gtk_text_iter_forward_word_end (GtkTextIter *iter);
gboolean gtk_text_iter_backward_word_start (GtkTextIter *iter);
void gtk_text_iter_set_offset (GtkTextIter *iter,
gint char_index);
void gtk_text_iter_set_line (GtkTextIter *iter,
gint line_number);
void gtk_text_iter_set_line_offset (GtkTextIter *iter,
gint char_on_line);
void gtk_text_iter_forward_to_end (GtkTextIter *iter);
gboolean gtk_text_iter_forward_to_newline (GtkTextIter *iter);
void gtk_text_iter_set_offset (GtkTextIter *iter,
gint char_index);
void gtk_text_iter_set_line (GtkTextIter *iter,
gint line_number);
void gtk_text_iter_set_line_offset (GtkTextIter *iter,
gint char_on_line);
void gtk_text_iter_forward_to_end (GtkTextIter *iter);
gboolean gtk_text_iter_forward_to_newline(GtkTextIter *iter);
/* returns TRUE if a toggle was found; NULL for the tag pointer
means "any tag toggle", otherwise the next toggle of the
specified tag is located. */
gboolean gtk_text_iter_forward_find_tag_toggle (GtkTextIter *iter,
GtkTextTag *tag);
GtkTextTag *tag);
gboolean gtk_text_iter_backward_find_tag_toggle (GtkTextIter *iter,
GtkTextTag *tag);
GtkTextTag *tag);
typedef gboolean (* GtkTextCharPredicate) (gunichar ch, gpointer user_data);

View File

@@ -35,6 +35,41 @@ gtk_text_mark_get_name (GtkTextMark *mark)
return g_strdup (seg->body.mark.name);
}
GtkTextMark *
gtk_text_mark_ref (GtkTextMark *mark)
{
GtkTextLineSegment *seg;
seg = (GtkTextLineSegment*)mark;
mark_segment_ref (seg);
return mark;
}
void
gtk_text_mark_unref (GtkTextMark *mark)
{
GtkTextLineSegment *seg;
seg = (GtkTextLineSegment*)mark;
mark_segment_unref (seg);
}
gboolean
gtk_text_mark_deleted (GtkTextMark *mark)
{
GtkTextLineSegment *seg;
g_return_val_if_fail (mark != NULL, FALSE);
seg = (GtkTextLineSegment*)mark;
return seg->body.mark.tree == NULL;
}
/*
* Macro that determines the size of a mark segment:
*/

View File

@@ -10,11 +10,16 @@ extern "C" {
typedef struct _GtkTextMark GtkTextMark;
void gtk_text_mark_set_visible (GtkTextMark *mark,
gboolean setting);
gboolean setting);
gboolean gtk_text_mark_is_visible (GtkTextMark *mark);
char * gtk_text_mark_get_name (GtkTextMark *mark);
GtkTextMark *gtk_text_mark_ref (GtkTextMark *mark);
void gtk_text_mark_unref (GtkTextMark *mark);
gboolean gtk_text_mark_deleted (GtkTextMark *mark);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -103,6 +103,100 @@ gint gtk_text_tag_event (GtkTextTag *tag,
GdkEvent *event,
const GtkTextIter *iter);
/*
* Style object created by folding a set of tags together
*/
typedef struct _GtkTextAppearance GtkTextAppearance;
struct _GtkTextAppearance
{
GdkColor bg_color;
GdkColor fg_color;
GdkBitmap *bg_stipple;
GdkBitmap *fg_stipple;
guint underline : 4; /* PangoUnderline */
guint overstrike : 1;
/* Whether to use background-related values; this is irrelevant for
* the values struct when in a tag, but is used for the composite
* values struct; it's true if any of the tags being composited
* had background stuff set. */
guint draw_bg : 1;
/* This is only used when we are actually laying out and rendering
* a paragraph; not when a GtkTextAppearance is part of a
* GtkTextStyleValues.
*/
guint inside_selection : 1;
};
struct _GtkTextStyleValues
{
guint refcount;
GtkTextAppearance appearance;
gint border_width;
GtkShadowType relief;
GtkJustification justify;
GtkTextDirection direction;
PangoFontDescription *font_desc;
/* lMargin1 */
gint left_margin;
/* lMargin2 */
gint left_wrapped_line_margin;
/* super/subscript offset, can be negative */
gint offset;
gint right_margin;
gint pixels_above_lines;
gint pixels_below_lines;
gint pixels_inside_wrap;
GtkTextTabArray *tab_array;
GtkWrapMode wrap_mode; /* How to handle wrap-around for this tag.
* Must be GTK_WRAPMODE_CHAR,
* GTK_WRAPMODE_NONE, GTK_WRAPMODE_WORD
*/
gchar *language;
/* hide the text */
guint invisible : 1;
/* Background is fit to full line height rather than
* baseline +/- ascent/descent (font height) */
guint bg_full_height : 1;
/* can edit this text */
guint editable : 1;
/* colors are allocated etc. */
guint realized : 1;
guint pad1 : 1;
guint pad2 : 1;
guint pad3 : 1;
guint pad4 : 1;
};
GtkTextStyleValues *gtk_text_style_values_new (void);
void gtk_text_style_values_copy (GtkTextStyleValues *src,
GtkTextStyleValues *dest);
void gtk_text_style_values_unref (GtkTextStyleValues *values);
void gtk_text_style_values_ref (GtkTextStyleValues *values);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -13,99 +13,6 @@ void gtk_text_style_values_fill_from_tags (GtkTextStyleValues *values,
void gtk_text_tag_array_sort (GtkTextTag **tag_array_p,
guint len);
/*
* Style object created by folding a set of tags together
*/
typedef struct _GtkTextAppearance GtkTextAppearance;
struct _GtkTextAppearance
{
GdkColor bg_color;
GdkColor fg_color;
GdkBitmap *bg_stipple;
GdkBitmap *fg_stipple;
guint underline : 4; /* PangoUnderline */
guint overstrike : 1;
/* Whether to use background-related values; this is irrelevant for
* the values struct when in a tag, but is used for the composite
* values struct; it's true if any of the tags being composited
* had background stuff set. */
guint draw_bg : 1;
/* This is only used when we are actually laying out and rendering
* a paragraph; not when a GtkTextAppearance is part of a
* GtkTextStyleValues.
*/
guint inside_selection : 1;
};
struct _GtkTextStyleValues
{
guint refcount;
GtkTextAppearance appearance;
gint border_width;
GtkShadowType relief;
GtkJustification justify;
GtkTextDirection direction;
PangoFontDescription *font_desc;
/* lMargin1 */
gint left_margin;
/* lMargin2 */
gint left_wrapped_line_margin;
/* super/subscript offset, can be negative */
gint offset;
gint right_margin;
gint pixels_above_lines;
gint pixels_below_lines;
gint pixels_inside_wrap;
GtkTextTabArray *tab_array;
GtkWrapMode wrap_mode; /* How to handle wrap-around for this tag.
* Must be GTK_WRAPMODE_CHAR,
* GTK_WRAPMODE_NONE, GTK_WRAPMODE_WORD
*/
gchar *language;
/* hide the text */
guint invisible : 1;
/* Background is fit to full line height rather than
* baseline +/- ascent/descent (font height) */
guint bg_full_height : 1;
/* can edit this text */
guint editable : 1;
/* colors are allocated etc. */
guint realized : 1;
guint pad1 : 1;
guint pad2 : 1;
guint pad3 : 1;
guint pad4 : 1;
};
GtkTextStyleValues *gtk_text_style_values_new (void);
void gtk_text_style_values_copy (GtkTextStyleValues *src,
GtkTextStyleValues *dest);
void gtk_text_style_values_unref (GtkTextStyleValues *values);
void gtk_text_style_values_ref (GtkTextStyleValues *values);
/* ensure colors are allocated, etc. for drawing */
void gtk_text_style_values_realize (GtkTextStyleValues *values,
GdkColormap *cmap,

View File

@@ -610,6 +610,9 @@ gtk_text_view_init (GtkTextView *text_view)
gtk_signal_connect (GTK_OBJECT (text_view->im_context), "commit",
GTK_SIGNAL_FUNC (gtk_text_view_commit_handler), text_view);
text_view->editable = TRUE;
text_view->cursor_visible = TRUE;
}
GtkWidget*
@@ -932,6 +935,62 @@ gtk_text_view_get_wrap_mode (GtkTextView *text_view)
return text_view->wrap_mode;
}
void
gtk_text_view_set_editable (GtkTextView *text_view,
gboolean setting)
{
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
if (text_view->editable != setting)
{
text_view->editable = setting;
if (text_view->layout)
{
text_view->layout->default_style->editable = text_view->editable;
gtk_text_layout_default_style_changed (text_view->layout);
}
}
}
gboolean
gtk_text_view_get_editable (GtkTextView *text_view)
{
g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
return text_view->editable;
}
void
gtk_text_view_set_cursor_visible (GtkTextView *text_view,
gboolean setting)
{
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
if (text_view->cursor_visible != setting)
{
text_view->cursor_visible = setting;
if (GTK_WIDGET_HAS_FOCUS (text_view))
{
GtkTextMark *insert;
insert = gtk_text_buffer_get_mark (text_view->buffer,
"insert");
gtk_text_mark_set_visible (insert, text_view->cursor_visible);
}
}
}
gboolean
gtk_text_view_get_cursor_visible (GtkTextView *text_view)
{
g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
return text_view->cursor_visible;
}
gboolean
gtk_text_view_place_cursor_onscreen (GtkTextView *text_view)
{
@@ -1483,7 +1542,8 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
return TRUE;
else if (event->keyval == GDK_Return)
{
gtk_text_buffer_insert_at_cursor (text_view->buffer, "\n", 1);
gtk_text_buffer_insert_interactive_at_cursor (text_view->buffer, "\n", 1,
text_view->editable);
gtk_text_view_scroll_to_mark (text_view,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"),
@@ -1553,7 +1613,9 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
gtk_text_buffer_paste_primary_selection (text_view->buffer,
&iter,
event->time);
event->time,
TRUE,
text_view->editable);
return TRUE;
}
else if (event->button == 3)
@@ -1589,7 +1651,7 @@ gtk_text_view_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
insert = gtk_text_buffer_get_mark (GTK_TEXT_VIEW (widget)->buffer,
"insert");
gtk_text_mark_set_visible (insert, TRUE);
gtk_text_mark_set_visible (insert, GTK_TEXT_VIEW (widget)->cursor_visible);
gtk_text_view_start_cursor_blink (GTK_TEXT_VIEW (widget));
@@ -1968,7 +2030,8 @@ gtk_text_view_delete_text (GtkTextView *text_view,
if (type == GTK_TEXT_DELETE_CHAR)
{
/* Char delete deletes the selection, if one exists */
if (gtk_text_buffer_delete_selection (text_view->buffer))
if (gtk_text_buffer_delete_selection (text_view->buffer, TRUE,
text_view->editable))
return;
}
@@ -2048,10 +2111,14 @@ gtk_text_view_delete_text (GtkTextView *text_view,
if (!gtk_text_iter_equal (&start, &end))
{
gtk_text_buffer_delete (text_view->buffer, &start, &end);
if (leave_one)
gtk_text_buffer_insert_at_cursor (text_view->buffer, " ", 1);
if (gtk_text_buffer_delete_interactive (text_view->buffer, &start, &end,
text_view->editable))
{
if (leave_one)
gtk_text_buffer_insert_interactive_at_cursor (text_view->buffer,
" ", 1,
text_view->editable);
}
gtk_text_view_scroll_to_mark (text_view,
gtk_text_buffer_get_mark (text_view->buffer, "insert"),
@@ -2062,7 +2129,7 @@ gtk_text_view_delete_text (GtkTextView *text_view,
static void
gtk_text_view_cut_text (GtkTextView *text_view)
{
gtk_text_buffer_cut (text_view->buffer, GDK_CURRENT_TIME);
gtk_text_buffer_cut (text_view->buffer, GDK_CURRENT_TIME, TRUE, text_view->editable);
gtk_text_view_scroll_to_mark (text_view,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"),
@@ -2082,7 +2149,7 @@ gtk_text_view_copy_text (GtkTextView *text_view)
static void
gtk_text_view_paste_text (GtkTextView *text_view)
{
gtk_text_buffer_paste_clipboard (text_view->buffer, GDK_CURRENT_TIME);
gtk_text_buffer_paste_clipboard (text_view->buffer, GDK_CURRENT_TIME, TRUE, text_view->editable);
gtk_text_view_scroll_to_mark (text_view,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"),
@@ -2561,9 +2628,10 @@ gtk_text_view_drag_data_get (GtkWidget *widget,
static void
gtk_text_view_drag_data_delete (GtkWidget *widget,
GdkDragContext *context)
GdkDragContext *context)
{
gtk_text_buffer_delete_selection (GTK_TEXT_VIEW (widget)->buffer);
gtk_text_buffer_delete_selection (GTK_TEXT_VIEW (widget)->buffer,
TRUE, GTK_TEXT_VIEW (widget)->editable);
}
static void
@@ -2604,9 +2672,18 @@ gtk_text_view_drag_motion (GtkWidget *widget,
}
else
{
gtk_text_mark_set_visible (text_view->dnd_mark, TRUE);
gdk_drag_status (context, context->suggested_action, time);
if (gtk_text_iter_editable (&newplace, text_view->editable))
{
gtk_text_mark_set_visible (text_view->dnd_mark, text_view->cursor_visible);
gdk_drag_status (context, context->suggested_action, time);
}
else
{
/* Can't drop here. */
gdk_drag_status (context, 0, time);
gtk_text_mark_set_visible (text_view->dnd_mark, FALSE);
}
}
gtk_text_buffer_move_mark (text_view->buffer,
@@ -2706,16 +2783,18 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
utf = gtk_text_latin1_to_utf ((const gchar*)selection_data->data,
selection_data->length);
gtk_text_buffer_insert (text_view->buffer, &drop_point,
utf, -1);
gtk_text_buffer_insert_interactive (text_view->buffer, &drop_point,
utf, -1,
text_view->editable);
g_free (utf);
}
break;
case UTF8:
gtk_text_buffer_insert (text_view->buffer, &drop_point,
(const gchar *)selection_data->data,
selection_data->length);
gtk_text_buffer_insert_interactive (text_view->buffer, &drop_point,
(const gchar *)selection_data->data,
selection_data->length,
text_view->editable);
break;
case CTEXT:
@@ -2737,7 +2816,9 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
utf = gtk_text_latin1_to_utf (list[i], strlen (list[i]));
gtk_text_buffer_insert (text_view->buffer, &drop_point, utf, -1);
gtk_text_buffer_insert_interactive (text_view->buffer,
&drop_point, utf, -1,
text_view->editable);
g_free (utf);
}
@@ -2852,17 +2933,20 @@ gtk_text_view_commit_handler (GtkIMContext *context,
const gchar *str,
GtkTextView *text_view)
{
gtk_text_buffer_delete_selection (text_view->buffer);
gtk_text_buffer_delete_selection (text_view->buffer, TRUE,
text_view->editable);
if (!strcmp (str, "\n"))
{
gtk_text_buffer_insert_at_cursor (text_view->buffer, "\n", 1);
gtk_text_buffer_insert_interactive_at_cursor (text_view->buffer, "\n", 1,
text_view->editable);
}
else
{
if (text_view->overwrite_mode)
gtk_text_view_delete_text (text_view, GTK_TEXT_DELETE_CHAR, 1);
gtk_text_buffer_insert_at_cursor (text_view->buffer, str, strlen (str));
gtk_text_buffer_insert_interactive_at_cursor (text_view->buffer, str, -1,
text_view->editable);
}
gtk_text_view_scroll_to_mark (text_view,

View File

@@ -64,6 +64,10 @@ struct _GtkTextView {
GtkWrapMode wrap_mode; /* Default wrap mode */
gboolean editable; /* default editability */
gboolean cursor_visible;
GdkWindow *bin_window;
GtkAdjustment *hadjustment;
GtkAdjustment *vadjustment;
@@ -144,6 +148,15 @@ void gtk_text_view_set_wrap_mode (GtkTextView *text_view,
GtkWrapMode wrap_mode);
GtkWrapMode gtk_text_view_get_wrap_mode (GtkTextView *text_view);
void gtk_text_view_set_editable (GtkTextView *text_view,
gboolean setting);
gboolean gtk_text_view_get_editable (GtkTextView *text_view);
void gtk_text_view_set_cursor_visible (GtkTextView *text_view,
gboolean setting);
gboolean gtk_text_view_get_cursor_visible (GtkTextView *text_view);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -20,6 +20,7 @@ struct _Buffer
GtkTextBuffer *buffer;
char *filename;
gint untitled_serial;
GtkTextTag *not_editable_tag;
};
struct _View
@@ -839,6 +840,53 @@ do_direction_changed (gpointer callback_data,
gtk_widget_queue_resize (view->text_view);
}
static void
do_editable_changed (gpointer callback_data,
guint callback_action,
GtkWidget *widget)
{
View *view = view_from_widget (widget);
gtk_text_view_set_editable (GTK_TEXT_VIEW (view->text_view), callback_action);
}
static void
do_cursor_visible_changed (gpointer callback_data,
guint callback_action,
GtkWidget *widget)
{
View *view = view_from_widget (widget);
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), callback_action);
}
static void
do_apply_editable (gpointer callback_data,
guint callback_action,
GtkWidget *widget)
{
View *view = view_from_widget (widget);
GtkTextIter start;
GtkTextIter end;
if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
&start, &end))
{
if (callback_action)
{
gtk_text_buffer_remove_tag (view->buffer->buffer,
"ineditable",
&start, &end);
}
else
{
gtk_text_buffer_apply_tag (view->buffer->buffer,
"ineditable",
&start, &end);
}
}
}
static void
view_init_menus (View *view)
{
@@ -893,9 +941,19 @@ static GtkItemFactoryEntry menu_items[] =
{ "/Settings/Wrap _Off", NULL, do_wrap_changed, GTK_WRAPMODE_NONE, "<RadioItem>" },
{ "/Settings/Wrap _Words", NULL, do_wrap_changed, GTK_WRAPMODE_WORD, "/Settings/Wrap Off" },
{ "/Settings/sep1", NULL, 0, 0, "<Separator>" },
{ "/Settings/Editable", NULL, do_editable_changed, TRUE, "<RadioItem>" },
{ "/Settings/Not editable", NULL, do_editable_changed, FALSE, "/Settings/Editable" },
{ "/Settings/sep1", NULL, 0, 0, "<Separator>" },
{ "/Settings/Cursor visible", NULL, do_cursor_visible_changed, TRUE, "<RadioItem>" },
{ "/Settings/Cursor not visible", NULL, do_cursor_visible_changed, FALSE, "/Settings/Cursor visible" },
{ "/Settings/sep1", NULL, 0, 0, "<Separator>" },
{ "/Settings/Left-to-Right", NULL, do_direction_changed, GTK_TEXT_DIR_LTR, "<RadioItem>" },
{ "/Settings/Right-to-Left", NULL, do_direction_changed, GTK_TEXT_DIR_RTL, "/Settings/Left-to-Right" },
{ "/_Attributes", NULL, 0, 0, "<Branch>" },
{ "/Attributes/Editable", NULL, do_apply_editable, TRUE, NULL },
{ "/Attributes/Not editable", NULL, do_apply_editable, FALSE, NULL },
{ "/_Test", NULL, 0, 0, "<Branch>" },
{ "/Test/_Example", NULL, do_example, 0, NULL },
};
@@ -1061,6 +1119,12 @@ create_buffer (void)
buffer->filename = NULL;
buffer->untitled_serial = -1;
buffer->not_editable_tag = gtk_text_buffer_create_tag (buffer->buffer,
"ineditable");
gtk_object_set (GTK_OBJECT (buffer->not_editable_tag),
"editable", FALSE,
"foreground", "purple", NULL);
buffers = g_slist_prepend (buffers, buffer);
return buffer;

View File

@@ -20,6 +20,7 @@ struct _Buffer
GtkTextBuffer *buffer;
char *filename;
gint untitled_serial;
GtkTextTag *not_editable_tag;
};
struct _View
@@ -839,6 +840,53 @@ do_direction_changed (gpointer callback_data,
gtk_widget_queue_resize (view->text_view);
}
static void
do_editable_changed (gpointer callback_data,
guint callback_action,
GtkWidget *widget)
{
View *view = view_from_widget (widget);
gtk_text_view_set_editable (GTK_TEXT_VIEW (view->text_view), callback_action);
}
static void
do_cursor_visible_changed (gpointer callback_data,
guint callback_action,
GtkWidget *widget)
{
View *view = view_from_widget (widget);
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), callback_action);
}
static void
do_apply_editable (gpointer callback_data,
guint callback_action,
GtkWidget *widget)
{
View *view = view_from_widget (widget);
GtkTextIter start;
GtkTextIter end;
if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
&start, &end))
{
if (callback_action)
{
gtk_text_buffer_remove_tag (view->buffer->buffer,
"ineditable",
&start, &end);
}
else
{
gtk_text_buffer_apply_tag (view->buffer->buffer,
"ineditable",
&start, &end);
}
}
}
static void
view_init_menus (View *view)
{
@@ -893,9 +941,19 @@ static GtkItemFactoryEntry menu_items[] =
{ "/Settings/Wrap _Off", NULL, do_wrap_changed, GTK_WRAPMODE_NONE, "<RadioItem>" },
{ "/Settings/Wrap _Words", NULL, do_wrap_changed, GTK_WRAPMODE_WORD, "/Settings/Wrap Off" },
{ "/Settings/sep1", NULL, 0, 0, "<Separator>" },
{ "/Settings/Editable", NULL, do_editable_changed, TRUE, "<RadioItem>" },
{ "/Settings/Not editable", NULL, do_editable_changed, FALSE, "/Settings/Editable" },
{ "/Settings/sep1", NULL, 0, 0, "<Separator>" },
{ "/Settings/Cursor visible", NULL, do_cursor_visible_changed, TRUE, "<RadioItem>" },
{ "/Settings/Cursor not visible", NULL, do_cursor_visible_changed, FALSE, "/Settings/Cursor visible" },
{ "/Settings/sep1", NULL, 0, 0, "<Separator>" },
{ "/Settings/Left-to-Right", NULL, do_direction_changed, GTK_TEXT_DIR_LTR, "<RadioItem>" },
{ "/Settings/Right-to-Left", NULL, do_direction_changed, GTK_TEXT_DIR_RTL, "/Settings/Left-to-Right" },
{ "/_Attributes", NULL, 0, 0, "<Branch>" },
{ "/Attributes/Editable", NULL, do_apply_editable, TRUE, NULL },
{ "/Attributes/Not editable", NULL, do_apply_editable, FALSE, NULL },
{ "/_Test", NULL, 0, 0, "<Branch>" },
{ "/Test/_Example", NULL, do_example, 0, NULL },
};
@@ -1061,6 +1119,12 @@ create_buffer (void)
buffer->filename = NULL;
buffer->untitled_serial = -1;
buffer->not_editable_tag = gtk_text_buffer_create_tag (buffer->buffer,
"ineditable");
gtk_object_set (GTK_OBJECT (buffer->not_editable_tag),
"editable", FALSE,
"foreground", "purple", NULL);
buffers = g_slist_prepend (buffers, buffer);
return buffer;