Added MooText interface for handling selection with mouse
This commit is contained in:
parent
fc202e9f98
commit
6aa44ba038
@ -313,12 +313,13 @@ int _moo_edit_button_press_event (GtkWidget *widget,
|
|||||||
if (event->type == GDK_BUTTON_PRESS)
|
if (event->type == GDK_BUTTON_PRESS)
|
||||||
{
|
{
|
||||||
if (event->button == 1) {
|
if (event->button == 1) {
|
||||||
|
GtkTextIter sel_start, sel_end;
|
||||||
|
|
||||||
edit->priv->drag_button = GDK_BUTTON_PRESS;
|
edit->priv->drag_button = GDK_BUTTON_PRESS;
|
||||||
edit->priv->drag_start_x = x;
|
edit->priv->drag_start_x = x;
|
||||||
edit->priv->drag_start_y = y;
|
edit->priv->drag_start_y = y;
|
||||||
|
|
||||||
/* if clicked in selected, start drag */
|
/* if clicked in selected, start drag */
|
||||||
GtkTextIter sel_start, sel_end;
|
|
||||||
if (gtk_text_buffer_get_selection_bounds (buffer, &sel_start, &sel_end))
|
if (gtk_text_buffer_get_selection_bounds (buffer, &sel_start, &sel_end))
|
||||||
{
|
{
|
||||||
gtk_text_iter_order (&sel_start, &sel_end);
|
gtk_text_iter_order (&sel_start, &sel_end);
|
||||||
@ -349,25 +350,30 @@ int _moo_edit_button_press_event (GtkWidget *widget,
|
|||||||
}
|
}
|
||||||
else if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
|
else if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
|
||||||
{
|
{
|
||||||
if (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL)) {
|
GtkTextIter bound;
|
||||||
|
|
||||||
|
if (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL))
|
||||||
|
{
|
||||||
/* it may happen sometimes, if you click fast enough */
|
/* it may happen sometimes, if you click fast enough */
|
||||||
gtk_text_buffer_place_cursor (buffer, &iter);
|
gtk_text_buffer_place_cursor (buffer, &iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
edit->priv->drag_button = GDK_2BUTTON_PRESS;
|
edit->priv->drag_button = GDK_2BUTTON_PRESS;
|
||||||
edit->priv->drag_start_x = x;
|
edit->priv->drag_start_x = x;
|
||||||
edit->priv->drag_start_y = y;
|
edit->priv->drag_start_y = y;
|
||||||
edit->priv->drag_type = MOO_EDIT_DRAG_SELECT;
|
edit->priv->drag_type = MOO_EDIT_DRAG_SELECT;
|
||||||
GtkTextIter bound = iter;
|
|
||||||
|
bound = iter;
|
||||||
if (extend_selection (edit, MOO_EDIT_SELECT_WORDS, &iter, &bound))
|
if (extend_selection (edit, MOO_EDIT_SELECT_WORDS, &iter, &bound))
|
||||||
gtk_text_buffer_select_range (buffer, &iter, &bound);
|
gtk_text_buffer_select_range (buffer, &iter, &bound);
|
||||||
}
|
}
|
||||||
else if (event->type == GDK_3BUTTON_PRESS && event->button == 1)
|
else if (event->type == GDK_3BUTTON_PRESS && event->button == 1)
|
||||||
{
|
{
|
||||||
|
GtkTextIter bound = iter;
|
||||||
edit->priv->drag_button = GDK_3BUTTON_PRESS;
|
edit->priv->drag_button = GDK_3BUTTON_PRESS;
|
||||||
edit->priv->drag_start_x = x;
|
edit->priv->drag_start_x = x;
|
||||||
edit->priv->drag_start_y = y;
|
edit->priv->drag_start_y = y;
|
||||||
edit->priv->drag_type = MOO_EDIT_DRAG_SELECT;
|
edit->priv->drag_type = MOO_EDIT_DRAG_SELECT;
|
||||||
GtkTextIter bound = iter;
|
|
||||||
if (extend_selection (edit, MOO_EDIT_SELECT_LINES, &iter, &bound))
|
if (extend_selection (edit, MOO_EDIT_SELECT_LINES, &iter, &bound))
|
||||||
gtk_text_buffer_select_range (buffer, &iter, &bound);
|
gtk_text_buffer_select_range (buffer, &iter, &bound);
|
||||||
}
|
}
|
||||||
@ -380,6 +386,7 @@ int _moo_edit_button_release_event (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
|
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
|
||||||
MooEdit *edit = MOO_EDIT (widget);
|
MooEdit *edit = MOO_EDIT (widget);
|
||||||
|
GtkTextIter iter;
|
||||||
|
|
||||||
switch (edit->priv->drag_type) {
|
switch (edit->priv->drag_type) {
|
||||||
case MOO_EDIT_DRAG_NONE:
|
case MOO_EDIT_DRAG_NONE:
|
||||||
@ -398,7 +405,6 @@ int _moo_edit_button_release_event (GtkWidget *widget,
|
|||||||
/* if we were really dragging, drop it
|
/* if we were really dragging, drop it
|
||||||
* otherwise, it was just a single click in selected text */
|
* otherwise, it was just a single click in selected text */
|
||||||
g_assert (!edit->priv->drag_moved); /* parent should handle drag */
|
g_assert (!edit->priv->drag_moved); /* parent should handle drag */
|
||||||
GtkTextIter iter;
|
|
||||||
gtk_text_view_get_iter_at_location (text_view, &iter,
|
gtk_text_view_get_iter_at_location (text_view, &iter,
|
||||||
edit->priv->drag_start_x,
|
edit->priv->drag_start_x,
|
||||||
edit->priv->drag_start_y);
|
edit->priv->drag_start_y);
|
||||||
|
@ -158,6 +158,7 @@ void moo_term_invalidate_rect (MooTerm *term,
|
|||||||
|
|
||||||
gdk_window_invalidate_rect (GTK_WIDGET(term)->window,
|
gdk_window_invalidate_rect (GTK_WIDGET(term)->window,
|
||||||
&r, FALSE);
|
&r, FALSE);
|
||||||
|
moo_term_invalidate_content_rect (term, rect);
|
||||||
add_update_timeout (term);
|
add_update_timeout (term);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +526,6 @@ static void term_draw_range (MooTerm *term,
|
|||||||
guint start,
|
guint start,
|
||||||
guint len)
|
guint len)
|
||||||
{
|
{
|
||||||
TermSelection *sel = term->priv->selection;
|
|
||||||
int selected;
|
int selected;
|
||||||
guint first = start;
|
guint first = start;
|
||||||
guint last = start + len;
|
guint last = start + len;
|
||||||
@ -555,7 +555,7 @@ static void term_draw_range (MooTerm *term,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selected = term_selection_row_selected (sel, abs_row);
|
selected = moo_term_selection_row_selected (term, abs_row);
|
||||||
|
|
||||||
switch (selected)
|
switch (selected)
|
||||||
{
|
{
|
||||||
@ -566,10 +566,10 @@ static void term_draw_range (MooTerm *term,
|
|||||||
|
|
||||||
case PART_SELECTED:
|
case PART_SELECTED:
|
||||||
{
|
{
|
||||||
guint l_row = sel->l_row;
|
guint l_row, l_col, r_row, r_col;
|
||||||
guint l_col = sel->l_col;
|
|
||||||
guint r_row = sel->r_row;
|
moo_term_get_selection_bounds (term, &l_row, &l_col,
|
||||||
guint r_col = sel->r_col;
|
&r_row, &r_col);
|
||||||
|
|
||||||
if (l_row == r_row)
|
if (l_row == r_row)
|
||||||
{
|
{
|
||||||
@ -806,7 +806,6 @@ static void term_draw_cursor (MooTerm *term)
|
|||||||
guint abs_row = buf_cursor_row_abs (term->priv->buffer);
|
guint abs_row = buf_cursor_row_abs (term->priv->buffer);
|
||||||
guint col = buf_cursor_col (term->priv->buffer);
|
guint col = buf_cursor_col (term->priv->buffer);
|
||||||
MooTermLine *line = buf_line (term->priv->buffer, abs_row);
|
MooTermLine *line = buf_line (term->priv->buffer, abs_row);
|
||||||
TermSelection *sel = term->priv->selection;
|
|
||||||
char ch[6];
|
char ch[6];
|
||||||
guint ch_len;
|
guint ch_len;
|
||||||
int screen_row = abs_row - term_top_line (term);
|
int screen_row = abs_row - term_top_line (term);
|
||||||
@ -852,7 +851,7 @@ static void term_draw_cursor (MooTerm *term)
|
|||||||
bg = term->priv->bg[CURSOR][MOO_TERM_COLOR_MAX];
|
bg = term->priv->bg[CURSOR][MOO_TERM_COLOR_MAX];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!term_selected (sel, abs_row, col))
|
if (!moo_term_selected (term, abs_row, col))
|
||||||
{
|
{
|
||||||
gdk_draw_rectangle (term->priv->back_pixmap,
|
gdk_draw_rectangle (term->priv->back_pixmap,
|
||||||
bg,
|
bg,
|
||||||
@ -889,7 +888,7 @@ static void term_draw_cursor (MooTerm *term)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CURSOR_UNDERLINE:
|
case CURSOR_UNDERLINE:
|
||||||
if (!term_selected (sel, abs_row, col))
|
if (!moo_term_selected (term, abs_row, col))
|
||||||
{
|
{
|
||||||
gdk_draw_rectangle (term->priv->back_pixmap,
|
gdk_draw_rectangle (term->priv->back_pixmap,
|
||||||
term->priv->bg[NORMAL][MOO_TERM_COLOR_MAX],
|
term->priv->bg[NORMAL][MOO_TERM_COLOR_MAX],
|
||||||
@ -1031,7 +1030,6 @@ void moo_term_invert_colors (MooTerm *term,
|
|||||||
{
|
{
|
||||||
if (invert != term->priv->colors_inverted)
|
if (invert != term->priv->colors_inverted)
|
||||||
{
|
{
|
||||||
moo_term_invalidate_content_all (term);
|
|
||||||
moo_term_invalidate_all (term);
|
moo_term_invalidate_all (term);
|
||||||
term->priv->colors_inverted = invert;
|
term->priv->colors_inverted = invert;
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ void moo_term_set_mouse_tracking (MooTerm *term,
|
|||||||
term->priv->tracking_mouse = tracking_type;
|
term->priv->tracking_mouse = tracking_type;
|
||||||
moo_term_update_pointer (term);
|
moo_term_update_pointer (term);
|
||||||
stop_mouse_tracking (term);
|
stop_mouse_tracking (term);
|
||||||
term_selection_clear (term);
|
moo_term_selection_clear (term);
|
||||||
|
|
||||||
switch (tracking_type)
|
switch (tracking_type)
|
||||||
{
|
{
|
||||||
|
@ -68,7 +68,6 @@ typedef enum {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct _TermFontInfo TermFontInfo;
|
typedef struct _TermFontInfo TermFontInfo;
|
||||||
typedef struct _TermSelection TermSelection;
|
|
||||||
|
|
||||||
|
|
||||||
struct _MooTermPrivate {
|
struct _MooTermPrivate {
|
||||||
@ -101,8 +100,7 @@ struct _MooTermPrivate {
|
|||||||
int single_shift;
|
int single_shift;
|
||||||
} saved_cursor;
|
} saved_cursor;
|
||||||
|
|
||||||
TermSelection *selection;
|
gpointer selection;
|
||||||
|
|
||||||
TermFontInfo *font_info;
|
TermFontInfo *font_info;
|
||||||
|
|
||||||
GdkPixmap *back_pixmap;
|
GdkPixmap *back_pixmap;
|
||||||
@ -150,6 +148,7 @@ struct _MooTermPrivate {
|
|||||||
(term)->priv->_top_line : \
|
(term)->priv->_top_line : \
|
||||||
buf_scrollback ((term)->priv->buffer))
|
buf_scrollback ((term)->priv->buffer))
|
||||||
|
|
||||||
|
void moo_term_text_iface_init (gpointer iface);
|
||||||
|
|
||||||
void moo_term_set_window_title (MooTerm *term,
|
void moo_term_set_window_title (MooTerm *term,
|
||||||
const char *title);
|
const char *title);
|
||||||
|
@ -13,108 +13,538 @@
|
|||||||
|
|
||||||
#define MOOTERM_COMPILATION
|
#define MOOTERM_COMPILATION
|
||||||
#include "mooterm/mooterm-private.h"
|
#include "mooterm/mooterm-private.h"
|
||||||
|
#include "mooterm/mootermbuffer-private.h"
|
||||||
#include "mooterm/mooterm-selection.h"
|
#include "mooterm/mooterm-selection.h"
|
||||||
|
#include "mooui/mootext.h"
|
||||||
|
|
||||||
|
|
||||||
TermSelection *term_selection_new (void)
|
typedef struct {
|
||||||
|
GtkTextIter start;
|
||||||
|
GtkTextIter end;
|
||||||
|
} Segment;
|
||||||
|
|
||||||
|
#define GET_SELECTION(term) ((Segment*)(term)->priv->selection)
|
||||||
|
|
||||||
|
#define ITER_ROW(iter) ((iter)->dummy3)
|
||||||
|
#define ITER_COL(iter) ((iter)->dummy4)
|
||||||
|
#define ITER_TERM(iter) ((MooTerm*)(iter)->dummy1)
|
||||||
|
#define ITER_SET_TERM(iter, term) (iter)->dummy1 = term
|
||||||
|
|
||||||
|
#define FILL_ITER(iter, term, row, col) \
|
||||||
|
(iter)->dummy1 = term; \
|
||||||
|
ITER_ROW(iter) = row; \
|
||||||
|
ITER_COL(iter) = col;
|
||||||
|
|
||||||
|
|
||||||
|
static int iter_cmp (const GtkTextIter *first,
|
||||||
|
const GtkTextIter *second);
|
||||||
|
static void iter_order (GtkTextIter *first,
|
||||||
|
GtkTextIter *second);
|
||||||
|
static void iter_set_start (GtkTextIter *iter);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gpointer term_selection_new (MooTerm *term)
|
||||||
{
|
{
|
||||||
TermSelection *sel = g_new0 (TermSelection, 1);
|
Segment *sel = g_new0 (Segment, 1);
|
||||||
|
|
||||||
sel->screen_width = 0;
|
FILL_ITER (&sel->start, term, 0, 0);
|
||||||
sel->button_pressed = FALSE;
|
FILL_ITER (&sel->end, term, 0, 0);
|
||||||
sel->click = 1;
|
|
||||||
sel->drag = FALSE;
|
|
||||||
sel->scroll = SELECT_SCROLL_NONE;
|
|
||||||
sel->st_id = 0;
|
|
||||||
sel->empty = TRUE;
|
|
||||||
|
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline static void reset_aux_stuff (TermSelection *sel)
|
static gboolean segment_empty (Segment *s)
|
||||||
{
|
{
|
||||||
sel->button_pressed = FALSE;
|
return !iter_cmp (&s->start, &s->end);
|
||||||
sel->click = 1;
|
|
||||||
sel->drag = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void term_selection_clear (MooTerm *term)
|
static int segment_sym_diff (Segment *s1, Segment *s2,
|
||||||
|
Segment *result)
|
||||||
{
|
{
|
||||||
if (!term->priv->selection->empty)
|
Segment *left = result;
|
||||||
|
Segment *right = &result[1];
|
||||||
|
|
||||||
|
if (segment_empty (s1))
|
||||||
{
|
{
|
||||||
term->priv->selection->empty = TRUE;
|
if (segment_empty (s2))
|
||||||
moo_term_invalidate_all (term);
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*left = *s2;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (segment_empty (s2))
|
||||||
|
{
|
||||||
|
*left = *s1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Segment tmp;
|
||||||
|
GtkTextIter itmp;
|
||||||
|
|
||||||
|
*left = *s1;
|
||||||
|
*right = *s2;
|
||||||
|
iter_order (&left->start, &left->end);
|
||||||
|
iter_order (&right->start, &right->end);
|
||||||
|
|
||||||
|
switch (iter_cmp (&left->start, &right->start))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
switch (iter_cmp (&left->end, &right->end))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
left->start = right->end;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
left->start = left->end;
|
||||||
|
left->end = right->end;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
tmp = *left;
|
||||||
|
*left = *right;
|
||||||
|
*right = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (iter_cmp (&left->end, &right->start))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
left->end = right->end;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
itmp = left->end;
|
||||||
|
left->end = right->start;
|
||||||
|
right->start = itmp;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void invalidate_segment (Segment *segm, guint num)
|
||||||
|
{
|
||||||
|
MooTerm *term;
|
||||||
|
int top_line;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (!num)
|
||||||
|
return;
|
||||||
|
|
||||||
|
term = ITER_TERM (&segm->start);
|
||||||
|
top_line = term_top_line (term);
|
||||||
|
|
||||||
|
for (i = 0; i < num; ++i)
|
||||||
|
{
|
||||||
|
GtkTextIter start = segm[i].start;
|
||||||
|
GtkTextIter end = segm[i].end;
|
||||||
|
GdkRectangle rect;
|
||||||
|
|
||||||
|
iter_order (&start, &end);
|
||||||
|
|
||||||
|
if (ITER_ROW (&start) < ITER_ROW (&end))
|
||||||
|
{
|
||||||
|
if (ITER_COL (&start) < (int)term->priv->width)
|
||||||
|
{
|
||||||
|
rect.x = ITER_COL (&start);
|
||||||
|
rect.width = term->priv->width - rect.x;
|
||||||
|
rect.y = ITER_ROW (&start) - top_line;
|
||||||
|
rect.height = 1;
|
||||||
|
moo_term_invalidate_rect (term, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ITER_ROW (&start) + 1 < ITER_ROW (&end))
|
||||||
|
{
|
||||||
|
rect.x = 0;
|
||||||
|
rect.width = term->priv->width;
|
||||||
|
rect.y = ITER_ROW (&start) + 1 - top_line;
|
||||||
|
rect.height = ITER_ROW (&end) - ITER_ROW (&start) - 1;
|
||||||
|
moo_term_invalidate_rect (term, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ITER_COL (&end) > 0)
|
||||||
|
{
|
||||||
|
rect.x = 0;
|
||||||
|
rect.width = ITER_COL (&end);
|
||||||
|
rect.y = ITER_ROW (&end) - top_line;
|
||||||
|
rect.height = 1;
|
||||||
|
moo_term_invalidate_rect (term, &rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ITER_COL (&start) < ITER_COL (&end))
|
||||||
|
{
|
||||||
|
rect.x = ITER_COL (&start);
|
||||||
|
rect.width = ITER_COL (&end) - ITER_COL (&start);
|
||||||
|
rect.y = ITER_ROW (&start) - top_line;
|
||||||
|
rect.height = 1;
|
||||||
|
moo_term_invalidate_rect (term, &rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *term_selection_get_text (MooTerm *term)
|
static void term_select_range (const GtkTextIter *start,
|
||||||
|
const GtkTextIter *end)
|
||||||
{
|
{
|
||||||
return NULL;
|
Segment diff[2];
|
||||||
|
Segment new_selection;
|
||||||
|
Segment old_selection;
|
||||||
|
|
||||||
|
old_selection = *GET_SELECTION (ITER_TERM (start));
|
||||||
|
|
||||||
|
ITER_SET_TERM (&new_selection.start, ITER_TERM (start));
|
||||||
|
ITER_SET_TERM (&new_selection.end, ITER_TERM (start));
|
||||||
|
|
||||||
|
new_selection.start = *start;
|
||||||
|
new_selection.end = *end;
|
||||||
|
|
||||||
|
if (!iter_cmp (start, end))
|
||||||
|
{
|
||||||
|
iter_set_start (&new_selection.start);
|
||||||
|
iter_set_start (&new_selection.end);
|
||||||
|
}
|
||||||
|
|
||||||
|
GET_SELECTION (ITER_TERM (start))->start = new_selection.start;
|
||||||
|
GET_SELECTION (ITER_TERM (start))->end = new_selection.end;
|
||||||
|
|
||||||
|
invalidate_segment (diff,
|
||||||
|
segment_sym_diff (&new_selection,
|
||||||
|
&old_selection,
|
||||||
|
diff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define HOWMANY(x, y) (((x) + (y) - 1) / y())
|
|
||||||
#define CALC_ROW(y, char_height) (HOWMANY (y + 1, char_height) - 1)
|
|
||||||
#define CALC_COL(x, char_width) (HOWMANY (x + 1, char_width) - 1)
|
|
||||||
#define DIFF(x, y) (ABS ((x) - (y)))
|
|
||||||
|
|
||||||
|
|
||||||
gboolean moo_term_button_press (GtkWidget *widget,
|
gboolean moo_term_button_press (GtkWidget *widget,
|
||||||
GdkEventButton *event)
|
GdkEventButton *event)
|
||||||
{
|
{
|
||||||
MooTerm *term;
|
moo_term_set_pointer_visible (MOO_TERM (widget), TRUE);
|
||||||
|
return moo_text_button_press_event (widget, event);
|
||||||
term = MOO_TERM (widget);
|
|
||||||
|
|
||||||
moo_term_set_pointer_visible (term, TRUE);
|
|
||||||
|
|
||||||
if (event->button != 1)
|
|
||||||
{
|
|
||||||
if (event->type != GDK_BUTTON_PRESS)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
switch (event->button)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
moo_term_paste_clipboard (term, GDK_SELECTION_PRIMARY);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
moo_term_do_popup_menu (term, event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gboolean moo_term_button_release (GtkWidget *widget,
|
gboolean moo_term_button_release (GtkWidget *widget,
|
||||||
GdkEventButton *event)
|
GdkEventButton *event)
|
||||||
{
|
{
|
||||||
MooTerm *term;
|
moo_term_set_pointer_visible (MOO_TERM (widget), TRUE);
|
||||||
|
return moo_text_button_release_event (widget, event);
|
||||||
term = MOO_TERM (widget);
|
|
||||||
|
|
||||||
moo_term_set_pointer_visible (term, TRUE);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gboolean moo_term_motion_notify (GtkWidget *widget,
|
gboolean moo_term_motion_notify (GtkWidget *widget,
|
||||||
GdkEventMotion *event)
|
GdkEventMotion *event)
|
||||||
{
|
{
|
||||||
MooTerm *term;
|
moo_term_set_pointer_visible (MOO_TERM (widget), TRUE);
|
||||||
|
return moo_text_motion_event (widget, event);
|
||||||
term = MOO_TERM (widget);
|
}
|
||||||
|
|
||||||
moo_term_set_pointer_visible (term, TRUE);
|
|
||||||
|
|
||||||
return TRUE;
|
gboolean moo_term_selection_empty (MooTerm *term)
|
||||||
|
{
|
||||||
|
return segment_empty (GET_SELECTION (term));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean moo_term_get_selection_bounds (MooTerm *term,
|
||||||
|
guint *left_row,
|
||||||
|
guint *left_col,
|
||||||
|
guint *right_row,
|
||||||
|
guint *right_col)
|
||||||
|
{
|
||||||
|
Segment *selection = GET_SELECTION (term);
|
||||||
|
|
||||||
|
if (segment_empty (selection))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (iter_cmp (&selection->start, &selection->end) > 0)
|
||||||
|
{
|
||||||
|
*left_row = ITER_ROW (&selection->end);
|
||||||
|
*left_col = ITER_COL (&selection->end);
|
||||||
|
*right_row = ITER_ROW (&selection->start);
|
||||||
|
*right_col = ITER_COL (&selection->start);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*left_row = ITER_ROW (&selection->start);
|
||||||
|
*left_col = ITER_COL (&selection->start);
|
||||||
|
*right_row = ITER_ROW (&selection->end);
|
||||||
|
*right_col = ITER_COL (&selection->end);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void moo_term_selection_clear (MooTerm *term)
|
||||||
|
{
|
||||||
|
GtkTextIter i;
|
||||||
|
FILL_ITER (&i, term, 0, 0);
|
||||||
|
term_select_range (&i, &i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void middle_button_click (MooText *obj,
|
||||||
|
G_GNUC_UNUSED GdkEventButton *event)
|
||||||
|
{
|
||||||
|
moo_term_paste_clipboard (MOO_TERM (obj), GDK_SELECTION_PRIMARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void right_button_click (MooText *obj,
|
||||||
|
GdkEventButton *event)
|
||||||
|
{
|
||||||
|
moo_term_do_popup_menu (MOO_TERM (obj), event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean extend_selection (MooText *obj,
|
||||||
|
MooTextSelectionType type,
|
||||||
|
GtkTextIter *insert,
|
||||||
|
GtkTextIter *selection_bound)
|
||||||
|
{
|
||||||
|
term_select_range (selection_bound, insert);
|
||||||
|
return iter_cmp (selection_bound, insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void window_to_buffer_coords (MooText *obj,
|
||||||
|
int window_x,
|
||||||
|
int window_y,
|
||||||
|
int *buffer_x,
|
||||||
|
int *buffer_y)
|
||||||
|
{
|
||||||
|
MooTerm *term = MOO_TERM (obj);
|
||||||
|
*buffer_x = window_x;
|
||||||
|
*buffer_y = window_y + (term_top_line (term) * term_char_height (term));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void get_iter_at_location (MooText *obj,
|
||||||
|
GtkTextIter *iter,
|
||||||
|
int x,
|
||||||
|
int y)
|
||||||
|
{
|
||||||
|
MooTerm *term = MOO_TERM (obj);
|
||||||
|
int char_width = term_char_width (term);
|
||||||
|
int char_height = term_char_height (term);
|
||||||
|
int scrollback = buf_scrollback (term->priv->buffer);
|
||||||
|
guint row, col;
|
||||||
|
|
||||||
|
g_return_if_fail (iter != NULL);
|
||||||
|
|
||||||
|
y /= char_height;
|
||||||
|
y = CLAMP (y, 0, scrollback + (int)term->priv->height - 1);
|
||||||
|
row = y;
|
||||||
|
|
||||||
|
x = CLAMP (x, 0, (int)term->priv->width * char_width - 1);
|
||||||
|
col = (x % char_width > char_width / 2) ?
|
||||||
|
x / char_width + 1 :
|
||||||
|
x / char_width;
|
||||||
|
|
||||||
|
FILL_ITER (iter, term, row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean get_selection_bounds (MooText *obj,
|
||||||
|
GtkTextIter *sel_start,
|
||||||
|
GtkTextIter *sel_end)
|
||||||
|
{
|
||||||
|
MooTerm *term = MOO_TERM (obj);
|
||||||
|
Segment *selection = term->priv->selection;
|
||||||
|
|
||||||
|
if (sel_start)
|
||||||
|
*sel_start = selection->start;
|
||||||
|
|
||||||
|
if (sel_end)
|
||||||
|
*sel_end = selection->end;
|
||||||
|
|
||||||
|
return !moo_term_selection_empty (term);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int iter_cmp (const GtkTextIter *first,
|
||||||
|
const GtkTextIter *second)
|
||||||
|
{
|
||||||
|
g_assert (ITER_TERM (first) == ITER_TERM (second));
|
||||||
|
|
||||||
|
if (ITER_ROW (first) < ITER_ROW (second))
|
||||||
|
return -1;
|
||||||
|
else if (ITER_ROW (first) > ITER_ROW (second))
|
||||||
|
return 1;
|
||||||
|
else if (ITER_COL (first) < ITER_COL (second))
|
||||||
|
return -1;
|
||||||
|
else if (ITER_COL (first) > ITER_COL (second))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void iter_set_start (GtkTextIter *iter)
|
||||||
|
{
|
||||||
|
ITER_ROW (iter) = ITER_COL (iter) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void iter_order (GtkTextIter *first,
|
||||||
|
GtkTextIter *second)
|
||||||
|
{
|
||||||
|
if (iter_cmp (first, second) > 0)
|
||||||
|
{
|
||||||
|
GtkTextIter tmp = *first;
|
||||||
|
*first = *second;
|
||||||
|
*second = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean iter_in_range (const GtkTextIter *iter,
|
||||||
|
const GtkTextIter *start,
|
||||||
|
const GtkTextIter *end)
|
||||||
|
{
|
||||||
|
return iter_cmp (start, iter) <= 0 && iter_cmp (iter, end) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void select_range (G_GNUC_UNUSED MooText *obj,
|
||||||
|
const GtkTextIter *start,
|
||||||
|
const GtkTextIter *end)
|
||||||
|
{
|
||||||
|
term_select_range (start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void place_selection_end (MooText *obj,
|
||||||
|
const GtkTextIter *where)
|
||||||
|
{
|
||||||
|
MooTerm *term = MOO_TERM (obj);
|
||||||
|
term_select_range (&GET_SELECTION(term)->start, where);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void scroll_selection_end_onscreen (MooText *obj)
|
||||||
|
{
|
||||||
|
MooTerm *term = MOO_TERM (obj);
|
||||||
|
GtkTextIter iter = GET_SELECTION(term)->end;
|
||||||
|
guint top_line = term_top_line (term);
|
||||||
|
|
||||||
|
if (ITER_ROW(&iter) < (int)top_line)
|
||||||
|
moo_term_scroll_lines (term, ITER_ROW(&iter) - (int)top_line);
|
||||||
|
else if (ITER_ROW(&iter) >= (int)top_line + (int)term->priv->height)
|
||||||
|
moo_term_scroll_lines (term, ITER_ROW(&iter) + 1 -
|
||||||
|
(int)top_line - (int)term->priv->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GdkWindow* get_window (MooText *obj)
|
||||||
|
{
|
||||||
|
return GTK_WIDGET(obj)->window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void get_visible_rect (MooText *obj,
|
||||||
|
GdkRectangle *rect)
|
||||||
|
{
|
||||||
|
MooTerm *term = MOO_TERM (obj);
|
||||||
|
int char_height = term_char_height (term);
|
||||||
|
rect->x = 0;
|
||||||
|
rect->width = term->priv->width * term_char_width (term);
|
||||||
|
rect->y = term_top_line (term) * char_height;
|
||||||
|
rect->height = term->priv->height * char_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean moo_term_selected (MooTerm *term,
|
||||||
|
guint row,
|
||||||
|
guint col)
|
||||||
|
{
|
||||||
|
GtkTextIter start, end, iter;
|
||||||
|
|
||||||
|
if (get_selection_bounds (MOO_TEXT (term), &start, &end))
|
||||||
|
{
|
||||||
|
iter_order (&start, &end);
|
||||||
|
FILL_ITER (&iter, term, row, col);
|
||||||
|
return iter_in_range (&iter, &start, &end);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int moo_term_selection_row_selected (MooTerm *term,
|
||||||
|
guint row)
|
||||||
|
{
|
||||||
|
GtkTextIter start, end;
|
||||||
|
|
||||||
|
if (get_selection_bounds (MOO_TEXT (term), &start, &end))
|
||||||
|
{
|
||||||
|
iter_order (&start, &end);
|
||||||
|
|
||||||
|
if (ITER_ROW (&end) < (int)row || (int)row < ITER_ROW (&start))
|
||||||
|
return NOT_SELECTED;
|
||||||
|
else if (ITER_ROW (&start) < (int)row && (int)row < ITER_ROW (&end))
|
||||||
|
return FULL_SELECTED;
|
||||||
|
else
|
||||||
|
return PART_SELECTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void moo_term_text_iface_init (gpointer g_iface)
|
||||||
|
{
|
||||||
|
MooTextIface *iface = (MooTextIface*) g_iface;
|
||||||
|
|
||||||
|
iface->start_selection_dnd = NULL;
|
||||||
|
|
||||||
|
iface->middle_button_click = middle_button_click;
|
||||||
|
iface->right_button_click = right_button_click;
|
||||||
|
|
||||||
|
iface->extend_selection = extend_selection;
|
||||||
|
iface->window_to_buffer_coords = window_to_buffer_coords;
|
||||||
|
iface->get_iter_at_location = get_iter_at_location;
|
||||||
|
iface->get_selection_bounds = get_selection_bounds;
|
||||||
|
iface->iter_order = iter_order;
|
||||||
|
iface->iter_in_range = iter_in_range;
|
||||||
|
iface->place_selection_end = place_selection_end;
|
||||||
|
iface->select_range = select_range;
|
||||||
|
iface->scroll_selection_end_onscreen = scroll_selection_end_onscreen;
|
||||||
|
|
||||||
|
iface->get_window = get_window;
|
||||||
|
iface->get_visible_rect = get_visible_rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *moo_term_selection_get_text (MooTerm *term)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#ifndef MOOTERM_MOOTERM_SELECTION_H
|
#ifndef MOOTERM_MOOTERM_SELECTION_H
|
||||||
#define MOOTERM_MOOTERM_SELECTION_H
|
#define MOOTERM_MOOTERM_SELECTION_H
|
||||||
|
|
||||||
#include <glib.h>
|
#include <mooterm/mooterm.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -25,82 +25,24 @@ enum {
|
|||||||
PART_SELECTED = 2
|
PART_SELECTED = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SELECT_SCROLL_NONE (0)
|
|
||||||
#define SELECT_SCROLL_UP (-1)
|
|
||||||
#define SELECT_SCROLL_DOWN (1)
|
|
||||||
|
|
||||||
struct _TermSelection {
|
gboolean moo_term_selection_empty (MooTerm *term);
|
||||||
guint screen_width;
|
|
||||||
|
|
||||||
/* absolute coordinates in the buffer
|
gpointer term_selection_new (MooTerm *term);
|
||||||
selected range is [(l_row, l_col), (r_row, r_col))
|
|
||||||
l_row, l_col and r_row are valid
|
|
||||||
r_col may be equal to _width */
|
|
||||||
guint l_row;
|
|
||||||
guint l_col;
|
|
||||||
guint r_row;
|
|
||||||
guint r_col;
|
|
||||||
gboolean empty;
|
|
||||||
|
|
||||||
gboolean button_pressed;
|
|
||||||
int click;
|
|
||||||
gboolean drag;
|
|
||||||
// buffer coordinates
|
|
||||||
guint drag_begin_row;
|
|
||||||
guint drag_begin_col;
|
|
||||||
guint drag_end_row;
|
|
||||||
guint drag_end_col;
|
|
||||||
|
|
||||||
int scroll;
|
|
||||||
guint st_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
TermSelection *term_selection_new (void);
|
void moo_term_selection_clear (MooTerm *term);
|
||||||
|
char *moo_term_selection_get_text (MooTerm *term);
|
||||||
#define term_selection_free(sel) g_free (sel)
|
int moo_term_selection_row_selected (MooTerm *term,
|
||||||
|
guint row);
|
||||||
void term_set_selection (struct _MooTerm *term,
|
gboolean moo_term_selected (MooTerm *term,
|
||||||
guint row1,
|
guint row,
|
||||||
guint col1,
|
guint col);
|
||||||
guint row2,
|
gboolean moo_term_get_selection_bounds (MooTerm *term,
|
||||||
guint col2);
|
guint *left_row,
|
||||||
void term_selection_clear (struct _MooTerm *term);
|
guint *left_col,
|
||||||
char *term_selection_get_text (struct _MooTerm *term);
|
guint *right_row,
|
||||||
|
guint *right_col);
|
||||||
inline static void term_selection_set_width (struct _MooTerm *term,
|
|
||||||
guint width)
|
|
||||||
{
|
|
||||||
term->priv->selection->screen_width = width;
|
|
||||||
term_selection_clear (term);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int term_selection_row_selected (TermSelection *sel,
|
|
||||||
guint row)
|
|
||||||
{
|
|
||||||
if (sel->empty || sel->r_row < row || row < sel->l_row)
|
|
||||||
return NOT_SELECTED;
|
|
||||||
else if (sel->l_row < row && row < sel->r_row)
|
|
||||||
return FULL_SELECTED;
|
|
||||||
else
|
|
||||||
return PART_SELECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static gboolean term_selected (TermSelection *sel,
|
|
||||||
guint row,
|
|
||||||
guint col)
|
|
||||||
{
|
|
||||||
if (sel->empty || sel->r_row < row || row < sel->l_row)
|
|
||||||
return FALSE;
|
|
||||||
else if (sel->l_row < row && row < sel->r_row)
|
|
||||||
return TRUE;
|
|
||||||
else if (sel->l_row == sel->r_row)
|
|
||||||
return sel->l_col <= col && col < sel->r_col;
|
|
||||||
else if (sel->l_row == row)
|
|
||||||
return sel->l_col <= col;
|
|
||||||
else
|
|
||||||
return col < sel->r_row;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -17,10 +17,13 @@
|
|||||||
#include "mooterm/mootermparser.h"
|
#include "mooterm/mootermparser.h"
|
||||||
#include "mooterm/mootermpt.h"
|
#include "mooterm/mootermpt.h"
|
||||||
#include "mooterm/mootermbuffer-private.h"
|
#include "mooterm/mootermbuffer-private.h"
|
||||||
|
#include "mooui/mootext.h"
|
||||||
#include "mooutils/moocompat.h"
|
#include "mooutils/moocompat.h"
|
||||||
#include "mooutils/moomarshals.h"
|
#include "mooutils/moomarshals.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void moo_term_class_init (MooTermClass *klass);
|
||||||
|
static void moo_term_init (MooTerm *term);
|
||||||
static void moo_term_finalize (GObject *object);
|
static void moo_term_finalize (GObject *object);
|
||||||
|
|
||||||
static void moo_term_realize (GtkWidget *widget);
|
static void moo_term_realize (GtkWidget *widget);
|
||||||
@ -83,7 +86,44 @@ enum {
|
|||||||
|
|
||||||
|
|
||||||
/* MOO_TYPE_TERM */
|
/* MOO_TYPE_TERM */
|
||||||
G_DEFINE_TYPE (MooTerm, moo_term, GTK_TYPE_WIDGET)
|
static gpointer moo_term_parent_class = NULL;
|
||||||
|
GType moo_term_get_type (void)
|
||||||
|
{
|
||||||
|
static GType type = 0;
|
||||||
|
|
||||||
|
if (!type)
|
||||||
|
{
|
||||||
|
static const GTypeInfo info = {
|
||||||
|
sizeof (MooTermClass),
|
||||||
|
(GBaseInitFunc) NULL,
|
||||||
|
(GBaseFinalizeFunc) NULL,
|
||||||
|
(GClassInitFunc) moo_term_class_init,
|
||||||
|
(GClassFinalizeFunc) NULL,
|
||||||
|
NULL, /* class_data */
|
||||||
|
sizeof (MooTerm),
|
||||||
|
0, /* n_preallocs */
|
||||||
|
(GInstanceInitFunc) moo_term_init,
|
||||||
|
NULL /* value_table */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GInterfaceInfo iface_info = {
|
||||||
|
(GInterfaceInitFunc) moo_term_text_iface_init,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
type = g_type_register_static (GTK_TYPE_WIDGET, "MooTerm",
|
||||||
|
&info, (GTypeFlags) 0);
|
||||||
|
|
||||||
|
g_type_add_interface_static (type,
|
||||||
|
MOO_TYPE_TEXT,
|
||||||
|
&iface_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static guint signals[LAST_SIGNAL];
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
|
||||||
@ -92,6 +132,8 @@ static void moo_term_class_init (MooTermClass *klass)
|
|||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
|
||||||
|
moo_term_parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
gobject_class->finalize = moo_term_finalize;
|
gobject_class->finalize = moo_term_finalize;
|
||||||
|
|
||||||
widget_class->realize = moo_term_realize;
|
widget_class->realize = moo_term_realize;
|
||||||
@ -188,7 +230,7 @@ static void moo_term_init (MooTerm *term)
|
|||||||
term->priv->width = 80;
|
term->priv->width = 80;
|
||||||
term->priv->height = 24;
|
term->priv->height = 24;
|
||||||
|
|
||||||
term->priv->selection = term_selection_new ();
|
term->priv->selection = term_selection_new (term);
|
||||||
|
|
||||||
term->priv->cursor_visible = TRUE;
|
term->priv->cursor_visible = TRUE;
|
||||||
|
|
||||||
@ -261,7 +303,7 @@ static void moo_term_finalize (GObject *object)
|
|||||||
g_object_unref (term->priv->primary_buffer);
|
g_object_unref (term->priv->primary_buffer);
|
||||||
g_object_unref (term->priv->alternate_buffer);
|
g_object_unref (term->priv->alternate_buffer);
|
||||||
|
|
||||||
term_selection_free (term->priv->selection);
|
g_free (term->priv->selection);
|
||||||
term_font_info_free (term->priv->font_info);
|
term_font_info_free (term->priv->font_info);
|
||||||
|
|
||||||
g_object_unref (term->priv->back_pixmap);
|
g_object_unref (term->priv->back_pixmap);
|
||||||
@ -464,7 +506,7 @@ static void scrollback_changed (MooTerm *term,
|
|||||||
|
|
||||||
if (term->priv->_scrolled && term->priv->_top_line > scrollback)
|
if (term->priv->_scrolled && term->priv->_top_line > scrollback)
|
||||||
{
|
{
|
||||||
term_selection_clear (term);
|
moo_term_selection_clear (term);
|
||||||
scroll_to_bottom (term, TRUE);
|
scroll_to_bottom (term, TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -485,8 +527,7 @@ static void width_changed (MooTerm *term,
|
|||||||
if (GTK_WIDGET_REALIZED (term))
|
if (GTK_WIDGET_REALIZED (term))
|
||||||
moo_term_resize_back_pixmap (term);
|
moo_term_resize_back_pixmap (term);
|
||||||
|
|
||||||
term_selection_set_width (term, term->priv->width);
|
moo_term_selection_clear (term);
|
||||||
term_selection_clear (term);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -507,7 +548,7 @@ static void height_changed (MooTerm *term,
|
|||||||
if (GTK_WIDGET_REALIZED (term))
|
if (GTK_WIDGET_REALIZED (term))
|
||||||
moo_term_resize_back_pixmap (term);
|
moo_term_resize_back_pixmap (term);
|
||||||
|
|
||||||
term_selection_clear (term);
|
moo_term_selection_clear (term);
|
||||||
moo_term_invalidate_all (term);
|
moo_term_invalidate_all (term);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,7 +708,6 @@ static void scroll_abs (MooTerm *term,
|
|||||||
term->priv->_top_line = line;
|
term->priv->_top_line = line;
|
||||||
term->priv->_scrolled = TRUE;
|
term->priv->_scrolled = TRUE;
|
||||||
|
|
||||||
moo_term_invalidate_content_all (term);
|
|
||||||
moo_term_invalidate_all (term);
|
moo_term_invalidate_all (term);
|
||||||
|
|
||||||
if (update_adj)
|
if (update_adj)
|
||||||
@ -696,7 +736,6 @@ static void scroll_to_bottom (MooTerm *term,
|
|||||||
|
|
||||||
term->priv->_scrolled = FALSE;
|
term->priv->_scrolled = FALSE;
|
||||||
|
|
||||||
moo_term_invalidate_content_all (term);
|
|
||||||
moo_term_invalidate_all (term);
|
moo_term_invalidate_all (term);
|
||||||
|
|
||||||
if (update_full)
|
if (update_full)
|
||||||
@ -759,7 +798,7 @@ void moo_term_copy_clipboard (MooTerm *term,
|
|||||||
GtkClipboard *cb;
|
GtkClipboard *cb;
|
||||||
char *text;
|
char *text;
|
||||||
|
|
||||||
text = term_selection_get_text (term);
|
text = moo_term_selection_get_text (term);
|
||||||
|
|
||||||
if (text && *text)
|
if (text && *text)
|
||||||
{
|
{
|
||||||
@ -1176,7 +1215,6 @@ void moo_term_set_alternate_buffer (MooTerm *term,
|
|||||||
else
|
else
|
||||||
term->priv->buffer = term->priv->primary_buffer;
|
term->priv->buffer = term->priv->primary_buffer;
|
||||||
|
|
||||||
moo_term_invalidate_content_all (term);
|
|
||||||
moo_term_invalidate_all (term);
|
moo_term_invalidate_all (term);
|
||||||
moo_term_buffer_scrollback_changed (term->priv->buffer);
|
moo_term_buffer_scrollback_changed (term->priv->buffer);
|
||||||
}
|
}
|
||||||
@ -1414,16 +1452,44 @@ static void menu_position_func (G_GNUC_UNUSED GtkMenu *menu,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void menu_copy (MooTerm *term)
|
||||||
|
{
|
||||||
|
moo_term_copy_clipboard (term, GDK_SELECTION_CLIPBOARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void menu_paste (MooTerm *term)
|
||||||
|
{
|
||||||
|
moo_term_paste_clipboard (term, GDK_SELECTION_CLIPBOARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_menu (GtkWidget *menu)
|
||||||
|
{
|
||||||
|
g_idle_add ((GSourceFunc)gtk_widget_destroy, menu);
|
||||||
|
}
|
||||||
|
|
||||||
void moo_term_do_popup_menu (MooTerm *term,
|
void moo_term_do_popup_menu (MooTerm *term,
|
||||||
GdkEventButton *event)
|
GdkEventButton *event)
|
||||||
{
|
{
|
||||||
GtkWidget *menu;
|
GtkWidget *menu;
|
||||||
|
GtkWidget *item;
|
||||||
|
|
||||||
menu = gtk_menu_new ();
|
menu = gtk_menu_new ();
|
||||||
|
/* TODO: wtf? */
|
||||||
g_signal_connect (menu, "deactivate",
|
g_signal_connect (menu, "deactivate",
|
||||||
G_CALLBACK (gtk_widget_destroy), NULL);
|
G_CALLBACK (destroy_menu), NULL);
|
||||||
|
|
||||||
|
item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
|
||||||
|
gtk_widget_show (item);
|
||||||
|
g_signal_connect_swapped (item, "activate",
|
||||||
|
G_CALLBACK (menu_copy), term);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||||
|
|
||||||
|
item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, NULL);
|
||||||
|
gtk_widget_show (item);
|
||||||
|
g_signal_connect_swapped (item, "activate",
|
||||||
|
G_CALLBACK (menu_paste), term);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||||
|
|
||||||
/* TODO: add copy/paste */
|
|
||||||
g_signal_emit (term, signals[POPULATE_POPUP], 0, menu);
|
g_signal_emit (term, signals[POPULATE_POPUP], 0, menu);
|
||||||
|
|
||||||
if (event)
|
if (event)
|
||||||
|
@ -28,6 +28,8 @@ libmooui_la_SOURCES = \
|
|||||||
mooshortcutsprefs-glade.c \
|
mooshortcutsprefs-glade.c \
|
||||||
mooshortcutsprefs.c \
|
mooshortcutsprefs.c \
|
||||||
mooshortcutsprefs.h \
|
mooshortcutsprefs.h \
|
||||||
|
mootext.c \
|
||||||
|
mootext.h \
|
||||||
mootoggleaction.c \
|
mootoggleaction.c \
|
||||||
mootoggleaction.h \
|
mootoggleaction.h \
|
||||||
moouiobject.c \
|
moouiobject.c \
|
||||||
|
474
moo/mooui/mootext.c
Normal file
474
moo/mooui/mootext.c
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
/*
|
||||||
|
* mooui/mootext.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* See COPYING file that comes with this distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mooui/mootext.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _MooTextData MooTextData;
|
||||||
|
struct _MooTextData {
|
||||||
|
guint drag_scroll_timeout;
|
||||||
|
GdkEventType drag_button;
|
||||||
|
MooTextDragType drag_type;
|
||||||
|
int drag_start_x;
|
||||||
|
int drag_start_y;
|
||||||
|
guint drag_moved : 1;
|
||||||
|
guint double_click_selects_brackets : 1;
|
||||||
|
guint double_click_selects_inside : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const GQuark *get_quark (void) G_GNUC_CONST;
|
||||||
|
static MooTextData *moo_text_data_new (void);
|
||||||
|
static MooTextData *moo_text_data_clear (MooTextData *data);
|
||||||
|
static void moo_text_data_free (MooTextData *data);
|
||||||
|
static MooTextData *moo_text_get_data (MooText *obj);
|
||||||
|
|
||||||
|
#define MOO_TEXT_DATA_QUARK (get_quark()[0])
|
||||||
|
#define GET_DATA(obj) (moo_text_get_data (obj))
|
||||||
|
|
||||||
|
typedef gboolean (*ExtendSelectionFunc) (MooText *obj,
|
||||||
|
MooTextSelectionType type,
|
||||||
|
GtkTextIter *insert,
|
||||||
|
GtkTextIter *selection_bound);
|
||||||
|
typedef void (*StartSelectionDndFunc) (MooText *obj,
|
||||||
|
const GtkTextIter *iter,
|
||||||
|
GdkEventMotion *event);
|
||||||
|
|
||||||
|
|
||||||
|
static MooTextData *moo_text_data_new (void)
|
||||||
|
{
|
||||||
|
return moo_text_data_clear (g_new0 (MooTextData, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static MooTextData *moo_text_data_clear (MooTextData *data)
|
||||||
|
{
|
||||||
|
data->drag_moved = FALSE;
|
||||||
|
data->drag_type = MOO_TEXT_DRAG_NONE;
|
||||||
|
data->drag_start_x = -1;
|
||||||
|
data->drag_start_y = -1;
|
||||||
|
data->drag_button = GDK_BUTTON_RELEASE;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void moo_text_data_free (MooTextData *data)
|
||||||
|
{
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* mouse functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define get_impl(func) MOO_TEXT_GET_IFACE(obj)->func
|
||||||
|
|
||||||
|
static gboolean can_drag_selection (MooText *obj)
|
||||||
|
{
|
||||||
|
return MOO_TEXT_GET_IFACE(obj)->start_selection_dnd != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void start_drag_scroll (MooText *obj);
|
||||||
|
static void stop_drag_scroll (MooText *obj);
|
||||||
|
static gboolean drag_scroll_timeout_func (MooText *obj);
|
||||||
|
static const int SCROLL_TIMEOUT = 100;
|
||||||
|
|
||||||
|
|
||||||
|
gboolean moo_text_button_press_event (GtkWidget *widget,
|
||||||
|
GdkEventButton *event)
|
||||||
|
{
|
||||||
|
MooText *obj;
|
||||||
|
GtkTextIter iter;
|
||||||
|
MooTextData *data;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
obj = MOO_TEXT (widget);
|
||||||
|
data = moo_text_get_data (obj);
|
||||||
|
|
||||||
|
gtk_widget_grab_focus (widget);
|
||||||
|
|
||||||
|
get_impl(window_to_buffer_coords) (obj, event->x, event->y, &x, &y);
|
||||||
|
get_impl(get_iter_at_location) (obj, &iter, x, y);
|
||||||
|
|
||||||
|
if (event->type == GDK_BUTTON_PRESS)
|
||||||
|
{
|
||||||
|
if (event->button == 1)
|
||||||
|
{
|
||||||
|
GtkTextIter sel_start, sel_end;
|
||||||
|
|
||||||
|
data->drag_button = GDK_BUTTON_PRESS;
|
||||||
|
data->drag_start_x = x;
|
||||||
|
data->drag_start_y = y;
|
||||||
|
|
||||||
|
/* if clicked in selected, start drag */
|
||||||
|
if (get_impl(get_selection_bounds) (obj, &sel_start, &sel_end))
|
||||||
|
{
|
||||||
|
get_impl(iter_order) (&sel_start, &sel_end);
|
||||||
|
if (get_impl(iter_in_range) (&iter, &sel_start, &sel_end)
|
||||||
|
&& can_drag_selection (obj))
|
||||||
|
{
|
||||||
|
/* clicked inside of selection,
|
||||||
|
* set up drag and return */
|
||||||
|
data->drag_type = MOO_TEXT_DRAG_DRAG;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* otherwise, clear selection, and position cursor at clicked point */
|
||||||
|
if (event->state & GDK_SHIFT_MASK)
|
||||||
|
{
|
||||||
|
get_impl(place_selection_end) (obj, &iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
get_impl(select_range) (obj, &iter, &iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->drag_type = MOO_TEXT_DRAG_SELECT;
|
||||||
|
}
|
||||||
|
else if (event->button == 2)
|
||||||
|
{
|
||||||
|
get_impl(middle_button_click) (obj, event);
|
||||||
|
}
|
||||||
|
else if (event->button == 3)
|
||||||
|
{
|
||||||
|
get_impl(right_button_click) (obj, event);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning ("got button %d in button_press callback", event->button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
|
||||||
|
{
|
||||||
|
GtkTextIter bound;
|
||||||
|
|
||||||
|
if (get_impl(get_selection_bounds) (obj, NULL, NULL))
|
||||||
|
{
|
||||||
|
/* it may happen sometimes, if you click fast enough */
|
||||||
|
get_impl(select_range) (obj, &iter, &iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->drag_button = GDK_2BUTTON_PRESS;
|
||||||
|
data->drag_start_x = x;
|
||||||
|
data->drag_start_y = y;
|
||||||
|
data->drag_type = MOO_TEXT_DRAG_SELECT;
|
||||||
|
|
||||||
|
bound = iter;
|
||||||
|
|
||||||
|
if (get_impl(extend_selection) (obj, MOO_TEXT_SELECT_WORDS, &iter, &bound))
|
||||||
|
get_impl(select_range) (obj, &bound, &iter);
|
||||||
|
}
|
||||||
|
else if (event->type == GDK_3BUTTON_PRESS && event->button == 1)
|
||||||
|
{
|
||||||
|
GtkTextIter bound;
|
||||||
|
|
||||||
|
data->drag_button = GDK_3BUTTON_PRESS;
|
||||||
|
data->drag_start_x = x;
|
||||||
|
data->drag_start_y = y;
|
||||||
|
data->drag_type = MOO_TEXT_DRAG_SELECT;
|
||||||
|
|
||||||
|
bound = iter;
|
||||||
|
|
||||||
|
if (get_impl(extend_selection) (obj, MOO_TEXT_SELECT_LINES, &iter, &bound))
|
||||||
|
get_impl(select_range) (obj, &bound, &iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean moo_text_button_release_event (GtkWidget *widget,
|
||||||
|
G_GNUC_UNUSED GdkEventButton *event)
|
||||||
|
{
|
||||||
|
MooText *obj = MOO_TEXT (widget);
|
||||||
|
MooTextData *data = moo_text_get_data (obj);
|
||||||
|
GtkTextIter iter;
|
||||||
|
|
||||||
|
switch (data->drag_type)
|
||||||
|
{
|
||||||
|
case MOO_TEXT_DRAG_NONE:
|
||||||
|
/* it may happen after right-click, or clicking outside
|
||||||
|
* of widget or something like that
|
||||||
|
* everything has been taken care of, so do nothing */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MOO_TEXT_DRAG_SELECT:
|
||||||
|
/* everything should be done already in button_press and
|
||||||
|
* motion_notify handlers */
|
||||||
|
stop_drag_scroll (obj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MOO_TEXT_DRAG_DRAG:
|
||||||
|
/* if we were really dragging, drop it
|
||||||
|
* otherwise, it was just a single click in selected text */
|
||||||
|
g_assert (!data->drag_moved); /* parent should handle drag */ /* TODO ??? */
|
||||||
|
|
||||||
|
get_impl(get_iter_at_location) (obj, &iter,
|
||||||
|
data->drag_start_x,
|
||||||
|
data->drag_start_y);
|
||||||
|
get_impl(select_range) (obj, &iter, &iter);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
moo_text_data_clear (data);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define outside(x,y,rect) \
|
||||||
|
((x) < (rect).x || \
|
||||||
|
(y) < (rect).y || \
|
||||||
|
(x) >= (rect).x + (rect).width || \
|
||||||
|
(y) >= (rect).y + (rect).height)
|
||||||
|
|
||||||
|
gboolean moo_text_motion_event (GtkWidget *widget,
|
||||||
|
GdkEventMotion *event)
|
||||||
|
{
|
||||||
|
MooText *obj = MOO_TEXT (widget);
|
||||||
|
MooTextData *data = moo_text_get_data (obj);
|
||||||
|
int x, y, event_x, event_y;
|
||||||
|
GtkTextIter iter;
|
||||||
|
|
||||||
|
if (!data->drag_type)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (event->is_hint)
|
||||||
|
{
|
||||||
|
gdk_window_get_pointer (event->window, &event_x, &event_y, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event_x = (int)event->x;
|
||||||
|
event_y = (int)event->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_impl(window_to_buffer_coords) (obj, event_x, event_y, &x, &y);
|
||||||
|
get_impl(get_iter_at_location) (obj, &iter, x, y);
|
||||||
|
|
||||||
|
if (data->drag_type == MOO_TEXT_DRAG_SELECT)
|
||||||
|
{
|
||||||
|
GdkRectangle rect;
|
||||||
|
GtkTextIter start;
|
||||||
|
MooTextSelectionType t;
|
||||||
|
|
||||||
|
data->drag_moved = TRUE;
|
||||||
|
get_impl(get_visible_rect) (obj, &rect);
|
||||||
|
|
||||||
|
if (outside (x, y, rect))
|
||||||
|
{
|
||||||
|
start_drag_scroll (obj);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stop_drag_scroll (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_impl(get_iter_at_location) (obj, &start,
|
||||||
|
data->drag_start_x,
|
||||||
|
data->drag_start_y);
|
||||||
|
|
||||||
|
switch (data->drag_button)
|
||||||
|
{
|
||||||
|
case GDK_BUTTON_PRESS:
|
||||||
|
t = MOO_TEXT_SELECT_CHARS;
|
||||||
|
break;
|
||||||
|
case GDK_2BUTTON_PRESS:
|
||||||
|
t = MOO_TEXT_SELECT_WORDS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
t = MOO_TEXT_SELECT_LINES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_impl(extend_selection) (obj, t, &iter, &start))
|
||||||
|
get_impl(select_range) (obj, &start, &iter);
|
||||||
|
else
|
||||||
|
get_impl(select_range) (obj, &iter, &iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this piece is from gtktextview.c */
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
gdk_window_get_pointer (get_impl(get_window) (obj), &x, &y, NULL);
|
||||||
|
|
||||||
|
if (gtk_drag_check_threshold (widget,
|
||||||
|
data->drag_start_x,
|
||||||
|
data->drag_start_y,
|
||||||
|
x, y))
|
||||||
|
{
|
||||||
|
GtkTextIter iter;
|
||||||
|
int buffer_x, buffer_y;
|
||||||
|
|
||||||
|
get_impl(window_to_buffer_coords) (obj,
|
||||||
|
data->drag_start_x,
|
||||||
|
data->drag_start_y,
|
||||||
|
&buffer_x,
|
||||||
|
&buffer_y);
|
||||||
|
|
||||||
|
get_impl(get_iter_at_location) (obj, &iter, buffer_x, buffer_y);
|
||||||
|
|
||||||
|
data->drag_type = MOO_TEXT_DRAG_NONE;
|
||||||
|
get_impl(start_selection_dnd) (obj, &iter, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void start_drag_scroll (MooText *obj)
|
||||||
|
{
|
||||||
|
MooTextData *data = moo_text_get_data (obj);
|
||||||
|
|
||||||
|
if (!data->drag_scroll_timeout)
|
||||||
|
data->drag_scroll_timeout =
|
||||||
|
g_timeout_add (SCROLL_TIMEOUT,
|
||||||
|
(GSourceFunc)drag_scroll_timeout_func,
|
||||||
|
obj);
|
||||||
|
|
||||||
|
drag_scroll_timeout_func (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void stop_drag_scroll (MooText *obj)
|
||||||
|
{
|
||||||
|
MooTextData *data = moo_text_get_data (obj);
|
||||||
|
|
||||||
|
if (data->drag_scroll_timeout)
|
||||||
|
g_source_remove (data->drag_scroll_timeout);
|
||||||
|
|
||||||
|
data->drag_scroll_timeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean drag_scroll_timeout_func (MooText *obj)
|
||||||
|
{
|
||||||
|
int x, y, px, py;
|
||||||
|
GtkTextIter iter;
|
||||||
|
GtkTextIter start;
|
||||||
|
MooTextSelectionType t;
|
||||||
|
MooTextData *data = moo_text_get_data (obj);
|
||||||
|
|
||||||
|
g_assert (data->drag_type == MOO_TEXT_DRAG_SELECT);
|
||||||
|
|
||||||
|
gdk_window_get_pointer (get_impl(get_window) (obj), &px, &py, NULL);
|
||||||
|
get_impl(window_to_buffer_coords) (obj, px, py, &x, &y);
|
||||||
|
get_impl(get_iter_at_location) (obj, &iter, x, y);
|
||||||
|
|
||||||
|
get_impl(get_iter_at_location) (obj, &start,
|
||||||
|
data->drag_start_x,
|
||||||
|
data->drag_start_y);
|
||||||
|
|
||||||
|
switch (data->drag_button)
|
||||||
|
{
|
||||||
|
case GDK_BUTTON_PRESS:
|
||||||
|
t = MOO_TEXT_SELECT_CHARS;
|
||||||
|
break;
|
||||||
|
case GDK_2BUTTON_PRESS:
|
||||||
|
t = MOO_TEXT_SELECT_WORDS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
t = MOO_TEXT_SELECT_LINES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_impl(extend_selection) (obj, t, &iter, &start))
|
||||||
|
get_impl(select_range) (obj, &start, &iter);
|
||||||
|
else
|
||||||
|
get_impl(select_range) (obj, &iter, &iter);
|
||||||
|
|
||||||
|
get_impl(scroll_selection_end_onscreen) (obj);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* GInterface stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void moo_text_iface_init (gpointer g_iface);
|
||||||
|
|
||||||
|
|
||||||
|
GType moo_text_get_type (void)
|
||||||
|
{
|
||||||
|
static GType type = 0;
|
||||||
|
|
||||||
|
if (!type)
|
||||||
|
{
|
||||||
|
static const GTypeInfo info =
|
||||||
|
{
|
||||||
|
sizeof (MooTextIface), /* class_size */
|
||||||
|
moo_text_iface_init, /* base_init */
|
||||||
|
NULL, /* base_finalize */
|
||||||
|
NULL, /* class_init */
|
||||||
|
0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
type = g_type_register_static (G_TYPE_INTERFACE,
|
||||||
|
"MooText",
|
||||||
|
&info, (GTypeFlags)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void moo_text_iface_init (G_GNUC_UNUSED gpointer g_iface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const GQuark *get_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark q[1] = {0};
|
||||||
|
|
||||||
|
if (!q[0])
|
||||||
|
{
|
||||||
|
q[0] = g_quark_from_static_string ("moo_text_data");
|
||||||
|
}
|
||||||
|
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static MooTextData *moo_text_get_data (MooText *obj)
|
||||||
|
{
|
||||||
|
MooTextData *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MOO_IS_TEXT (obj), NULL);
|
||||||
|
|
||||||
|
data = g_object_get_qdata (G_OBJECT (obj), MOO_TEXT_DATA_QUARK);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
data = moo_text_data_new ();
|
||||||
|
g_object_set_qdata_full (G_OBJECT (obj),
|
||||||
|
MOO_TEXT_DATA_QUARK,
|
||||||
|
data,
|
||||||
|
(GDestroyNotify) moo_text_data_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* GInterface stuff
|
||||||
|
*/
|
||||||
|
|
101
moo/mooui/mootext.h
Normal file
101
moo/mooui/mootext.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* mooui/mootext.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* See COPYING file that comes with this distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOOUI_MOOTEXT_H
|
||||||
|
#define MOOUI_MOOTEXT_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#define MOO_TYPE_TEXT (moo_text_get_type ())
|
||||||
|
#define MOO_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOO_TYPE_TEXT, MooText))
|
||||||
|
#define MOO_IS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOO_TYPE_TEXT))
|
||||||
|
#define MOO_TEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MOO_TYPE_TEXT, MooTextIface))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _MooText MooText;
|
||||||
|
typedef struct _MooTextIface MooTextIface;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MOO_TEXT_DRAG_NONE = 0,
|
||||||
|
MOO_TEXT_DRAG_SELECT,
|
||||||
|
MOO_TEXT_DRAG_DRAG
|
||||||
|
} MooTextDragType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MOO_TEXT_SELECT_CHARS,
|
||||||
|
MOO_TEXT_SELECT_WORDS,
|
||||||
|
MOO_TEXT_SELECT_LINES
|
||||||
|
} MooTextSelectionType;
|
||||||
|
|
||||||
|
struct _MooTextIface {
|
||||||
|
GTypeInterface parent;
|
||||||
|
|
||||||
|
void (*middle_button_click) (MooText *obj,
|
||||||
|
GdkEventButton *event);
|
||||||
|
void (*right_button_click) (MooText *obj,
|
||||||
|
GdkEventButton *event);
|
||||||
|
|
||||||
|
void (*start_selection_dnd) (MooText *obj,
|
||||||
|
const GtkTextIter *iter,
|
||||||
|
GdkEventMotion *event);
|
||||||
|
|
||||||
|
gboolean (*extend_selection) (MooText *obj,
|
||||||
|
MooTextSelectionType type,
|
||||||
|
GtkTextIter *insert,
|
||||||
|
GtkTextIter *selection_bound);
|
||||||
|
void (*window_to_buffer_coords) (MooText *obj,
|
||||||
|
int window_x,
|
||||||
|
int window_y,
|
||||||
|
int *buffer_x,
|
||||||
|
int *buffer_y);
|
||||||
|
void (*get_iter_at_location) (MooText *obj,
|
||||||
|
GtkTextIter *iter,
|
||||||
|
int x,
|
||||||
|
int y);
|
||||||
|
gboolean (*get_selection_bounds) (MooText *obj,
|
||||||
|
GtkTextIter *sel_start,
|
||||||
|
GtkTextIter *sel_end);
|
||||||
|
void (*iter_order) (GtkTextIter *first,
|
||||||
|
GtkTextIter *second);
|
||||||
|
gboolean (*iter_in_range) (const GtkTextIter *iter,
|
||||||
|
const GtkTextIter *start,
|
||||||
|
const GtkTextIter *end);
|
||||||
|
void (*place_selection_end) (MooText *obj,
|
||||||
|
const GtkTextIter *where);
|
||||||
|
void (*select_range) (MooText *obj,
|
||||||
|
const GtkTextIter *start,
|
||||||
|
const GtkTextIter *end);
|
||||||
|
void (*scroll_selection_end_onscreen) (MooText *obj);
|
||||||
|
|
||||||
|
GdkWindow* (*get_window) (MooText *obj);
|
||||||
|
void (*get_visible_rect) (MooText *obj,
|
||||||
|
GdkRectangle *rect);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GType moo_text_get_type (void);
|
||||||
|
|
||||||
|
gboolean moo_text_button_press_event (GtkWidget *widget,
|
||||||
|
GdkEventButton *event);
|
||||||
|
gboolean moo_text_button_release_event (GtkWidget *widget,
|
||||||
|
GdkEventButton *event);
|
||||||
|
gboolean moo_text_motion_event (GtkWidget *widget,
|
||||||
|
GdkEventMotion *event);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* MOOUI_MOOTEXT_H */
|
@ -108,7 +108,7 @@ static guint signals[LAST_SIGNAL] = {0};
|
|||||||
|
|
||||||
/* MOO_TYPE_WINDOW */
|
/* MOO_TYPE_WINDOW */
|
||||||
static gpointer moo_window_parent_class = NULL;
|
static gpointer moo_window_parent_class = NULL;
|
||||||
GType moo_window_get_type ()
|
GType moo_window_get_type (void)
|
||||||
{
|
{
|
||||||
static GType type = 0;
|
static GType type = 0;
|
||||||
if (!type)
|
if (!type)
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
</ignoreparts>
|
</ignoreparts>
|
||||||
<projectdirectory>.</projectdirectory>
|
<projectdirectory>.</projectdirectory>
|
||||||
<absoluteprojectpath>false</absoluteprojectpath>
|
<absoluteprojectpath>false</absoluteprojectpath>
|
||||||
<description></description>
|
<description/>
|
||||||
<secondaryLanguages>
|
<secondaryLanguages>
|
||||||
<language>C</language>
|
<language>C</language>
|
||||||
</secondaryLanguages>
|
</secondaryLanguages>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
<mainprogram>tests/mterm</mainprogram>
|
<mainprogram>tests/mterm</mainprogram>
|
||||||
<directoryradio>executable</directoryradio>
|
<directoryradio>executable</directoryradio>
|
||||||
<customdirectory>/</customdirectory>
|
<customdirectory>/</customdirectory>
|
||||||
<programargs></programargs>
|
<programargs/>
|
||||||
<terminal>false</terminal>
|
<terminal>false</terminal>
|
||||||
<autocompile>true</autocompile>
|
<autocompile>true</autocompile>
|
||||||
<envvars/>
|
<envvars/>
|
||||||
@ -141,7 +141,7 @@
|
|||||||
<abortonerror>true</abortonerror>
|
<abortonerror>true</abortonerror>
|
||||||
<numberofjobs>1</numberofjobs>
|
<numberofjobs>1</numberofjobs>
|
||||||
<dontact>false</dontact>
|
<dontact>false</dontact>
|
||||||
<makebin></makebin>
|
<makebin/>
|
||||||
<prio>0</prio>
|
<prio>0</prio>
|
||||||
</make>
|
</make>
|
||||||
</kdevautoproject>
|
</kdevautoproject>
|
||||||
@ -149,10 +149,10 @@
|
|||||||
<general>
|
<general>
|
||||||
<dbgshell>libtool</dbgshell>
|
<dbgshell>libtool</dbgshell>
|
||||||
<programargs>--g-fatal-warnings bash</programargs>
|
<programargs>--g-fatal-warnings bash</programargs>
|
||||||
<gdbpath></gdbpath>
|
<gdbpath/>
|
||||||
<configGdbScript></configGdbScript>
|
<configGdbScript/>
|
||||||
<runShellScript></runShellScript>
|
<runShellScript/>
|
||||||
<runGdbScript></runGdbScript>
|
<runGdbScript/>
|
||||||
<breakonloadinglibs>true</breakonloadinglibs>
|
<breakonloadinglibs>true</breakonloadinglibs>
|
||||||
<separatetty>false</separatetty>
|
<separatetty>false</separatetty>
|
||||||
<floatingtoolbar>true</floatingtoolbar>
|
<floatingtoolbar>true</floatingtoolbar>
|
||||||
@ -253,7 +253,7 @@
|
|||||||
</codecompletion>
|
</codecompletion>
|
||||||
<references/>
|
<references/>
|
||||||
<creategettersetter>
|
<creategettersetter>
|
||||||
<prefixGet></prefixGet>
|
<prefixGet/>
|
||||||
<prefixSet>set</prefixSet>
|
<prefixSet>set</prefixSet>
|
||||||
<prefixVariable>m_,_</prefixVariable>
|
<prefixVariable>m_,_</prefixVariable>
|
||||||
<parameterName>theValue</parameterName>
|
<parameterName>theValue</parameterName>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user