Making drawing like vte's

master
Yevgen Muntyan 2006-06-09 14:28:17 -05:00
parent bc4bf98bf4
commit 510eff37ce
10 changed files with 569 additions and 1604 deletions

View File

@ -31,6 +31,9 @@
#define HOW_MANY(x__,y__) (((x__) + (y__) - 1) / (y__))
static void add_update_timeout (MooTerm *term);
static void
font_calculate (MooTermFont *font)
{
@ -147,7 +150,7 @@ _moo_term_font_free (MooTermFont *font)
void
_moo_term_invalidate (MooTerm *term)
_moo_term_invalidate (MooTerm *term)
{
GdkRectangle rec = {0, 0, term->priv->width, term->priv->height};
_moo_term_invalidate_screen_rect (term, &rec);
@ -385,6 +388,7 @@ _moo_term_cursor_moved (MooTerm *term,
{
term->priv->cursor_row = buf_cursor_row (buf);
term->priv->cursor_col = buf_cursor_col_display (buf);
add_update_timeout (term);
}
}
@ -434,14 +438,14 @@ moo_term_draw (MooTerm *term,
int width = term->priv->width;
int height = term->priv->height;
GdkRectangle clip = {0, 0, width, height};
GdkRegion *screen_region = NULL;
// GdkRegion *screen_region = NULL;
g_return_if_fail (region != NULL);
gdk_region_get_rectangles (region, &rects, &n_rects);
if (term->priv->changed)
screen_region = gdk_region_new ();
// if (term->priv->changed)
// screen_region = gdk_region_new ();
for (i = 0; i < n_rects; ++i)
{
@ -455,22 +459,22 @@ moo_term_draw (MooTerm *term,
term_draw_range (term, drawable,
top_line + r->y + j,
r->x, r->width);
if (screen_region)
gdk_region_union_with_rect (screen_region, r);
//
// if (screen_region)
// gdk_region_union_with_rect (screen_region, r);
}
}
if (term->priv->changed && !gdk_region_empty (screen_region))
{
gdk_region_subtract (term->priv->changed,
screen_region);
if (gdk_region_empty (term->priv->changed))
region_destroy (&term->priv->changed);
}
// if (term->priv->changed && !gdk_region_empty (screen_region))
// {
// gdk_region_subtract (term->priv->changed,
// screen_region);
// if (gdk_region_empty (term->priv->changed))
// region_destroy (&term->priv->changed);
// }
if (screen_region)
gdk_region_destroy (screen_region);
// if (screen_region)
// gdk_region_destroy (screen_region);
g_free (rects);
}
@ -501,107 +505,110 @@ region_union_with_rect (GdkRegion **region,
}
static gboolean
update_timeout (MooTerm *term)
{
GdkRegion *region, *changed, *clip_region;
GdkRectangle *rectangles;
int n_rectangles, i;
int top_line = term_top_line (term);
int scrollback = buf_scrollback (term->priv->buffer);
GdkWindow *window = GTK_WIDGET(term)->window;
gboolean need_redraw = FALSE;
GdkRectangle clip = {0, 0, term->priv->width, term->priv->height};
if (!GTK_WIDGET_DRAWABLE (term))
return TRUE;
gdk_window_freeze_updates (window);
if (!term->priv->changed &&
term->priv->cursor_col == term->priv->cursor_col_old &&
term->priv->cursor_row == term->priv->cursor_row_old)
goto out;
if (term->priv->changed)
{
changed = term->priv->changed;
term->priv->changed = NULL;
}
else
{
changed = gdk_region_new ();
}
if (term->priv->cursor_col != term->priv->cursor_col_old ||
term->priv->cursor_row != term->priv->cursor_row_old)
{
int row;
row = scrollback + term->priv->cursor_row - top_line;
if (term->priv->cursor_col < term->priv->width &&
row >= 0 && row < (int) term->priv->height)
{
GdkRectangle rect = {term->priv->cursor_col, row, 1, 1};
gdk_region_union_with_rect (changed, &rect);
}
row = scrollback + term->priv->cursor_row_old - top_line;
if (term->priv->cursor_col_old < term->priv->width &&
row >= 0 && row < (int) term->priv->height)
{
GdkRectangle rect = {term->priv->cursor_col_old, row, 1, 1};
gdk_region_union_with_rect (changed, &rect);
}
}
clip_region = gdk_region_rectangle (&clip);
gdk_region_intersect (changed, clip_region);
gdk_region_destroy (clip_region);
if (gdk_region_empty (changed))
{
gdk_region_destroy (changed);
goto out;
}
gdk_region_get_rectangles (changed, &rectangles, &n_rectangles);
g_return_val_if_fail (n_rectangles > 0, TRUE);
for (i = 0; i < n_rectangles; ++i)
{
rect_screen_to_window (term, &rectangles[i], &rectangles[i]);
}
region = gdk_region_rectangle (&rectangles[0]);
for (i = 1; i < n_rectangles; ++i)
gdk_region_union_with_rect (region, &rectangles[i]);
gdk_window_invalidate_region (window, region, FALSE);
need_redraw = TRUE;
g_free (rectangles);
gdk_region_destroy (region);
gdk_region_destroy (changed);
out:
term->priv->cursor_col_old = term->priv->cursor_col;
term->priv->cursor_row_old = term->priv->cursor_row;
gdk_window_thaw_updates (window);
if (need_redraw)
{
if (g_timer_elapsed (term->priv->redraw_timer, NULL) > REDRAW_INTERVAL)
gdk_window_process_updates (GTK_WIDGET(term)->window, FALSE);
}
else
{
g_timer_start (term->priv->redraw_timer);
}
return TRUE;
}
// static gboolean
// update_timeout (MooTerm *term)
// {
// GdkRegion *region, *changed, *clip_region;
// GdkRectangle *rectangles;
// int n_rectangles, i;
// int top_line = term_top_line (term);
// int scrollback = buf_scrollback (term->priv->buffer);
// GdkWindow *window = GTK_WIDGET(term)->window;
// gboolean need_redraw = FALSE;
// GdkRectangle clip = {0, 0, term->priv->width, term->priv->height};
//
// if (!GTK_WIDGET_DRAWABLE (term))
// return TRUE;
//
// gdk_window_freeze_updates (window);
//
// if (!term->priv->changed &&
// term->priv->cursor_col == term->priv->cursor_col_old &&
// term->priv->cursor_row == term->priv->cursor_row_old)
// goto out;
//
// if (term->priv->changed)
// {
// changed = term->priv->changed;
// term->priv->changed = NULL;
// }
// else
// {
// changed = gdk_region_new ();
// }
//
// if (term->priv->cursor_col != term->priv->cursor_col_old ||
// term->priv->cursor_row != term->priv->cursor_row_old)
// {
// int row;
//
// row = scrollback + term->priv->cursor_row - top_line;
// if (term->priv->cursor_col < term->priv->width &&
// row >= 0 && row < (int) term->priv->height)
// {
// GdkRectangle rect = {term->priv->cursor_col, row, 1, 1};
// gdk_region_union_with_rect (changed, &rect);
// }
//
// row = scrollback + term->priv->cursor_row_old - top_line;
// if (term->priv->cursor_col_old < term->priv->width &&
// row >= 0 && row < (int) term->priv->height)
// {
// GdkRectangle rect = {term->priv->cursor_col_old, row, 1, 1};
// gdk_region_union_with_rect (changed, &rect);
// }
// }
//
// clip_region = gdk_region_rectangle (&clip);
// gdk_region_intersect (changed, clip_region);
// gdk_region_destroy (clip_region);
//
// if (gdk_region_empty (changed))
// {
// gdk_region_destroy (changed);
// goto out;
// }
//
// gdk_region_get_rectangles (changed, &rectangles, &n_rectangles);
// g_return_val_if_fail (n_rectangles > 0, TRUE);
//
// for (i = 0; i < n_rectangles; ++i)
// {
// rect_screen_to_window (term, &rectangles[i], &rectangles[i]);
// }
//
// region = gdk_region_rectangle (&rectangles[0]);
//
// for (i = 1; i < n_rectangles; ++i)
// gdk_region_union_with_rect (region, &rectangles[i]);
//
// gdk_window_invalidate_region (window, region, FALSE);
// need_redraw = TRUE;
//
// g_free (rectangles);
// gdk_region_destroy (region);
// gdk_region_destroy (changed);
//
// out:
// term->priv->cursor_col_old = term->priv->cursor_col;
// term->priv->cursor_row_old = term->priv->cursor_row;
// gdk_window_thaw_updates (window);
//
// if (need_redraw)
// {
// if (g_timer_elapsed (term->priv->redraw_timer, NULL) > REDRAW_INTERVAL)
// {
// gdk_window_process_updates (GTK_WIDGET(term)->window, FALSE);
// g_timer_start (term->priv->redraw_timer);
// }
// }
// else
// {
// g_timer_start (term->priv->redraw_timer);
// }
//
// return TRUE;
// }
gboolean
@ -612,12 +619,10 @@ _moo_term_expose_event (GtkWidget *widget,
GdkRegion *text_region;
MooTerm *term = MOO_TERM (widget);
g_assert (term_top_line (term) <= buf_scrollback (term->priv->buffer));
if (widget->window != event->window)
return FALSE;
if (!term->priv->update_timeout)
term->priv->update_timeout =
g_timeout_add_full (UPDATE_PRIORITY, UPDATE_TIMEOUT,
(GSourceFunc) update_timeout, term, NULL);
g_assert (term_top_line (term) <= buf_scrollback (term->priv->buffer));
text_rec.width = PIXEL_WIDTH (term);
text_rec.height = PIXEL_HEIGHT (term);
@ -627,10 +632,8 @@ _moo_term_expose_event (GtkWidget *widget,
if (!gdk_region_empty (text_region))
moo_term_draw (term, event->window, text_region);
g_timer_start (term->priv->redraw_timer);
gdk_region_destroy (text_region);
return TRUE;
return FALSE;
}
@ -1002,20 +1005,21 @@ term_draw_cursor (MooTerm *term,
}
void
_moo_term_buf_content_changed (MooTerm *term,
MooTermBuffer *buf)
static void
add_buffer_changed (MooTerm *term)
{
GdkRegion *changed;
guint top_line, scrollback;
int height;
MooTermBuffer *buf;
if (!GTK_WIDGET_DRAWABLE (term))
return;
buf = term->priv->buffer;
changed = buf->priv->changed;
if (buf != term->priv->buffer || !changed || gdk_region_empty (changed))
if (!changed || gdk_region_empty (changed))
return;
buf->priv->changed = NULL;
@ -1056,6 +1060,151 @@ _moo_term_buf_content_changed (MooTerm *term,
}
static gboolean
invalidate_window (MooTerm *term)
{
GdkRegion *region, *changed, *clip_region;
GdkRectangle *rectangles;
int n_rectangles, i;
int top_line = term_top_line (term);
int scrollback = buf_scrollback (term->priv->buffer);
GdkWindow *window = GTK_WIDGET(term)->window;
gboolean need_redraw = FALSE;
GdkRectangle clip = {0, 0, term->priv->width, term->priv->height};
if (!GTK_WIDGET_DRAWABLE (term))
return FALSE;
add_buffer_changed (term);
if (!term->priv->changed &&
term->priv->cursor_col == term->priv->cursor_col_old &&
term->priv->cursor_row == term->priv->cursor_row_old)
goto out;
if (term->priv->changed)
{
changed = term->priv->changed;
term->priv->changed = NULL;
}
else
{
changed = gdk_region_new ();
}
if (term->priv->cursor_col != term->priv->cursor_col_old ||
term->priv->cursor_row != term->priv->cursor_row_old)
{
int row;
row = scrollback + term->priv->cursor_row - top_line;
if (term->priv->cursor_col < term->priv->width &&
row >= 0 && row < (int) term->priv->height)
{
GdkRectangle rect = {term->priv->cursor_col, row, 1, 1};
gdk_region_union_with_rect (changed, &rect);
}
row = scrollback + term->priv->cursor_row_old - top_line;
if (term->priv->cursor_col_old < term->priv->width &&
row >= 0 && row < (int) term->priv->height)
{
GdkRectangle rect = {term->priv->cursor_col_old, row, 1, 1};
gdk_region_union_with_rect (changed, &rect);
}
}
clip_region = gdk_region_rectangle (&clip);
gdk_region_intersect (changed, clip_region);
gdk_region_destroy (clip_region);
if (gdk_region_empty (changed))
{
gdk_region_destroy (changed);
goto out;
}
gdk_region_get_rectangles (changed, &rectangles, &n_rectangles);
g_return_val_if_fail (n_rectangles > 0, TRUE);
for (i = 0; i < n_rectangles; ++i)
{
rect_screen_to_window (term, &rectangles[i], &rectangles[i]);
}
region = gdk_region_rectangle (&rectangles[0]);
for (i = 1; i < n_rectangles; ++i)
gdk_region_union_with_rect (region, &rectangles[i]);
gdk_window_invalidate_region (window, region, FALSE);
need_redraw = TRUE;
g_free (rectangles);
gdk_region_destroy (region);
gdk_region_destroy (changed);
out:
term->priv->cursor_col_old = term->priv->cursor_col;
term->priv->cursor_row_old = term->priv->cursor_row;
return need_redraw;
}
static gboolean
update_delay_timeout (MooTerm *term)
{
/* We only stop the timer if no update request was received in this
* past cycle.
*/
if (invalidate_window (term))
return TRUE;
term->priv->update_timer = 0;
return FALSE;
}
static gboolean
update_timeout (MooTerm *term)
{
invalidate_window (term);
/* Set a timer such that we do not invalidate for a while. */
/* This limits the number of times we draw to ~40fps. */
term->priv->update_timer =
g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
UPDATE_REPEAT_TIMEOUT,
(GSourceFunc) update_delay_timeout,
term, NULL);
return FALSE;
}
static void
add_update_timeout (MooTerm *term)
{
if (!term->priv->update_timer)
term->priv->update_timer =
g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
UPDATE_TIMEOUT,
(GSourceFunc) update_timeout,
term, NULL);
}
void
_moo_term_buf_content_changed (MooTerm *term,
MooTermBuffer *buf)
{
if (GTK_WIDGET_DRAWABLE (term) &&
buf == term->priv->buffer &&
buf->priv->changed &&
!gdk_region_empty (buf->priv->changed))
{
add_update_timeout (term);
}
}
void
_moo_term_buffer_scrolled (MooTermBuffer *buf,
guint lines,
@ -1065,6 +1214,7 @@ _moo_term_buffer_scrolled (MooTermBuffer *buf,
{
GdkRectangle rect = {0, 0, term->priv->width, term->priv->height};
region_union_with_rect (&term->priv->changed, &rect);
add_update_timeout (term);
}
}

View File

@ -38,11 +38,13 @@ G_BEGIN_DECLS
#define PT_WRITER_PRIORITY G_PRIORITY_DEFAULT
#define PT_READER_PRIORITY G_PRIORITY_DEFAULT
#define ADJUSTMENT_PRIORITY G_PRIORITY_HIGH_IDLE
#define ADJUSTMENT_PRIORITY G_PRIORITY_DEFAULT_IDLE
#define ADJUSTMENT_DELTA 30.0
#define UPDATE_PRIORITY G_PRIORITY_DEFAULT
#define UPDATE_TIMEOUT 30
#define REDRAW_INTERVAL 0.6
#define UPDATE_TIMEOUT 10
#define UPDATE_REPEAT_TIMEOUT 40
#define PROCESS_INCOMING_TIMEOUT 10
#define INPUT_CHUNK_SIZE 4096
#define MIN_TERMINAL_WIDTH 8
#define MIN_TERMINAL_HEIGHT 4
@ -81,6 +83,8 @@ typedef struct _MooTermFont MooTermFont;
struct _MooTermPrivate {
struct _MooTermPt *pt;
struct _MooTermParser *parser;
GString *incoming;
guint process_timeout;
struct _MooTermBuffer *buffer;
struct _MooTermBuffer *primary_buffer;
@ -115,10 +119,9 @@ struct _MooTermPrivate {
MooTermFont *font;
GdkRegion *changed; /* screen coordinates */
guint update_timeout;
GTimer *redraw_timer;
guint cursor_row_old; /* cursor has been here, and it's been invalidated */
guint cursor_col_old;
guint update_timer;
GdkGC *clip;
gboolean font_changed;
@ -242,6 +245,8 @@ void _moo_term_pause_cursor_blinking (MooTerm *term);
void _moo_term_set_cursor_blinks (MooTerm *term,
gboolean blinks);
gsize _moo_term_get_input_chunk_len (MooTerm *term);
/*************************************************************************/
/* vt commands

View File

@ -205,7 +205,8 @@ static int segment_sym_diff (Segment *s1, Segment *s2,
}
static void invalidate_segment (Segment *segm, guint num)
static void
invalidate_segment (Segment *segm, guint num)
{
MooTerm *term;
int top_line;
@ -223,7 +224,7 @@ static void invalidate_segment (Segment *segm, guint num)
MooTermIter end = segm[i].end;
GdkRectangle rect;
_moo_term_iter_order (&start, &end);
_moo_term_iter_order (&start, &end);
if (ITER_ROW (&start) < ITER_ROW (&end))
{

View File

@ -257,7 +257,7 @@ moo_term_init (MooTerm *term)
term->priv->pt = _moo_term_pt_new (term);
g_signal_connect_swapped (term->priv->pt, "child-died",
G_CALLBACK (child_died), term);
term->priv->incoming = g_string_new_len (NULL, INPUT_CHUNK_SIZE);
term->priv->parser = _moo_term_parser_new (term);
_moo_term_init_palette (term);
@ -271,9 +271,6 @@ moo_term_init (MooTerm *term)
term->priv->width = 80;
term->priv->height = 24;
term->priv->redraw_timer = g_timer_new ();
g_timer_stop (term->priv->redraw_timer);
term->priv->selection = _moo_term_selection_new (term);
term->priv->cursor_visible = TRUE;
@ -360,11 +357,16 @@ moo_term_init (MooTerm *term)
#define OBJECT_UNREF(obj__) if (obj__) g_object_unref (obj__)
static void moo_term_finalize (GObject *object)
static void
moo_term_finalize (GObject *object)
{
guint i, j;
MooTerm *term = MOO_TERM (object);
if (term->priv->process_timeout)
g_source_remove (term->priv->process_timeout);
g_string_free (term->priv->incoming, TRUE);
if (term->priv->cursor_blink_timeout_id)
g_source_remove (term->priv->cursor_blink_timeout_id);
@ -382,8 +384,6 @@ static void moo_term_finalize (GObject *object)
if (term->priv->changed)
gdk_region_destroy (term->priv->changed);
g_timer_destroy (term->priv->redraw_timer);
OBJECT_UNREF (term->priv->layout);
OBJECT_UNREF (term->priv->im);
@ -557,9 +557,9 @@ moo_term_unrealize (GtkWidget *widget)
guint i;
MooTerm *term = MOO_TERM (widget);
if (term->priv->update_timeout)
g_source_remove (term->priv->update_timeout);
term->priv->update_timeout = 0;
if (term->priv->update_timer)
g_source_remove (term->priv->update_timer);
term->priv->update_timer = 0;
if (term->priv->menu)
g_object_unref (term->priv->menu);
@ -682,7 +682,7 @@ static void buf_size_changed (MooTerm *term,
}
#define equal(a, b) (ABS((a)-(b)) < 0.4)
#define EQUAL(a, b) (ABS((a)-(b)) < 0.4)
static void update_adjustment (MooTerm *term)
{
@ -697,17 +697,12 @@ static void update_adjustment (MooTerm *term)
value = term_top_line (term);
page_size = term->priv->height;
if ((ABS (upper - term->priv->adjustment->upper) >
ADJUSTMENT_DELTA * page_size) ||
(ABS (value - term->priv->adjustment->value) >
ADJUSTMENT_DELTA * page_size))
{
now = TRUE;
}
now = ABS (upper - term->priv->adjustment->upper) > ADJUSTMENT_DELTA * page_size ||
ABS (value - term->priv->adjustment->value) > ADJUSTMENT_DELTA * page_size;
if (!equal (adj->lower, 0.0) || !equal (adj->upper, upper) ||
!equal (adj->value, value) || !equal (adj->page_size, page_size) ||
!equal (adj->page_increment, page_size) || !equal (adj->step_increment, 1.0))
if (!EQUAL (adj->lower, 0.0) || !EQUAL (adj->upper, upper) ||
!EQUAL (adj->value, value) || !EQUAL (adj->page_size, page_size) ||
!EQUAL (adj->page_increment, page_size) || !EQUAL (adj->step_increment, 1.0))
{
adj->lower = 0.0;
adj->upper = upper;
@ -729,19 +724,18 @@ static void update_adjustment_value (MooTerm *term)
if (!term->priv->adjustment)
return;
if (ABS (value - term->priv->adjustment->value) >
ADJUSTMENT_DELTA * term->priv->height)
{
now = TRUE;
}
now = ABS (value - term->priv->adjustment->value) >
ADJUSTMENT_DELTA * term->priv->height;
if (!equal (term->priv->adjustment->value, value))
if (!EQUAL (term->priv->adjustment->value, value))
{
term->priv->adjustment->value = value;
queue_adjustment_value_changed (term, now);
}
}
#undef EQUAL
static void adjustment_value_changed (MooTerm *term)
{
@ -761,8 +755,9 @@ static void adjustment_value_changed (MooTerm *term)
}
static void queue_adjustment_changed (MooTerm *term,
gboolean now)
static void
queue_adjustment_changed (MooTerm *term,
gboolean now)
{
if (now)
{
@ -1070,10 +1065,45 @@ moo_term_paste_clipboard (MooTerm *term,
}
static gboolean
process_incoming (MooTerm *term)
{
gboolean done;
// if (term->priv->incoming->len > 2*INPUT_CHUNK_SIZE)
// g_print ("process_incoming: %d chars\n",
// term->priv->incoming->len);
done = !term->priv->incoming->len ||
_moo_term_parser_parse (term->priv->parser,
term->priv->incoming->str,
term->priv->incoming->len);
if (term->priv->incoming->len > INPUT_CHUNK_SIZE)
{
g_string_free (term->priv->incoming, TRUE);
term->priv->incoming = g_string_new_len (NULL, INPUT_CHUNK_SIZE);
}
else
{
g_string_truncate (term->priv->incoming, 0);
}
term->priv->process_timeout = 0;
if (!done)
term->priv->process_timeout =
g_timeout_add (PROCESS_INCOMING_TIMEOUT,
(GSourceFunc) process_incoming,
term);
return FALSE;
}
void
moo_term_feed (MooTerm *term,
const char *data,
int len)
moo_term_feed (MooTerm *term,
const char *data,
int len)
{
if (!len)
return;
@ -1083,7 +1113,29 @@ moo_term_feed (MooTerm *term,
if (len < 0)
len = strlen (data);
_moo_term_parser_parse (term->priv->parser, data, len);
// g_print ("moo_term_feed: %d chars\n", len);
g_string_append_len (term->priv->incoming, data, len);
if (!term->priv->process_timeout)
term->priv->process_timeout =
g_timeout_add (PROCESS_INCOMING_TIMEOUT,
(GSourceFunc) process_incoming,
term);
}
gsize
_moo_term_get_input_chunk_len (MooTerm *term)
{
switch (term->priv->incoming->len / INPUT_CHUNK_SIZE)
{
case 0:
return INPUT_CHUNK_SIZE - term->priv->incoming->len;
case 1:
return INPUT_CHUNK_SIZE / 2;
default:
return 0;
}
}

View File

@ -584,16 +584,18 @@ _moo_term_buffer_cursor_move (MooTermBuffer *buf,
}
void _moo_term_buffer_cursor_moved (MooTermBuffer *buf)
void
_moo_term_buffer_cursor_moved (MooTermBuffer *buf)
{
if (!buf->priv->freeze_cursor_notify)
g_signal_emit (buf, signals[CURSOR_MOVED], 0);
}
void _moo_term_buffer_cursor_move_to (MooTermBuffer *buf,
int row,
int col)
void
_moo_term_buffer_cursor_move_to (MooTermBuffer *buf,
int row,
int col)
{
int width = buf_screen_width (buf);
int height = buf_screen_height (buf);

View File

@ -60,7 +60,8 @@ static void exec_dcs (MooTermParser *parser);
#define iter_free g_free
static InputIter *iter_new (MooTermParser *parser)
static InputIter *
iter_new (MooTermParser *parser)
{
InputIter *iter = g_new (InputIter, 1);
@ -72,14 +73,16 @@ static InputIter *iter_new (MooTermParser *parser)
}
static gboolean iter_eof (InputIter *iter)
static gboolean
iter_eof (InputIter *iter)
{
return !iter->old && iter->offset >=
iter->parser->input.data_len;
}
static void iter_forward (InputIter *iter)
static void
iter_forward (InputIter *iter)
{
g_assert (!iter_eof (iter));
@ -97,7 +100,8 @@ static void iter_forward (InputIter *iter)
}
static void iter_backward (InputIter *iter)
static void
iter_backward (InputIter *iter)
{
g_assert (iter->offset ||
(!iter->old && iter->parser->input.old_data->len));
@ -115,14 +119,16 @@ static void iter_backward (InputIter *iter)
}
static void iter_set_eof (InputIter *iter)
static void
iter_set_eof (InputIter *iter)
{
iter->old = FALSE;
iter->offset = iter->parser->input.data_len;
}
static guchar iter_get_char (InputIter *iter)
static guchar
iter_get_char (InputIter *iter)
{
g_assert (!iter_eof (iter));
@ -133,7 +139,8 @@ static guchar iter_get_char (InputIter *iter)
}
static void save_cmd (MooTermParser *parser)
static void
save_cmd (MooTermParser *parser)
{
GString *old = parser->input.old_data;
guint offset = parser->cmd_start->offset;
@ -168,7 +175,8 @@ static void save_cmd (MooTermParser *parser)
}
static void save_character (MooTermParser *parser)
static void
save_character (MooTermParser *parser)
{
g_string_truncate (parser->input.old_data, 0);
g_string_append_len (parser->input.old_data,
@ -178,7 +186,9 @@ static void save_character (MooTermParser *parser)
}
static void one_char_cmd (MooTermParser *parser, guchar c)
static void
one_char_cmd (MooTermParser *parser,
guchar c)
{
flush_chars (parser);
DEBUG_ONE_CHAR(c);
@ -276,7 +286,8 @@ static void one_char_cmd (MooTermParser *parser, guchar c)
/* returns 0 on end of input */
static guchar get_char (MooTermParser *parser)
static guchar
get_char (MooTermParser *parser)
{
guchar c = 0;
@ -304,19 +315,22 @@ static guchar get_char (MooTermParser *parser)
}
static void flush_chars (MooTermParser *parser)
static void
flush_chars (MooTermParser *parser)
{
if (parser->character->len)
{
g_warning ("%s: invalid UTF8 '%s'", G_STRLOC,
parser->character->str);
// g_warning ("%s: invalid UTF8 '%s'", G_STRLOC,
// parser->character->str);
VT_PRINT_CHAR (ERROR_CHAR);
g_string_truncate (parser->character, 0);
}
}
static void process_char (MooTermParser *parser, guchar c)
static void
process_char (MooTermParser *parser,
guchar c)
{
if (parser->character->len || c >= 128)
{
@ -333,8 +347,8 @@ static void process_char (MooTermParser *parser, guchar c)
break;
case -1:
g_warning ("%s: invalid UTF8 '%s'", G_STRLOC,
parser->character->str);
// g_warning ("%s: invalid UTF8 '%s'", G_STRLOC,
// parser->character->str);
VT_PRINT_CHAR (ERROR_CHAR);
g_string_truncate (parser->character, 0);
break;
@ -352,7 +366,8 @@ static void process_char (MooTermParser *parser, guchar c)
}
static void parser_init (MooTermParser *parser)
static void
parser_init (MooTermParser *parser)
{
parser->save = FALSE;
@ -377,7 +392,8 @@ static void parser_init (MooTermParser *parser)
}
static void parser_finish (MooTermParser *parser)
static void
parser_finish (MooTermParser *parser)
{
if (!parser->save)
g_string_truncate (parser->input.old_data, 0);
@ -385,7 +401,7 @@ static void parser_finish (MooTermParser *parser)
MooTermParser*
_moo_term_parser_new (MooTerm *term)
_moo_term_parser_new (MooTerm *term)
{
MooTermParser *p = g_new0 (MooTermParser, 1);
@ -437,10 +453,10 @@ _moo_term_parser_free (MooTermParser *parser)
}
void
_moo_term_parser_parse (MooTermParser *parser,
const char *string,
guint len)
static void
parser_do_parse (MooTermParser *parser,
const char *string,
guint len)
{
guchar c;
@ -801,12 +817,27 @@ STATE_DCS_ESCAPE_:
}
gboolean
_moo_term_parser_parse (MooTermParser *parser,
const char *string,
guint len)
{
parser_do_parse (parser, string, len);
// if (parser->save)
// g_print ("saved %d chars\n", parser->input.old_data->len);
return !parser->save;
}
/***************************************************************************/
/* Parsing and executing received command sequence
*/
static void exec_cmd (MooTermParser *parser,
guchar cmd)
static void
exec_cmd (MooTermParser *parser,
guchar cmd)
{
switch (cmd)
{
@ -871,8 +902,9 @@ static void exec_cmd (MooTermParser *parser,
}
static void init_yyparse (MooTermParser *parser,
LexType lex_type)
static void
init_yyparse (MooTermParser *parser,
LexType lex_type)
{
parser->lex.lex = lex_type;
parser->lex.part = PART_START;
@ -882,7 +914,8 @@ static void init_yyparse (MooTermParser *parser,
}
int _moo_term_yylex (MooTermParser *parser)
int
_moo_term_yylex (MooTermParser *parser)
{
guint offset = parser->lex.offset;
@ -1042,7 +1075,8 @@ int _moo_term_yylex (MooTermParser *parser)
}
char *_moo_term_current_ctl (MooTermParser *parser)
char *
_moo_term_current_ctl (MooTermParser *parser)
{
GString *s;
char *nice;
@ -1087,7 +1121,8 @@ char *_moo_term_current_ctl (MooTermParser *parser)
}
static void exec_escape_sequence (MooTermParser *parser)
static void
exec_escape_sequence (MooTermParser *parser)
{
init_yyparse (parser, LEX_ESCAPE);
DEBUG_CONTROL;
@ -1095,7 +1130,8 @@ static void exec_escape_sequence (MooTermParser *parser)
}
static void exec_csi (MooTermParser *parser)
static void
exec_csi (MooTermParser *parser)
{
init_yyparse (parser, LEX_CONTROL);
DEBUG_CONTROL;
@ -1103,7 +1139,8 @@ static void exec_csi (MooTermParser *parser)
}
static void exec_dcs (MooTermParser *parser)
static void
exec_dcs (MooTermParser *parser)
{
init_yyparse (parser, LEX_DCS);
DEBUG_CONTROL;
@ -1111,8 +1148,9 @@ static void exec_dcs (MooTermParser *parser)
}
void _moo_term_yyerror (MooTermParser *parser,
G_GNUC_UNUSED const char *string)
void
_moo_term_yyerror (MooTermParser *parser,
G_GNUC_UNUSED const char *string)
{
char *s = _moo_term_current_ctl (parser);
g_warning ("parse error: '%s'\n", s);
@ -1120,8 +1158,9 @@ void _moo_term_yyerror (MooTermParser *parser,
}
static void exec_apc (MooTermParser *parser,
guchar final)
static void
exec_apc (MooTermParser *parser,
guchar final)
{
char *s = g_strdup_printf ("\237%s%c", parser->data->str, final);
char *nice = _moo_term_nice_bytes (s, -1);
@ -1131,8 +1170,9 @@ static void exec_apc (MooTermParser *parser,
}
static void exec_pm (MooTermParser *parser,
guchar final)
static void
exec_pm (MooTermParser *parser,
guchar final)
{
char *s = g_strdup_printf ("\236%s%c", parser->data->str, final);
char *nice = _moo_term_nice_bytes (s, -1);
@ -1142,8 +1182,9 @@ static void exec_pm (MooTermParser *parser,
}
static void exec_osc (MooTermParser *parser,
guchar final)
static void
exec_osc (MooTermParser *parser,
guchar final)
{
if (parser->data->len >= 2 &&
parser->data->str[0] >= '0' &&
@ -1178,58 +1219,56 @@ static void exec_osc (MooTermParser *parser,
}
char *_moo_term_nice_char (guchar c)
char *
_moo_term_nice_char (guchar c)
{
if (' ' <= c && c <= '~')
{
return g_strndup ((char*)&c, 1);
}
else
switch (c)
{
switch (c)
{
case 0x1B:
return g_strdup ("<ESC>");
case 0x84:
return g_strdup ("<IND>");
case 0x85:
return g_strdup ("<NEL>");
case 0x88:
return g_strdup ("<HTS>");
case 0x8D:
return g_strdup ("<RI>");
case 0x8E:
return g_strdup ("<SS2>");
case 0x8F:
return g_strdup ("<SS3>");
case 0x90:
return g_strdup ("<DCS>");
case 0x98:
return g_strdup ("<SOS>");
case 0x9A:
return g_strdup ("<DECID>");
case 0x9B:
return g_strdup ("<CSI>");
case 0x9C:
return g_strdup ("<ST>");
case 0x9D:
return g_strdup ("<OSC>");
case 0x9E:
return g_strdup ("<PM>");
case 0x9F:
return g_strdup ("<APC>");
default:
if ('A' - 64 <= c && c <= ']' - 64)
return g_strdup_printf ("^%c", c + 64);
else
return g_strdup_printf ("<%d>", c);
}
case 0x1B:
return g_strdup ("<ESC>");
case 0x84:
return g_strdup ("<IND>");
case 0x85:
return g_strdup ("<NEL>");
case 0x88:
return g_strdup ("<HTS>");
case 0x8D:
return g_strdup ("<RI>");
case 0x8E:
return g_strdup ("<SS2>");
case 0x8F:
return g_strdup ("<SS3>");
case 0x90:
return g_strdup ("<DCS>");
case 0x98:
return g_strdup ("<SOS>");
case 0x9A:
return g_strdup ("<DECID>");
case 0x9B:
return g_strdup ("<CSI>");
case 0x9C:
return g_strdup ("<ST>");
case 0x9D:
return g_strdup ("<OSC>");
case 0x9E:
return g_strdup ("<PM>");
case 0x9F:
return g_strdup ("<APC>");
}
if ('A' - 64 <= c && c <= ']' - 64)
return g_strdup_printf ("^%c", c + 64);
else
return g_strdup_printf ("<%d>", c);
}
char *_moo_term_nice_bytes (const char *string,
int len)
char *
_moo_term_nice_bytes (const char *string,
int len)
{
int i;
GString *str;

View File

@ -90,7 +90,7 @@ typedef struct _MooTermParser {
MooTermParser *_moo_term_parser_new (MooTerm *term);
void _moo_term_parser_free (MooTermParser *parser);
void _moo_term_parser_parse (MooTermParser *parser,
gboolean _moo_term_parser_parse (MooTermParser *parser,
const char *string,
guint len);
void _moo_term_parser_reset (MooTermParser *parser);

View File

@ -27,7 +27,6 @@
#define TRY_NUM 10
#define SLEEP_TIME 10
#define TERM_EMULATION "xterm"
#define READ_CHUNK_SIZE 1024
#define WRITE_CHUNK_SIZE 4096
#define POLL_TIME 5
#define POLL_NUM 1
@ -36,7 +35,8 @@ static char *HELPER_DIR = NULL;
#define HELPER_BINARY "termhelper.exe"
void moo_term_set_helper_directory (const char *dir)
void
moo_term_set_helper_directory (const char *dir)
{
g_free (HELPER_DIR);
HELPER_DIR = g_strdup (dir);
@ -193,10 +193,11 @@ fork_command (MooTermPt *pt_gen,
pt->out_io = g_io_channel_win32_new_fd (pt->out);
g_io_channel_set_encoding (pt->out_io, NULL, NULL);
g_io_channel_set_buffered (pt->in_io, FALSE);
pt->out_watch_id = g_io_add_watch (pt->out_io,
(GIOCondition)(G_IO_IN | G_IO_PRI | G_IO_HUP),
(GIOFunc) read_helper_out,
pt);
pt->out_watch_id = g_io_add_watch_full (pt->out_io,
G_PRIORITY_DEFAULT_IDLE,
G_IO_IN | G_IO_PRI | G_IO_HUP,
(GIOFunc) read_helper_out,
pt, NULL);
// GSource *src = g_main_context_find_source_by_id (NULL, helper.out_watch_id);
// if (src) g_source_set_priority (src, READ_HELPER_OUT_PRIORITY);
@ -229,29 +230,31 @@ read_helper_out (GIOChannel *source,
}
else if (condition & (G_IO_IN | G_IO_PRI))
{
char buf[READ_CHUNK_SIZE];
int count = 0;
gsize read;
char buf[INPUT_CHUNK_SIZE];
gsize count = 0, read, to_read;
int again = TRY_NUM;
g_io_channel_read_chars (source, buf, 1, &read, &err);
if (read == 1) ++count;
to_read = _moo_term_get_input_chunk_len (MOO_TERM_PT(pt)->priv->term);
g_assert (to_read <= sizeof (buf));
while (again && !err && !error_occured && count < READ_CHUNK_SIZE)
if (!to_read)
return TRUE;
g_io_channel_read_chars (source, buf, 1, &read, &err);
if (read == 1)
++count;
while (again && !err && !error_occured && count < to_read)
{
if (g_io_channel_get_buffer_condition (source) & G_IO_IN)
{
g_io_channel_read_chars (source, buf + count, 1, &read, &err);
if (read == 1)
{
++count;
}
else
{
if (--again)
g_usleep (SLEEP_TIME);
}
else if (--again)
g_usleep (SLEEP_TIME);
}
else
{
@ -260,7 +263,7 @@ read_helper_out (GIOChannel *source,
}
}
if (count > 0)
if (count)
moo_term_feed (MOO_TERM_PT(pt)->priv->term, buf, count);
error_occured = (err != NULL);
@ -292,7 +295,7 @@ read_helper_out (GIOChannel *source,
static void
kill_child (MooTermPt *pt_gen)
kill_child (MooTermPt *pt_gen)
{
MooTermPtCyg *pt = MOO_TERM_PT_CYG (pt_gen);

View File

@ -37,7 +37,6 @@
#endif
#define TERM_EMULATION "xterm"
#define READ_CHUNK_SIZE 1024
#define WRITE_CHUNK_SIZE 4096
#define POLL_TIME 5
#define POLL_NUM 1
@ -258,10 +257,11 @@ fork_argv (MooTermPt *pt_gen,
g_io_channel_set_encoding (pt->io, NULL, NULL);
g_io_channel_set_buffered (pt->io, FALSE);
pt->io_watch_id = g_io_add_watch (pt->io,
G_IO_IN | G_IO_PRI | G_IO_HUP,
(GIOFunc) read_child_out,
pt);
pt->io_watch_id = g_io_add_watch_full (pt->io,
G_PRIORITY_DEFAULT_IDLE,
G_IO_IN | G_IO_PRI | G_IO_HUP,
(GIOFunc) read_child_out,
pt, NULL);
src = g_main_context_find_source_by_id (NULL, pt->io_watch_id);
@ -328,28 +328,31 @@ static void kill_child (MooTermPt *pt_gen)
}
static gboolean read_child_out (G_GNUC_UNUSED GIOChannel *source,
GIOCondition condition,
MooTermPtUnix *pt)
static gboolean
read_child_out (G_GNUC_UNUSED GIOChannel *source,
GIOCondition condition,
MooTermPtUnix *pt)
{
gboolean error_occured = FALSE;
int error_no = 0;
char buf[READ_CHUNK_SIZE];
int current = 0;
char buf[INPUT_CHUNK_SIZE];
guint again = POLL_NUM;
gsize to_read;
gsize current = 0;
/* try to read leftover from the pipe */
if (condition & G_IO_HUP)
{
int r;
int bytes;
g_message ("%s: G_IO_HUP", G_STRLOC);
error_no = errno;
r = read (pt->master, buf, READ_CHUNK_SIZE);
bytes = read (pt->master, buf, sizeof (buf));
if (r > 0)
feed_buffer (pt, buf, r);
if (bytes > 0)
feed_buffer (pt, buf, bytes);
goto error;
}
@ -362,11 +365,22 @@ static gboolean read_child_out (G_GNUC_UNUSED GIOChannel *source,
g_assert (condition & (G_IO_IN | G_IO_PRI));
to_read = _moo_term_get_input_chunk_len (MOO_TERM_PT(pt)->priv->term);
g_assert (to_read <= sizeof (buf));
if (!to_read)
{
// g_print ("read_child_out: skipping\n");
return TRUE;
}
if (pt->non_block)
{
int r = read (pt->master, buf, READ_CHUNK_SIZE);
int bytes;
switch (r)
bytes = read (pt->master, buf, to_read);
switch (bytes)
{
case -1:
if (errno != EAGAIN && errno != EINTR)
@ -388,14 +402,14 @@ static gboolean read_child_out (G_GNUC_UNUSED GIOChannel *source,
g_free (s);
}
#endif
feed_buffer (pt, buf, r);
feed_buffer (pt, buf, bytes);
break;
}
return TRUE;
}
while (again && !error_occured && current < READ_CHUNK_SIZE)
while (again && !error_occured && current < to_read)
{
struct pollfd fd = {pt->master, POLLIN | POLLPRI, 0};
@ -492,12 +506,12 @@ error:
}
static void feed_buffer (MooTermPtUnix *pt,
const char *string,
int len)
static void
feed_buffer (MooTermPtUnix *pt,
const char *string,
int len)
{
moo_term_feed (MOO_TERM_PT(pt)->priv->term,
string, len);
moo_term_feed (MOO_TERM_PT(pt)->priv->term, string, len);
}

File diff suppressed because it is too large Load Diff