mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-11 13:10:07 +00:00
Patch from Dov Grobgeld to implement auto-bidi-direction for GtkTextView
Mon Mar 1 10:41:27 2004 Owen Taylor <otaylor@redhat.com> Patch from Dov Grobgeld to implement auto-bidi-direction for GtkTextView (#118543) * gtk/gtktextbtree.[ch]: Resolve bidi base direction for each line by propagating backwards/forwards as necessary. * gtk/gtktextlayout.[ch] gtk/gtktextview.c: Set the bidi base direction for the ;ine with the cursor from the keyboard direction. Add gtk_text_layout_set_keyboard_direction(). Mon Mar 1 10:31:11 2004 Owen Taylor <otaylor@redhat.com> * gtk/gtkentry.[ch]: Implement auto-bidi-direction, based on a patch from Dov Grobgeld. (#118540)
This commit is contained in:
parent
f0d22047c3
commit
8130a8a227
15
ChangeLog
15
ChangeLog
@ -1,6 +1,19 @@
|
||||
Mon Mar 1 10:41:27 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
Patch from Dov Grobgeld to implement auto-bidi-direction
|
||||
for GtkTextView (#118543)
|
||||
|
||||
* gtk/gtktextbtree.[ch]: Resolve bidi base direction
|
||||
for each line by propagating backwards/forwards as
|
||||
necessary.
|
||||
|
||||
* gtk/gtktextlayout.[ch] gtk/gtktextview.c: Set the
|
||||
bidi base direction for the ;ine with the cursor from
|
||||
the keyboard direction. Add gtk_text_layout_set_keyboard_direction().
|
||||
|
||||
Mon Mar 1 10:31:11 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkentry.c: Implement auto-bidi-direction,
|
||||
* gtk/gtkentry.[ch]: Implement auto-bidi-direction,
|
||||
based on a patch from Dov Grobgeld. (#118540)
|
||||
|
||||
Sun Feb 29 22:01:49 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
@ -1,6 +1,19 @@
|
||||
Mon Mar 1 10:41:27 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
Patch from Dov Grobgeld to implement auto-bidi-direction
|
||||
for GtkTextView (#118543)
|
||||
|
||||
* gtk/gtktextbtree.[ch]: Resolve bidi base direction
|
||||
for each line by propagating backwards/forwards as
|
||||
necessary.
|
||||
|
||||
* gtk/gtktextlayout.[ch] gtk/gtktextview.c: Set the
|
||||
bidi base direction for the ;ine with the cursor from
|
||||
the keyboard direction. Add gtk_text_layout_set_keyboard_direction().
|
||||
|
||||
Mon Mar 1 10:31:11 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkentry.c: Implement auto-bidi-direction,
|
||||
* gtk/gtkentry.[ch]: Implement auto-bidi-direction,
|
||||
based on a patch from Dov Grobgeld. (#118540)
|
||||
|
||||
Sun Feb 29 22:01:49 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
@ -1,6 +1,19 @@
|
||||
Mon Mar 1 10:41:27 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
Patch from Dov Grobgeld to implement auto-bidi-direction
|
||||
for GtkTextView (#118543)
|
||||
|
||||
* gtk/gtktextbtree.[ch]: Resolve bidi base direction
|
||||
for each line by propagating backwards/forwards as
|
||||
necessary.
|
||||
|
||||
* gtk/gtktextlayout.[ch] gtk/gtktextview.c: Set the
|
||||
bidi base direction for the ;ine with the cursor from
|
||||
the keyboard direction. Add gtk_text_layout_set_keyboard_direction().
|
||||
|
||||
Mon Mar 1 10:31:11 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkentry.c: Implement auto-bidi-direction,
|
||||
* gtk/gtkentry.[ch]: Implement auto-bidi-direction,
|
||||
based on a patch from Dov Grobgeld. (#118540)
|
||||
|
||||
Sun Feb 29 22:01:49 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
@ -1,6 +1,19 @@
|
||||
Mon Mar 1 10:41:27 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
Patch from Dov Grobgeld to implement auto-bidi-direction
|
||||
for GtkTextView (#118543)
|
||||
|
||||
* gtk/gtktextbtree.[ch]: Resolve bidi base direction
|
||||
for each line by propagating backwards/forwards as
|
||||
necessary.
|
||||
|
||||
* gtk/gtktextlayout.[ch] gtk/gtktextview.c: Set the
|
||||
bidi base direction for the ;ine with the cursor from
|
||||
the keyboard direction. Add gtk_text_layout_set_keyboard_direction().
|
||||
|
||||
Mon Mar 1 10:31:11 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkentry.c: Implement auto-bidi-direction,
|
||||
* gtk/gtkentry.[ch]: Implement auto-bidi-direction,
|
||||
based on a patch from Dov Grobgeld. (#118540)
|
||||
|
||||
Sun Feb 29 22:01:49 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
@ -1,6 +1,19 @@
|
||||
Mon Mar 1 10:41:27 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
Patch from Dov Grobgeld to implement auto-bidi-direction
|
||||
for GtkTextView (#118543)
|
||||
|
||||
* gtk/gtktextbtree.[ch]: Resolve bidi base direction
|
||||
for each line by propagating backwards/forwards as
|
||||
necessary.
|
||||
|
||||
* gtk/gtktextlayout.[ch] gtk/gtktextview.c: Set the
|
||||
bidi base direction for the ;ine with the cursor from
|
||||
the keyboard direction. Add gtk_text_layout_set_keyboard_direction().
|
||||
|
||||
Mon Mar 1 10:31:11 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkentry.c: Implement auto-bidi-direction,
|
||||
* gtk/gtkentry.[ch]: Implement auto-bidi-direction,
|
||||
based on a patch from Dov Grobgeld. (#118540)
|
||||
|
||||
Sun Feb 29 22:01:49 2004 Owen Taylor <otaylor@redhat.com>
|
||||
|
@ -93,6 +93,7 @@ struct _GtkEntry
|
||||
|
||||
guint select_words : 1;
|
||||
guint select_lines : 1;
|
||||
guint resolved_dir : 4; /* PangoDirection */
|
||||
guint button;
|
||||
guint blink_timeout;
|
||||
guint recompute_idle;
|
||||
|
@ -554,6 +554,174 @@ _gtk_text_btree_segments_changed (GtkTextBTree *tree)
|
||||
* Indexable segment mutation
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following function is responsible for resolving the bidi direction
|
||||
* for the lines between start and end. But it also calculates any
|
||||
* dependent bidi direction for surrounding lines that change as a result
|
||||
* of the bidi direction decisions within the range. The function is
|
||||
* trying to do as little propagation as is needed.
|
||||
*/
|
||||
static void
|
||||
gtk_text_btree_resolve_bidi (GtkTextIter *start,
|
||||
GtkTextIter *end)
|
||||
{
|
||||
GtkTextBTree *tree = _gtk_text_iter_get_btree (start);
|
||||
GtkTextLine *start_line, *end_line, *start_line_prev, *end_line_next, *line;
|
||||
PangoDirection last_strong, dir_above_propagated, dir_below_propagated;
|
||||
|
||||
/* Resolve the strong bidi direction for all lines between
|
||||
* start and end.
|
||||
*/
|
||||
start_line = _gtk_text_iter_get_text_line (start);
|
||||
start_line_prev = _gtk_text_line_previous (start_line);
|
||||
end_line = _gtk_text_iter_get_text_line (end);
|
||||
end_line_next = _gtk_text_line_next (end_line);
|
||||
|
||||
line = start_line;
|
||||
while (line && line != end_line_next)
|
||||
{
|
||||
/* Loop through the segments and search for a strong character
|
||||
*/
|
||||
GtkTextLineSegment *seg = line->segments;
|
||||
line->dir_strong = PANGO_DIRECTION_NEUTRAL;
|
||||
|
||||
while (seg)
|
||||
{
|
||||
if (seg->byte_count > 0)
|
||||
{
|
||||
PangoDirection pango_dir;
|
||||
|
||||
pango_dir = pango_find_base_dir (seg->body.chars,
|
||||
seg->byte_count);
|
||||
|
||||
if (pango_dir != PANGO_DIRECTION_NEUTRAL)
|
||||
{
|
||||
line->dir_strong = pango_dir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
seg = seg->next;
|
||||
}
|
||||
|
||||
line = _gtk_text_line_next (line);
|
||||
}
|
||||
|
||||
/* Sweep forward */
|
||||
|
||||
/* The variable dir_above_propagated contains the forward propagated
|
||||
* direction before start. It is neutral if start is in the beginning
|
||||
* of the buffer.
|
||||
*/
|
||||
dir_above_propagated = PANGO_DIRECTION_NEUTRAL;
|
||||
if (start_line_prev)
|
||||
dir_above_propagated = start_line_prev->dir_propagated_forward;
|
||||
|
||||
/* Loop forward and propagate the direction of each paragraph
|
||||
* to all neutral lines.
|
||||
*/
|
||||
line = start_line;
|
||||
last_strong = dir_above_propagated;
|
||||
while (line != end_line_next)
|
||||
{
|
||||
if (line->dir_strong != PANGO_DIRECTION_NEUTRAL)
|
||||
last_strong = line->dir_strong;
|
||||
|
||||
line->dir_propagated_forward = last_strong;
|
||||
|
||||
line = _gtk_text_line_next (line);
|
||||
}
|
||||
|
||||
/* Continue propagating as long as the previous resolved forward
|
||||
* is different from last_strong.
|
||||
*/
|
||||
{
|
||||
GtkTextIter end_propagate;
|
||||
|
||||
while (line &&
|
||||
line->dir_strong == PANGO_DIRECTION_NEUTRAL &&
|
||||
line->dir_propagated_forward != last_strong)
|
||||
{
|
||||
GtkTextLine *prev = line;
|
||||
line->dir_propagated_forward = last_strong;
|
||||
|
||||
line = _gtk_text_line_next(line);
|
||||
if (!line)
|
||||
{
|
||||
line = prev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The last line to invalidate is the last line before the
|
||||
* line with the strong character. Or in case of the end of the
|
||||
* buffer, the last line of the buffer. (There seems to be an
|
||||
* extra "virtual" last line in the buffer that must not be used
|
||||
* calling _gtk_text_btree_get_iter_at_line (causes crash). Thus the
|
||||
* _gtk_text_line_previous is ok in that case as well.)
|
||||
*/
|
||||
line = _gtk_text_line_previous (line);
|
||||
_gtk_text_btree_get_iter_at_line (tree, &end_propagate, line, 0);
|
||||
_gtk_text_btree_invalidate_region (tree, end, &end_propagate);
|
||||
}
|
||||
|
||||
/* Sweep backward */
|
||||
|
||||
/* The variable dir_below_propagated contains the backward propagated
|
||||
* direction after end. It is neutral if end is at the end of
|
||||
* the buffer.
|
||||
*/
|
||||
dir_below_propagated = PANGO_DIRECTION_NEUTRAL;
|
||||
if (end_line_next)
|
||||
dir_below_propagated = end_line_next->dir_propagated_back;
|
||||
|
||||
/* Loop backward and propagate the direction of each paragraph
|
||||
* to all neutral lines.
|
||||
*/
|
||||
line = end_line;
|
||||
last_strong = dir_below_propagated;
|
||||
while (line != start_line_prev)
|
||||
{
|
||||
if (line->dir_strong != PANGO_DIRECTION_NEUTRAL)
|
||||
last_strong = line->dir_strong;
|
||||
|
||||
line->dir_propagated_back = last_strong;
|
||||
|
||||
line = _gtk_text_line_previous (line);
|
||||
}
|
||||
|
||||
/* Continue propagating as long as the resolved backward dir
|
||||
* is different from last_strong.
|
||||
*/
|
||||
{
|
||||
GtkTextIter start_propagate;
|
||||
|
||||
while (line &&
|
||||
line->dir_strong == PANGO_DIRECTION_NEUTRAL &&
|
||||
line->dir_propagated_back != last_strong)
|
||||
{
|
||||
GtkTextLine *prev = line;
|
||||
line->dir_propagated_back = last_strong;
|
||||
|
||||
line = _gtk_text_line_previous (line);
|
||||
if (!line)
|
||||
{
|
||||
line = prev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We only need to invalidate for backwards propagation if the
|
||||
* line we ended up on didn't get a direction from forwards
|
||||
* propagation.
|
||||
*/
|
||||
if (line && line->dir_propagated_forward == PANGO_DIRECTION_NEUTRAL)
|
||||
{
|
||||
_gtk_text_btree_get_iter_at_line (tree, &start_propagate, line, 0);
|
||||
_gtk_text_btree_invalidate_region(tree, &start_propagate, start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_text_btree_delete (GtkTextIter *start,
|
||||
GtkTextIter *end)
|
||||
@ -884,6 +1052,8 @@ _gtk_text_btree_delete (GtkTextIter *start,
|
||||
/* Re-initialize our iterators */
|
||||
_gtk_text_btree_get_iter_at_line (tree, start, start_line, start_byte_offset);
|
||||
*end = *start;
|
||||
|
||||
_gtk_text_btree_resolve_bidi (start, end);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1050,6 +1220,8 @@ _gtk_text_btree_insert (GtkTextIter *iter,
|
||||
|
||||
/* Convenience for the user */
|
||||
*iter = end;
|
||||
|
||||
_gtk_text_btree_resolve_bidi (&start, &end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4498,6 +4670,9 @@ gtk_text_line_new (void)
|
||||
GtkTextLine *line;
|
||||
|
||||
line = g_new0(GtkTextLine, 1);
|
||||
line->dir_strong = PANGO_DIRECTION_NEUTRAL;
|
||||
line->dir_propagated_forward = PANGO_DIRECTION_NEUTRAL;
|
||||
line->dir_propagated_back = PANGO_DIRECTION_NEUTRAL;
|
||||
|
||||
return line;
|
||||
}
|
||||
|
@ -216,6 +216,9 @@ struct _GtkTextLine {
|
||||
GtkTextLineSegment *segments; /* First in ordered list of segments
|
||||
* that make up the line. */
|
||||
GtkTextLineData *views; /* data stored here by views */
|
||||
guchar dir_strong; /* BiDi algo dir of line */
|
||||
guchar dir_propagated_back; /* BiDi algo dir of next line */
|
||||
guchar dir_propagated_forward; /* BiDi algo dir of prev line */
|
||||
};
|
||||
|
||||
|
||||
|
@ -85,6 +85,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GTK_TEXT_LAYOUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TEXT_LAYOUT, GtkTextLayoutPrivate))
|
||||
|
||||
typedef struct _GtkTextLayoutPrivate GtkTextLayoutPrivate;
|
||||
|
||||
struct _GtkTextLayoutPrivate
|
||||
{
|
||||
/* Cache the line that the cursor is positioned on, as the keyboard
|
||||
direction only influences the direction of the cursor line.
|
||||
*/
|
||||
GtkTextLine *cursor_line;
|
||||
};
|
||||
|
||||
static GtkTextLineData *gtk_text_layout_real_wrap (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
/* may be NULL */
|
||||
@ -110,6 +122,22 @@ static void gtk_text_layout_invalidate_all (GtkTextLayout *layout);
|
||||
|
||||
static PangoAttribute *gtk_text_attr_appearance_new (const GtkTextAppearance *appearance);
|
||||
|
||||
static void gtk_text_layout_mark_set_handler (GtkTextBuffer *buffer,
|
||||
const GtkTextIter *location,
|
||||
GtkTextMark *mark,
|
||||
gpointer data);
|
||||
static void gtk_text_layout_buffer_insert_text (GtkTextBuffer *textbuffer,
|
||||
GtkTextIter *iter,
|
||||
gchar *str,
|
||||
gint len,
|
||||
gpointer data);
|
||||
static void gtk_text_layout_buffer_delete_range (GtkTextBuffer *textbuffer,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end,
|
||||
gpointer data);
|
||||
|
||||
static void gtk_text_layout_update_cursor_line (GtkTextLayout *layout);
|
||||
|
||||
enum {
|
||||
INVALIDATED,
|
||||
CHANGED,
|
||||
@ -209,6 +237,8 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
|
||||
GTK_TYPE_OBJECT,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_INT);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GtkTextLayoutPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -284,6 +314,16 @@ gtk_text_layout_set_buffer (GtkTextLayout *layout,
|
||||
_gtk_text_btree_remove_view (_gtk_text_buffer_get_btree (layout->buffer),
|
||||
layout);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (layout->buffer,
|
||||
G_CALLBACK (gtk_text_layout_mark_set_handler),
|
||||
layout);
|
||||
g_signal_handlers_disconnect_by_func (layout->buffer,
|
||||
G_CALLBACK (gtk_text_layout_buffer_insert_text),
|
||||
layout);
|
||||
g_signal_handlers_disconnect_by_func (layout->buffer,
|
||||
G_CALLBACK (gtk_text_layout_buffer_delete_range),
|
||||
layout);
|
||||
|
||||
g_object_unref (layout->buffer);
|
||||
layout->buffer = NULL;
|
||||
}
|
||||
@ -295,6 +335,14 @@ gtk_text_layout_set_buffer (GtkTextLayout *layout,
|
||||
g_object_ref (buffer);
|
||||
|
||||
_gtk_text_btree_add_view (_gtk_text_buffer_get_btree (buffer), layout);
|
||||
|
||||
/* Bind to all signals that move the insert mark. */
|
||||
g_signal_connect_after (layout->buffer, "mark_set",
|
||||
G_CALLBACK (gtk_text_layout_mark_set_handler), layout);
|
||||
g_signal_connect_after (layout->buffer, "insert_text",
|
||||
G_CALLBACK (gtk_text_layout_buffer_insert_text), layout);
|
||||
g_signal_connect_after (layout->buffer, "delete_range",
|
||||
G_CALLBACK (gtk_text_layout_buffer_delete_range), layout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,6 +422,25 @@ gtk_text_layout_set_cursor_direction (GtkTextLayout *layout,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_text_layout_set_keyboard_direction:
|
||||
* @keyboard_dir: the current direction of the keyboard.
|
||||
*
|
||||
* Sets the keyboard direction; this is used as for the bidirectional
|
||||
* base direction for the line with the cursor if the line contains
|
||||
* only neutral characters.
|
||||
**/
|
||||
void
|
||||
gtk_text_layout_set_keyboard_direction (GtkTextLayout *layout,
|
||||
GtkTextDirection keyboard_dir)
|
||||
{
|
||||
if (keyboard_dir != layout->keyboard_direction)
|
||||
{
|
||||
layout->keyboard_direction = keyboard_dir;
|
||||
gtk_text_layout_invalidate_cursor_line (layout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_text_layout_get_buffer:
|
||||
* @layout: a #GtkTextLayout
|
||||
@ -704,23 +771,33 @@ gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
|
||||
static void
|
||||
gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextLine *line;
|
||||
GtkTextLayoutPrivate *priv = GTK_TEXT_LAYOUT_GET_PRIVATE (layout);
|
||||
GtkTextLineData *line_data;
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter,
|
||||
gtk_text_buffer_get_mark (layout->buffer, "insert"));
|
||||
if (priv->cursor_line == NULL)
|
||||
return;
|
||||
|
||||
line = _gtk_text_iter_get_text_line (&iter);
|
||||
line_data = _gtk_text_line_get_data (line, layout);
|
||||
line_data = _gtk_text_line_get_data (priv->cursor_line, layout);
|
||||
if (line_data)
|
||||
{
|
||||
gtk_text_layout_invalidate_cache (layout, line);
|
||||
_gtk_text_line_invalidate_wrap (line, line_data);
|
||||
gtk_text_layout_invalidate_cache (layout, priv->cursor_line);
|
||||
_gtk_text_line_invalidate_wrap (priv->cursor_line, line_data);
|
||||
gtk_text_layout_invalidated (layout);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_layout_update_cursor_line(GtkTextLayout *layout)
|
||||
{
|
||||
GtkTextLayoutPrivate *priv = GTK_TEXT_LAYOUT_GET_PRIVATE (layout);
|
||||
GtkTextIter iter;
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter,
|
||||
gtk_text_buffer_get_mark (layout->buffer, "insert"));
|
||||
|
||||
priv->cursor_line = _gtk_text_iter_get_text_line (&iter);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_layout_real_invalidate (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
@ -1121,26 +1198,46 @@ totally_invisible_line (GtkTextLayout *layout,
|
||||
|
||||
static void
|
||||
set_para_values (GtkTextLayout *layout,
|
||||
GtkTextAttributes *style,
|
||||
PangoDirection base_dir,
|
||||
GtkTextAttributes *style,
|
||||
GtkTextLineDisplay *display)
|
||||
{
|
||||
PangoAlignment pango_align = PANGO_ALIGN_LEFT;
|
||||
int layout_width;
|
||||
|
||||
display->direction = style->direction;
|
||||
switch (base_dir)
|
||||
{
|
||||
/* If no base direction was found, then use the style direction */
|
||||
case PANGO_DIRECTION_NEUTRAL :
|
||||
display->direction = style->direction;
|
||||
|
||||
if (display->direction == GTK_TEXT_DIR_LTR)
|
||||
display->layout = pango_layout_new (layout->ltr_context);
|
||||
else
|
||||
/* Override the base direction */
|
||||
if (display->direction == GTK_TEXT_DIR_RTL)
|
||||
base_dir = PANGO_DIRECTION_RTL;
|
||||
else
|
||||
base_dir = PANGO_DIRECTION_LTR;
|
||||
|
||||
break;
|
||||
case PANGO_DIRECTION_RTL :
|
||||
display->direction = GTK_TEXT_DIR_RTL;
|
||||
break;
|
||||
default:
|
||||
display->direction = GTK_TEXT_DIR_LTR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (display->direction == GTK_TEXT_DIR_RTL)
|
||||
display->layout = pango_layout_new (layout->rtl_context);
|
||||
else
|
||||
display->layout = pango_layout_new (layout->ltr_context);
|
||||
|
||||
switch (style->justification)
|
||||
{
|
||||
case GTK_JUSTIFY_LEFT:
|
||||
pango_align = (style->direction == GTK_TEXT_DIR_LTR) ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
|
||||
pango_align = (base_dir == PANGO_DIRECTION_LTR) ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
|
||||
break;
|
||||
case GTK_JUSTIFY_RIGHT:
|
||||
pango_align = (style->direction == GTK_TEXT_DIR_LTR) ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
|
||||
pango_align = (base_dir == PANGO_DIRECTION_LTR) ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
|
||||
break;
|
||||
case GTK_JUSTIFY_CENTER:
|
||||
pango_align = PANGO_ALIGN_CENTER;
|
||||
@ -1683,6 +1780,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
gboolean size_only)
|
||||
{
|
||||
GtkTextLayoutPrivate *priv = GTK_TEXT_LAYOUT_GET_PRIVATE (layout);
|
||||
GtkTextLineDisplay *display;
|
||||
GtkTextLineSegment *seg;
|
||||
GtkTextIter iter;
|
||||
@ -1696,6 +1794,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
GSList *cursor_segs = NULL;
|
||||
GSList *tmp_list1, *tmp_list2;
|
||||
gboolean saw_widget = FALSE;
|
||||
PangoDirection base_dir;
|
||||
|
||||
g_return_val_if_fail (line != NULL, NULL);
|
||||
|
||||
@ -1728,6 +1827,18 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
if (totally_invisible_line (layout, line, &iter))
|
||||
return display;
|
||||
|
||||
/* Find the bidi base direction */
|
||||
base_dir = line->dir_propagated_forward;
|
||||
if (base_dir == PANGO_DIRECTION_NEUTRAL)
|
||||
base_dir = line->dir_propagated_back;
|
||||
|
||||
if (line == priv->cursor_line &&
|
||||
line->dir_strong == PANGO_DIRECTION_NEUTRAL)
|
||||
{
|
||||
base_dir = (layout->keyboard_direction == GTK_TEXT_DIR_LTR) ?
|
||||
PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
/* Allocate space for flat text for buffer
|
||||
*/
|
||||
text_allocated = _gtk_text_line_byte_count (line);
|
||||
@ -1758,7 +1869,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
*/
|
||||
if (!para_values_set)
|
||||
{
|
||||
set_para_values (layout, style, display);
|
||||
set_para_values (layout, base_dir, style, display);
|
||||
para_values_set = TRUE;
|
||||
}
|
||||
|
||||
@ -1927,7 +2038,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
if (!para_values_set)
|
||||
{
|
||||
style = get_style (layout, &iter);
|
||||
set_para_values (layout, style, display);
|
||||
set_para_values (layout, base_dir, style, display);
|
||||
release_style (layout, style);
|
||||
}
|
||||
|
||||
@ -3070,3 +3181,40 @@ gtk_text_layout_spew (GtkTextLayout *layout)
|
||||
layout->height, layout->screen_width);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Catch all situations that move the insertion point.
|
||||
*/
|
||||
static void
|
||||
gtk_text_layout_mark_set_handler (GtkTextBuffer *buffer,
|
||||
const GtkTextIter *location,
|
||||
GtkTextMark *mark,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTextLayout *layout = GTK_TEXT_LAYOUT (data);
|
||||
|
||||
if (mark == gtk_text_buffer_get_insert (buffer))
|
||||
gtk_text_layout_update_cursor_line (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_layout_buffer_insert_text (GtkTextBuffer *textbuffer,
|
||||
GtkTextIter *iter,
|
||||
gchar *str,
|
||||
gint len,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTextLayout *layout = GTK_TEXT_LAYOUT (data);
|
||||
|
||||
gtk_text_layout_update_cursor_line (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_layout_buffer_delete_range (GtkTextBuffer *textbuffer,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTextLayout *layout = GTK_TEXT_LAYOUT (data);
|
||||
|
||||
gtk_text_layout_update_cursor_line (layout);
|
||||
}
|
||||
|
@ -165,6 +165,11 @@ struct _GtkTextLayout
|
||||
*/
|
||||
guint cursor_direction : 2;
|
||||
|
||||
/* The keyboard direction is used to default the alignment when
|
||||
there are no strong characters.
|
||||
*/
|
||||
guint keyboard_direction : 2;
|
||||
|
||||
/* The preedit string and attributes, if any */
|
||||
|
||||
gchar *preedit_string;
|
||||
@ -265,7 +270,9 @@ void gtk_text_layout_set_contexts (GtkTextLayout *lay
|
||||
PangoContext *ltr_context,
|
||||
PangoContext *rtl_context);
|
||||
void gtk_text_layout_set_cursor_direction (GtkTextLayout *layout,
|
||||
GtkTextDirection direction);
|
||||
GtkTextDirection direction);
|
||||
void gtk_text_layout_set_keyboard_direction (GtkTextLayout *layout,
|
||||
GtkTextDirection keyboard_dir);
|
||||
void gtk_text_layout_default_style_changed (GtkTextLayout *layout);
|
||||
|
||||
void gtk_text_layout_set_screen_width (GtkTextLayout *layout,
|
||||
|
@ -5620,26 +5620,28 @@ gtk_text_view_check_keymap_direction (GtkTextView *text_view)
|
||||
{
|
||||
if (text_view->layout)
|
||||
{
|
||||
gboolean split_cursor;
|
||||
GtkTextDirection new_dir;
|
||||
GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (text_view));
|
||||
|
||||
GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
|
||||
GtkTextDirection new_cursor_dir;
|
||||
GtkTextDirection new_keyboard_dir;
|
||||
gboolean split_cursor;
|
||||
|
||||
g_object_get (settings,
|
||||
"gtk-split-cursor", &split_cursor,
|
||||
NULL);
|
||||
if (split_cursor)
|
||||
{
|
||||
new_dir = GTK_TEXT_DIR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
|
||||
new_dir = (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
|
||||
GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
|
||||
}
|
||||
|
||||
if (text_view->layout->cursor_direction != new_dir)
|
||||
gtk_text_layout_set_cursor_direction (text_view->layout, new_dir);
|
||||
if (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR)
|
||||
new_keyboard_dir = GTK_TEXT_DIR_LTR;
|
||||
else
|
||||
new_keyboard_dir = GTK_TEXT_DIR_RTL;
|
||||
|
||||
if (split_cursor)
|
||||
new_cursor_dir = GTK_TEXT_DIR_NONE;
|
||||
else
|
||||
new_cursor_dir = new_keyboard_dir;
|
||||
|
||||
gtk_text_layout_set_cursor_direction (text_view->layout, new_cursor_dir);
|
||||
gtk_text_layout_set_keyboard_direction (text_view->layout, new_keyboard_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user