/************************************************************************* * * GTK Euler : the notebook widget * *************************************************************************/ #include #include #include #include #include #include #include "term.h" #include "sysdep.h" #include "stack.h" #include "builtin.h" #include "command.h" #include "edit.h" #include "rc.h" #define TERM_MINWIDTH_DEFAULT 80 #define TERM_MINHEIGHT_DEFAULT 24 int linelength = E_TWIDTH_DEFAULT; static char deadkey; /* for deadkey handling (^ and ¨) */ #define PADDING 2 enum { GTK_TERM_CHANGED, GTK_TERM_SAVED, GTK_TERM_EDITING, GTK_TERM_INTERPRETING, LAST_SIGNAL }; static guint gtk_term_signals[LAST_SIGNAL] = {0,0,0,0}; static GtkWidgetClass *parent_class = NULL; static void gtk_term_class_init (GtkTermClass *klass); static void gtk_term_init (GtkTerm *term); /* GtkObject and GtkWidget virtual methods */ static void gtk_term_destroy (GtkObject *object); static void gtk_term_realize (GtkWidget *widget); static void gtk_term_unrealize (GtkWidget *widget); static void gtk_term_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_term_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gint gtk_term_expose (GtkWidget *widget, GdkEventExpose *event); static void gtk_term_map (GtkWidget *widget); static gint gtk_term_focus_in(GtkWidget *widget, GdkEventFocus *event); static gint gtk_term_focus_out(GtkWidget *widget, GdkEventFocus *event); static gint gtk_term_key_press (GtkWidget *widget, GdkEventKey *event); static gint gtk_term_button_press (GtkWidget *widget, GdkEventButton *event); static gint gtk_term_button_release (GtkWidget *widget, GdkEventButton *event); static gint gtk_term_motion_notify (GtkWidget *widget, GdkEventMotion *event); static gint gtk_term_selection_clear(GtkWidget *widget, GdkEventSelection *event); static void gtk_term_selection_get(GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time); static void gtk_term_selection_received(GtkWidget *widget, GtkSelectionData *selection_data, guint time); /* private methods */ static void gtk_term_adjustment_safe_set_value(GtkTerm *term, gfloat value); static void gtk_term_scrollbar_moved (GtkAdjustment *adj, GtkWidget *widget); static void gtk_term_scroll(GtkWidget* widget, GdkEventScroll* event, gpointer user_data); static void gtk_term_cursor_up(GtkTerm *term); static void gtk_term_cursor_down(GtkTerm *term); static void gtk_term_update_caret(GtkTerm *term); static gint gtk_term_blink_caret(gpointer data); static void gtk_term_draw_caret(GtkTerm *term, guint state); static void gtk_term_scroll_to_pos(GtkTerm *term); static void gtk_term_draw_text(GtkTerm *term); static void gtk_term_redraw_current(GtkTerm *term); static void gtk_term_redraw_below(GtkTerm *term, int index); GType gtk_term_get_type() { static GType term_type = 0; if (!term_type) { GTypeInfo term_info = { sizeof (GtkTermClass), NULL, NULL, (GClassInitFunc) gtk_term_class_init, NULL, NULL, sizeof (GtkTerm), 0, (GInstanceInitFunc) gtk_term_init }; term_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkTerm", &term_info, 0); } return term_type; } /* * init of new signals and virtual methods */ static void gtk_term_class_init(GtkTermClass *klass) { GtkObjectClass *object_class = (GtkObjectClass*)klass; GtkWidgetClass *widget_class = (GtkWidgetClass*)klass; /* * save a copy of parent class structure to keep access to * its methods */ parent_class = gtk_type_class (gtk_widget_get_type ()); /* * define new signals */ gtk_term_signals[GTK_TERM_CHANGED] = g_signal_new ("term_changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkTermClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gtk_term_signals[GTK_TERM_SAVED] = g_signal_new ("term_saved", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkTermClass, saved), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gtk_term_signals[GTK_TERM_EDITING] = g_signal_new("term_editing", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkTermClass, editing), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gtk_term_signals[GTK_TERM_INTERPRETING] = g_signal_new("term_interpreting", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkTermClass, interpreting), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /* * define virtual methods */ object_class->destroy = gtk_term_destroy; widget_class->realize = gtk_term_realize; widget_class->unrealize = gtk_term_unrealize; widget_class->size_request = gtk_term_size_request; widget_class->size_allocate = gtk_term_size_allocate; widget_class->expose_event = gtk_term_expose; widget_class->map = gtk_term_map; widget_class->button_press_event = gtk_term_button_press; widget_class->button_release_event = gtk_term_button_release; widget_class->motion_notify_event = gtk_term_motion_notify; widget_class->focus_in_event = gtk_term_focus_in; widget_class->focus_out_event = gtk_term_focus_out; widget_class->key_press_event = gtk_term_key_press; widget_class->selection_clear_event = gtk_term_selection_clear; widget_class->selection_received = gtk_term_selection_received; widget_class->selection_get = gtk_term_selection_get; } /* * init of object parameters, create subwidgets */ static void gtk_term_init(GtkTerm *term) { GTK_WIDGET_SET_FLAGS(term, GTK_CAN_FOCUS); term->name = g_string_new(""); term->a = e_new(); e_append(term->a,"",E_OUTPUT); term->top = term->cur = term->pos = term->epos = 0; term->promptlen = 1; term->xoff = 0; term->xcaret = term->ycaret = 0; term->twidth = 0; term->theight = 0; term->tfont = g_string_new(""); term->font = NULL; term->cwidth = 0; term->cheight = 0; term->cursor = NULL; term->scan = 0; term->code = 0; term->commentGC = term->outputGC = term->promptGC = term->udfGC = term->highlightGC = NULL; /* scrollbar set up */ term->v_adj = GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 0.0, 1.0, (gfloat)term->theight -1.0, (gfloat)term->theight)); gtk_object_ref ((gpointer)(term->v_adj)); gtk_object_sink (GTK_OBJECT (term->v_adj)); g_signal_connect ((gpointer) (term->v_adj),"value_changed", G_CALLBACK (gtk_term_scrollbar_moved),term); g_signal_connect ((gpointer) (term), "scroll_event", G_CALLBACK (gtk_term_scroll), NULL); /* caret timer */ term->timeout_id = -1; term->caret_blink_state = 0; /* command history set up */ term->history = e_new(); e_append(term->history,"",0); term->max_history = 32; term->hist = 0; /* clipboard */ term->clipboard = g_string_new(""); /* flags */ term->editing = 0; term->initializing = 1; term->selecting = 0; term->changed = 0; term->menu = NULL; gtk_selection_add_target(GTK_WIDGET(term),GDK_SELECTION_PRIMARY,GDK_SELECTION_TYPE_STRING,1); } /************************************************************************ * PUBLIC INTERFACE ************************************************************************/ /* * create a term widget with cols columns and rows rows */ GtkWidget* gtk_term_new(guint cols, guint rows, char *font) { GtkTerm *term = gtk_type_new (gtk_term_get_type ()); g_string_assign(term->tfont,font); term->twidth = cols; term->theight = rows; return GTK_WIDGET (term); } /* * load a notebook */ gint gtk_term_load(GtkWidget *widget, gchar *filename) { GtkTerm * term; int i; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); if (!e_load(term->a,filename)) return 0; term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); term->top = 0; /* find out for the first command */ for (i=0 ; ia) ; i++) if (e_get_type(term->a,i)==E_PROMPT) { term->cur = i; term->pos = term->epos = term->promptlen; term->xoff = 0; gtk_term_update_caret(term); break; } gdk_window_clear(term->text); gtk_term_draw_text(term); g_string_assign(term->name,filename); term->changed = 0; g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_SAVED],0); return 1; } /* * save the terminal to a notebook */ gint gtk_term_save(GtkWidget *widget, gchar *filename) { GtkTerm *term; gchar *file; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); if (filename) file = filename; else file = term->name->str; if (!e_save(term->a,file)) return 0; if (filename) g_string_assign(term->name,filename); term->changed = 0; g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_SAVED],0); return 1; } /* * clear the terminal */ void gtk_term_clear(GtkWidget *widget) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); e_clear(term->a); e_append(term->a,"",0); term->cur = term->top = 0; term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gdk_window_clear(term->text); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } void gtk_term_clear_new(GtkWidget *widget) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); gtk_term_draw_caret(term,0); e_clear(term->a); e_append(term->a,">",E_PROMPT); term->cur = term->top = 0; term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gdk_window_clear(term->text); gtk_term_draw_text(term); term->changed = 0; g_string_assign(term->name,""); g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_SAVED],0); gtk_term_draw_caret(term,1); } /* gtk_term_copy * copy the current selection to the clipboard */ void gtk_term_copy(GtkWidget *widget) { GtkTerm *term; gchar *s; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); if (term->epos!=term->pos) { if(gtk_selection_owner_set(widget,GDK_SELECTION_PRIMARY,GDK_CURRENT_TIME)){ if (term->epos>term->pos) s = g_strndup(&((e_get_text(term->a,term->cur))[term->pos]),term->epos-term->pos); else s = g_strndup(&((e_get_text(term->a,term->cur))[term->epos]),term->pos-term->epos); g_string_assign(term->clipboard,s); g_free(s); } else { g_print("euler could not own the selection"); } } //else g_string_assign(term->clipboard,""); } /* gtk_term_cut * cut the current selection to the clipboard */ void gtk_term_cut(GtkWidget *widget) { GtkTerm *term; gchar *s; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); if (term->epos!=term->pos) { if(gtk_selection_owner_set(widget,GDK_SELECTION_PRIMARY,GDK_CURRENT_TIME)) { if (term->epos>term->pos) { s = g_strndup(&((e_get_text(term->a,term->cur))[term->pos]),term->epos-term->pos); e_remove_text(term->a,term->cur,term->pos,term->epos-term->pos); term->epos = term->pos; } else { s = g_strndup(&((e_get_text(term->a,term->cur))[term->epos]),term->pos-term->epos); e_remove_text(term->a,term->cur,term->epos,term->pos-term->epos); term->pos = term->epos; } g_string_assign(term->clipboard,s); g_free(s); gtk_term_update_caret(term); gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } else { g_print("euler could not own the selection\n"); } } } /* gtk_term_paste * paste the clipboard content to the current line */ void gtk_term_paste(GtkWidget *widget) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); gtk_selection_convert(widget,GDK_SELECTION_PRIMARY,GDK_TARGET_STRING,GDK_CURRENT_TIME); } gchar * gtk_term_get_comment(GtkWidget *widget) { GtkTerm *term; gchar *buffer, *next; int k, i, buffersize = 0; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); /* calculate the size of the comment */ k=term->cur; while (k-1>=0 && e_get_type(term->a,k-1)==E_COMMENT) { k--; buffersize += e_get_text_length(term->a,k)-1; } if (!buffersize) return NULL; next = buffer = g_malloc(buffersize); for (i=k;e_get_type(term->a,i)==E_COMMENT;i++) { strcpy(next,e_get_text(term->a,i)+2); next += e_get_text_length(term->a,i)-1; *(next-1)='\n'; } *(next-1)=0; return buffer; } void gtk_term_set_comment(GtkWidget *widget, gchar *cmt) { GtkTerm *term; char *s = cmt; int old_cur, dy; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); gtk_term_draw_caret(term,0); /* delete the current comment */ while (term->cur-1>=0 && e_get_type(term->a,term->cur-1)==E_COMMENT) { e_remove(term->a,term->cur-1); term->cur--; } old_cur=term->cur; /* insert the new one if any */ if (strlen(cmt)) { e_insert(term->a,term->cur,"% ",E_COMMENT); term->cur++; while (*s) { switch (*s) { case '\n' : e_insert(term->a,term->cur,"% ",E_COMMENT); term->cur++; break; default : e_append_char(term->a,term->cur-1,*s); } s++; } } if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } /* redraw what is needed */ term->v_adj->value = (gfloat)term->top; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_update_caret(term); gtk_term_redraw_below(term,old_cur); dy = old_cur - term->top; if (dy>=term->theight) gtk_term_adjustment_safe_set_value(term, (gfloat)(old_cur-term->theight+1)); else if (dy<0) gtk_term_adjustment_safe_set_value(term, (gfloat)old_cur); gtk_term_draw_caret(term,1); } gchar* gtk_term_get_name(GtkWidget *widget) { GtkTerm *term; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); return term->name->str; } gint gtk_term_is_named(GtkWidget *widget) { GtkTerm *term; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); return (term->name->len!=0); } gint gtk_term_is_changed(GtkWidget *widget) { GtkTerm *term; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); return term->changed; } gint gtk_term_is_initialized(GtkWidget *widget) { GtkTerm *term; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); return !term->initializing; } gint gtk_term_is_editing(GtkWidget *widget) { GtkTerm *term; g_return_val_if_fail (widget != NULL,0); g_return_val_if_fail (GTK_IS_TERM (widget),0); term = GTK_TERM (widget); return term->editing; } void gtk_term_print(GtkWidget *widget, gchar *s) { GtkTerm * term; int i,n; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); g_return_if_fail (s != NULL); term = GTK_TERM (widget); while (*s) { switch (*s) { case '\n' : term->pos = term->epos = 0; gtk_term_update_caret(term); gtk_term_redraw_current(term); e_insert(term->a,term->cur+1,"",E_OUTPUT); term->cur++; term->v_adj->value = (gfloat)term->top; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_scroll_to_pos(term); break; case 9 : n=4-(term->pos%4); for (i=0; ia,term->cur,' '); term->pos++; term->epos++; } break; default : e_append_char(term->a,term->cur,*s); // gtk_term_update_caret(term); // gtk_term_redraw_current(term); term->pos++; term->epos++; } s++; } if (!term->changed && !term->initializing) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } void gtk_term_edit_on(GtkWidget *widget) { GtkTerm * term; char ch; int i, type = E_OUTPUT, oldcur;; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); ch =(e_get_text(term->a,term->cur))[term->pos-1]; if (ch=='>') { term->promptlen = term->pos; if (term->promptlen==1) { e_set_type(term->a,term->cur,E_PROMPT); type = E_PROMPT; } } else if (ch=='$') { e_set_type(term->a,term->cur,E_UDF); type = E_UDF; } oldcur = term->cur; for (i=term->cur+1;ia);i++) { if (e_get_type(term->a,i)==type) { e_remove(term->a,term->cur); term->cur=i-1; break; } } term->v_adj->value = (gfloat)term->top; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_scroll_to_pos(term); gtk_term_redraw_below(term,oldcur-1>=0? oldcur:0); term->editing = 1; if (term->timeout_id == -1 && term->editing && GTK_WIDGET_HAS_FOCUS(widget)) { term->timeout_id = gtk_timeout_add (500, gtk_term_blink_caret, term); gtk_term_draw_caret(term,1); } g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_EDITING],0); if (term->initializing) term->initializing = 0; } void gtk_term_edit_off(GtkWidget *widget) { GtkTerm * term; int type; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_INTERPRETING],0); term->editing = 0; if (term->timeout_id != -1) { g_source_remove(term->timeout_id); term->timeout_id = -1; } type = e_get_type(term->a,term->cur); if (type==E_COMMENT || (!strncmp(e_get_text(term->a,term->cur),">function",9) && term->cur+1a) && e_get_type(term->a,term->cur+1)==E_UDF) || (type==E_UDF && strncmp(e_get_text(term->a,term->cur),"$endfunction",12))) return; /* the line will be evaluated : remove the old output results */ while (term->cur+1a)) { type = e_get_type(term->a,term->cur+1); if (type==E_PROMPT || type==E_COMMENT) break; e_remove(term->a,term->cur+1); } term->v_adj->value = (gfloat)term->top; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); } void gtk_term_insert_command(GtkWidget *widget, char *text) { int type; GtkTerm * term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); type = e_get_type(term->a,term->cur); if (type!=E_PROMPT && type!=E_UDF) return; gtk_term_draw_caret(term,0); if (type==E_PROMPT) { int i = term->cur; while (i-1>=0 && e_get_type(term->a,i-1)==E_COMMENT) i--; term->cur = i; e_insert(term->a,term->cur,">",E_PROMPT); } else { e_insert(term->a,term->cur,"$",E_UDF); } term->pos = term->epos = term->promptlen; term->v_adj->upper = (gfloat)(e_get_length(term->a)); gtk_adjustment_changed(term->v_adj); if (term->cur < term->top) { gtk_term_scroll_to_pos(term); } else { gtk_term_update_caret(term); gtk_term_redraw_below(term,term->cur); } gtk_term_update_caret(term); gtk_term_draw_caret(term,1); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } void gtk_term_delete_command(GtkWidget *widget) { GtkTerm * term; int i; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); if (e_get_type(term->a,term->cur)==E_UDF) { if (term->cur==e_get_length(term->a)-1 || e_get_type(term->a,term->cur+1)!=E_UDF) return; gtk_term_draw_caret(term,0); e_remove(term->a,term->cur); term->pos = term->epos = term->promptlen; // term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_update_caret(term); gtk_term_redraw_below(term,term->cur); gtk_term_draw_caret(term,1); return; } /* is there another command line after this one (don't delete * the last line) ? */ for (i=term->cur+1;ia);i++) if (e_get_type(term->a,i)==E_PROMPT) break; if (i==e_get_length(term->a)) return; gtk_term_draw_caret(term,0); /* delete the comment lines if any */ while(term->cur && e_get_type(term->a,term->cur-1)==E_COMMENT) { e_remove(term->a,term->cur-1); term->cur--; } /* delete the command line */ e_remove(term->a,term->cur); /* delete the output and user function definition lines if any */ while (e_get_type(term->a,term->cur)==E_OUTPUT || e_get_type(term->a,term->cur)==E_UDF) e_remove(term->a,term->cur); /* set up the new current line (the next prompt) */ while (term->cura) && e_get_type(term->a,term->cur)!=E_PROMPT) term->cur++; term->pos = term->epos = term->promptlen; // term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_scroll_to_pos(term); gdk_window_clear(term->text); gtk_term_draw_text(term); gtk_term_draw_caret(term,1); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } void gtk_term_delete_current_output(GtkWidget *widget) { GtkTerm * term; int i, changed=0; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); if (term->editing) { i = term->cur+1; while (ia) && e_get_type(term->a,i)==E_OUTPUT) { e_remove(term->a,i); changed = 1; } if(!changed) return; // term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_scroll_to_pos(term); gdk_window_clear(term->text); gtk_term_draw_text(term); gtk_term_draw_caret(term,1); if (!term->changed && changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } } void gtk_term_delete_outputs(GtkWidget *widget) { GtkTerm * term; int i, changed=0; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); if (term->editing) { i=0; while (ia)) { if (e_get_type(term->a,i)==E_OUTPUT) { e_remove(term->a,i); if (icur) term->cur--; changed = 1; } else i++; } if (!changed) return; // term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_scroll_to_pos(term); gdk_window_clear(term->text); gtk_term_draw_text(term); gtk_term_draw_caret(term,1); if (!term->changed && changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } } void gtk_term_set_popup(GtkWidget *widget, GtkMenu *menu) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); g_return_if_fail (menu!=NULL); term = GTK_TERM (widget); term->menu = menu; } void gtk_term_set_scrollbar(GtkWidget *widget, GtkWidget *scroll) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); g_return_if_fail (scroll!=NULL); term = GTK_TERM (widget); term->p_scroll = scroll; } void gtk_term_set_colors(GtkWidget *widget, GdkColor *cmdColor, GdkColor *outColor, GdkColor *cmtColor, GdkColor *udfColor) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); gdk_gc_set_foreground(term->commentGC,cmtColor); gdk_gc_set_foreground(term->outputGC,outColor); gdk_gc_set_foreground(term->promptGC,cmdColor); gdk_gc_set_foreground(term->udfGC,udfColor); } /************************************************************************ * PRIVATE METHODS ************************************************************************/ static void gtk_term_cursor_up(GtkTerm *term) { int i; if (e_get_type(term->a,term->cur)==E_UDF) { if (e_get_type(term->a,term->cur-1)==E_UDF) { gtk_term_draw_caret(term,0); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); term->cur--; gtk_term_scroll_to_pos(term); gtk_term_draw_caret(term,1); } return; } if (e_get_type(term->a,term->cur)!=E_PROMPT) return; for (i=term->cur-1 ; i>=0 ; i--) if (e_get_type(term->a,i)==E_PROMPT) { gtk_term_draw_caret(term,0); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); term->cur = i; gtk_term_scroll_to_pos(term); gtk_term_draw_caret(term,1); break; } } static void gtk_term_cursor_down(GtkTerm *term) { int i; if (e_get_type(term->a,term->cur)==E_UDF) { if (e_get_type(term->a,term->cur+1)==E_UDF) { gtk_term_draw_caret(term,0); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); term->cur++; gtk_term_scroll_to_pos(term); gtk_term_draw_caret(term,1); } return; } if (e_get_type(term->a,term->cur)!=E_PROMPT) return; for (i=term->cur+1 ; ia) ; i++) if (e_get_type(term->a,i)==E_PROMPT) { gtk_term_draw_caret(term,0); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); term->cur = i; gtk_term_scroll_to_pos(term); gtk_term_draw_caret(term,1); break; } } static void gtk_term_scroll_to_pos(GtkTerm *term) { gint w,h,dy; dy = term->cur - term->top; if (dy>=term->theight) gtk_term_adjustment_safe_set_value(term, (gfloat)(term->cur-term->theight+1)); else if (dy<0) gtk_term_adjustment_safe_set_value(term, (gfloat)term->cur); else{ gtk_term_adjustment_safe_set_value(term, (gfloat)term->v_adj->value); gtk_term_update_caret(term); } gdk_drawable_get_size(term->text,&w,&h); term->xcaret = term->xoff+term->pos*term->cwidth+PADDING; if (term->xcaret>w-40){ while (term->xcaret>w-40) { term->xoff-=40; term->xcaret = term->xoff+term->pos*term->cwidth+PADDING; } gdk_window_clear(term->text); gtk_term_draw_text(term); } else if (term->xcaretxcaretxoff+=40; term->xcaret = term->xoff+term->pos*term->cwidth+PADDING; } gdk_window_clear(term->text); gtk_term_draw_text(term); } else gtk_term_redraw_current(term); } static void gtk_term_update_caret(GtkTerm *term) { term->xcaret = term->xoff+term->pos*term->cwidth+PADDING; term->ycaret = (term->cur-term->top)*term->cheight+PADDING; } static void gtk_term_draw_caret(GtkTerm *term, guint state) { GdkGC *gc; if (term->pos==term->epos && term->cur >= term->top && term->cur < (term->top + term->theight)) { if (state && !term->caret_blink_state) { gc = ((GtkWidget*)term)->style->black_gc; gdk_draw_line(term->text,gc,term->xcaret,term->ycaret,term->xcaret,term->ycaret+term->cheight); } else if (!state && term->caret_blink_state) { gc = ((GtkWidget*)term)->style->white_gc; gdk_draw_line(term->text,gc,term->xcaret,term->ycaret,term->xcaret,term->ycaret+term->cheight); gtk_term_redraw_current(term); } term->caret_blink_state = state; } } static gint gtk_term_blink_caret(gpointer data) { GtkTerm *term = (GtkTerm*)data; g_return_val_if_fail (data != NULL, FALSE); gtk_term_draw_caret(term,!term->caret_blink_state); return TRUE; } /************************************************************************ * GtkObject and GtkWidget VIRTUAL METHODS DEFINITION ************************************************************************/ /* * GtkObject destroy method */ static void gtk_term_destroy (GtkObject *object) { GtkTerm *term; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_TERM (object)); term = GTK_TERM (object); if (term->timeout_id != -1) g_source_remove(term->timeout_id); e_free(term->history); e_free(term->a); if (term->cursor) { gdk_cursor_destroy(term->cursor); term->cursor = NULL; } if (term->font) { gdk_font_unref (term->font); term->font = NULL; } if (term->v_adj) { gtk_signal_disconnect_by_data (GTK_OBJECT (term->v_adj), term); gtk_object_unref (GTK_OBJECT (term->v_adj)); term->v_adj = NULL; } g_string_free(term->name,TRUE); g_string_free(term->clipboard,TRUE); /* * call widget class destroy method */ if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy)(object); } /* * realize / unrealize : set up or destroy the gdk_window */ static void gtk_term_realize (GtkWidget *widget) { GtkTerm *term; GdkWindowAttr attributes; gint attributes_mask; GdkColormap *cmap; GdkColor c; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); term = GTK_TERM (widget); attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.window_type = GDK_WINDOW_CHILD; attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK | GDK_KEY_PRESS_MASK; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = cmap = gtk_widget_get_colormap (widget); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; /* main window */ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); widget->style = gtk_style_attach (widget->style, widget->window); gdk_window_set_user_data (widget->window, widget); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); attributes.x = widget->style->xthickness; attributes.y = widget->style->ythickness; attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2); attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2); attributes.cursor = term->cursor = gdk_cursor_new(GDK_XTERM); attributes_mask |= GDK_WA_CURSOR; term->text = gdk_window_new (widget->window, &attributes, attributes_mask); gdk_window_set_user_data (term->text, term); gdk_window_set_background (term->text, &widget->style->white); gdk_window_show(term->text); term->font = gdk_font_load (term->tfont->str); if (!term->font) { fprintf(stderr,"The default font could not be found. Please change it by editing the \"tfont\" symbol in ~/euler/eulerrc\n"); exit(1); } term->cwidth = gdk_char_width(term->font,'m'); term->cheight = 2+gdk_string_height(term->font,"abcdefghijklmnopqrstuvwxyz0123456789"); term->commentGC = gdk_gc_new(term->text); c.red = 0; c.green = 100<<8; c.blue = 0; if (gdk_color_alloc(cmap,&c)) gdk_gc_set_foreground(term->commentGC,&c); term->outputGC = gdk_gc_new(term->text); term->udfGC = gdk_gc_new(term->text); c.red = 0; c.green = 0; c.blue = 100<<8; if (gdk_color_alloc(cmap,&c)) gdk_gc_set_foreground(term->udfGC,&c); term->promptGC = gdk_gc_new(term->text); c.red = 100<<8; c.green = 0; c.blue = 0; if (gdk_color_alloc(cmap,&c)) gdk_gc_set_foreground(term->promptGC,&c); term->highlightGC = gdk_gc_new(term->text); c.red = 255<<8; c.green = 153<<8; c.blue = 41<<8; if (gdk_color_alloc(cmap,&c)) gdk_gc_set_foreground(term->highlightGC,&c); term->v_adj->value = 0.0; term->v_adj->lower = 0.0; term->v_adj->upper = (gfloat)(e_get_length(term->a)); term->v_adj->step_increment = 1.0; term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); } static void gtk_term_unrealize (GtkWidget *widget) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED); term = GTK_TERM (widget); gdk_window_set_user_data (term->text, NULL); gdk_window_destroy (term->text); term->text = NULL; gdk_gc_destroy(term->commentGC); gdk_gc_destroy(term->outputGC); gdk_gc_destroy(term->udfGC); gdk_gc_destroy(term->promptGC); gdk_gc_destroy(term->highlightGC); if (GTK_WIDGET_CLASS (parent_class)->unrealize) (*GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } /* * selection handling */ static gint gtk_term_selection_clear(GtkWidget *widget, GdkEventSelection *event) { GtkTerm *term; g_return_val_if_fail (widget != NULL,FALSE); g_return_val_if_fail (GTK_IS_TERM(widget),FALSE); term = GTK_TERM(widget); /* Let the selection handling code know that the selection * has been changed, since we've overriden the default handler */ if (!gtk_selection_clear (widget, event)) return FALSE; if (term->clipboard->len!=0) g_string_assign(term->clipboard,""); return TRUE; } static void gtk_term_selection_get(GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM(widget)); term = GTK_TERM(widget); gtk_selection_data_set(selection_data,GDK_SELECTION_TYPE_STRING,8,term->clipboard->str,term->clipboard->len); } static void gtk_term_selection_received(GtkWidget *widget, GtkSelectionData *selection_data, guint time) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM(widget)); term = GTK_TERM(widget); if (selection_data->length<0) return; if (selection_data->type != GDK_SELECTION_TYPE_STRING) return; /* if a piece of text is currently selected : delete it */ if (term->editing && (term->pos != term->epos)) { if (term->epos>term->pos) { e_remove_text(term->a,term->cur,term->pos,term->epos-term->pos); term->epos = term->pos; } else { e_remove_text(term->a,term->cur,term->epos,term->pos-term->epos); term->pos = term->epos; } } selection_data->data[selection_data->length] = 0; e_insert_text(term->a,term->cur,term->pos,(gchar *)selection_data->data); term->pos += strlen ((gchar *)selection_data->data); term->epos = term->pos; gtk_term_update_caret(term); gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } /* * size_request : set the minimum widget size : 80 chars * 24 lines */ static void gtk_term_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); g_return_if_fail (requisition != NULL); term = GTK_TERM (widget); requisition->width = (term->twidth * term->cwidth) + (widget->style->xthickness * 2) + 2*PADDING; requisition->height = (term->theight * term->cheight) + (widget->style->ythickness * 2) + 2*PADDING; } /* * size_allocate : set the actual widget size */ static void gtk_term_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkTerm *term; static short count = 1; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); g_return_if_fail (allocation != NULL); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED(widget)) { term = GTK_TERM(widget); if (count == 2) { int w = (TERM_MINWIDTH_DEFAULT * term->cwidth) + (widget->style->xthickness * 2) + 2*PADDING; int h = (TERM_MINHEIGHT_DEFAULT * term->cheight) + (widget->style->ythickness * 2) + 2*PADDING; gtk_widget_set_size_request(widget, w, h); count = 0; } if (count == 1) count = 2; gdk_window_move_resize(widget->window, allocation->x, allocation->y, allocation->width, allocation->height); gdk_window_move_resize(term->text, widget->style->xthickness, widget->style->ythickness, allocation->width-2*widget->style->xthickness, allocation->height-2*widget->style->ythickness); linelength = term->twidth = (allocation->width - (2 * widget->style->xthickness) - 2 * PADDING)/term->cwidth; term->theight = (allocation->height - (2 * widget->style->ythickness)- 2 * PADDING)/term->cheight; /* * resize the scrollbar */ term->v_adj->page_increment = (gfloat)(term->theight-1); term->v_adj->page_size = (gfloat)term->theight; gtk_adjustment_changed(term->v_adj); gtk_term_scroll_to_pos(term); } } static void gtk_term_redraw_current(GtkTerm *term) { int offy; GdkGC * gc = NULL; offy = PADDING+(term->cur-term->top)*term->cheight; gdk_window_clear_area(term->text,0,offy,2*PADDING+term->twidth*term->cwidth,term->cheight); if (term->pos!=term->epos) { if (term->epos>term->pos) gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret,offy,(term->epos-term->pos)*term->cwidth,term->cheight); else gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret-(term->pos-term->epos)*term->cwidth,offy,(term->pos-term->epos)*term->cwidth,term->cheight); } switch (e_get_type(term->a,term->cur)) { case E_OUTPUT: gc = term->outputGC; break; case E_PROMPT: gc = term->promptGC; break; case E_UDF: gc = term->udfGC; break; case E_COMMENT: gc = term->commentGC; } gdk_draw_string(term->text,term->font,gc,PADDING+term->xoff,offy+term->cheight-term->font->descent-1,e_get_text(term->a,term->cur)); } static void gtk_term_redraw_below(GtkTerm *term, int index) { int offy; GdkGC * gc = NULL; int i, last; offy = PADDING+(index-term->top)*term->cheight; gdk_window_clear_area(term->text, 0, offy, 2*PADDING+term->twidth*term->cwidth, (term->theight-index+term->top)*term->cheight); last = MIN(term->top+term->theight,e_get_length(term->a)); for (i=index ; icur && term->epos!=term->pos) { if (term->epos>term->pos) gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret,offy,(term->epos-term->pos)*term->cwidth,term->cheight); else gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret-(term->pos-term->epos)*term->cwidth,offy,(term->pos-term->epos)*term->cwidth,term->cheight); } offy+=term->cheight; switch (e_get_type(term->a,i)) { case E_OUTPUT: gc = term->outputGC; break; case E_PROMPT: gc = term->promptGC; break; case E_UDF: gc = term->udfGC; break; case E_COMMENT: gc = term->commentGC; } gdk_draw_string(term->text,term->font,gc, PADDING+term->xoff, offy-term->font->descent-1, e_get_text(term->a,i)); } } static void gtk_term_draw_text(GtkTerm *term) { int offx, offy; GdkGC * gc = NULL; int i, last; if (term->editing) gtk_term_draw_caret(term,0); offx = PADDING+term->xoff; offy = PADDING; last = MIN(term->top+term->theight,e_get_length(term->a)); for (i=term->top ; icur && term->epos!=term->pos) { if (term->epos>term->pos) gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret,offy,(term->epos-term->pos)*term->cwidth,term->cheight); else gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret-(term->pos-term->epos)*term->cwidth,offy,(term->pos-term->epos)*term->cwidth,term->cheight); } offy+=term->cheight; switch (e_get_type(term->a,i)) { case E_OUTPUT: gc = term->outputGC; break; case E_PROMPT: gc = term->promptGC; break; case E_UDF: gc = term->udfGC; break; case E_COMMENT: gc = term->commentGC; } // gdk_draw_rectangle(term->text,gc,FALSE,offx,offy-term->cheight,widget->allocation.width-2*(PADDING+widget->style->klass->ythickness),term->cheight); gdk_draw_string(term->text,term->font,gc,offx,offy-term->font->descent-1,e_get_text(term->a,i)); } if (term->editing) gtk_term_draw_caret(term,1); } /* * draw / expose : draw or refresh the widget */ static gint gtk_term_expose (GtkWidget *widget, GdkEventExpose *event) { GtkTerm * term; g_return_val_if_fail (widget != NULL,FALSE); g_return_val_if_fail (GTK_IS_TERM (widget),FALSE); g_return_val_if_fail (event!=NULL,FALSE); if (GTK_WIDGET_DRAWABLE (widget)) { term = GTK_TERM (widget); if (event->window==term->text) gtk_term_draw_text(term); else gtk_draw_shadow (widget->style,widget->window,GTK_STATE_NORMAL,GTK_SHADOW_IN,0,0,widget->allocation.width,widget->allocation.height); } return FALSE; } static void gtk_term_adjustment_safe_set_value(GtkTerm *term, gfloat value) { if (value < term->v_adj->lower || term->v_adj->upper < term->v_adj->page_size) gtk_adjustment_set_value(term->v_adj, term->v_adj->lower); else if (value > term->v_adj->upper - term->v_adj->page_size) gtk_adjustment_set_value(term->v_adj, term->v_adj->upper - term->v_adj->page_size); else gtk_adjustment_set_value(term->v_adj, value); } /* * Callback for when the adjustment changes - i.e., the scrollbar * moves. */ static void gtk_term_scrollbar_moved (GtkAdjustment *adj, GtkWidget *widget) { GtkTerm *term; gint dy; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); dy = (gint)adj->value - term->top; if (dy) { if (term->editing) gtk_term_draw_caret(term,0); if (dy>0) { gint offx, offy, i; GdkGC *gc = NULL; offx = PADDING+term->xoff; offy = PADDING; gdk_window_copy_area(term->text,term->outputGC,offx,offy, term->text, offx,offy+dy*term->cheight, term->twidth*term->cwidth+PADDING, (term->theight-dy)*term->cheight); gdk_draw_rectangle(term->text,widget->style->white_gc,TRUE, offx,offy+(term->theight-dy)*term->cheight, term->twidth*term->cwidth+PADDING, dy*term->cheight); for (i=term->top+term->theight; itop+term->theight+dy; i++) { if (i==term->cur && term->epos!=term->pos) { if (term->epos>term->pos) gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret,offy+(i-term->top-dy)*term->cheight,(term->epos-term->pos)*term->cwidth+PADDING,term->cheight); else gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret-(term->pos-term->epos)*term->cwidth,offy+(i-term->top-dy)*term->cheight,(term->pos-term->epos)*term->cwidth+PADDING,term->cheight); } switch (e_get_type(term->a,i)) { case E_OUTPUT: gc = term->outputGC; break; case E_PROMPT: gc = term->promptGC; break; case E_UDF: gc = term->udfGC; break; case E_COMMENT: gc = term->commentGC; } if(e_get_text(term->a,i)) gdk_draw_string(term->text,term->font,gc, offx, offy+(i-term->top-dy+1)*term->cheight-term->font->descent-1, e_get_text(term->a,i)); } term->top += dy; } else { gint offx, offy, i; GdkGC *gc = NULL; dy = -dy; offx = PADDING+term->xoff; offy = PADDING; gdk_window_copy_area(term->text,term->outputGC,offx,offy+dy*term->cheight, term->text, offx,offy, term->twidth*term->cwidth+PADDING, (term->theight-dy)*term->cheight); gdk_draw_rectangle(term->text,widget->style->white_gc,TRUE, offx,offy, term->twidth*term->cwidth+PADDING, dy*term->cheight); for (i=term->top-dy; itop; i++) { if (i==term->cur && term->epos!=term->pos) { if (term->epos>term->pos) gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret,offy+(i-term->top+dy)*term->cheight,(term->epos-term->pos)*term->cwidth+PADDING,term->cheight); else gdk_draw_rectangle(term->text,term->highlightGC,TRUE,term->xcaret-(term->pos-term->epos)*term->cwidth,offy+(i-term->top+dy)*term->cheight,(term->pos-term->epos)*term->cwidth+PADDING,term->cheight); } switch (e_get_type(term->a,i)) { case E_OUTPUT: gc = term->outputGC; break; case E_PROMPT: gc = term->promptGC; break; case E_UDF: gc = term->udfGC; break; case E_COMMENT: gc = term->commentGC; } if(e_get_text(term->a,i)) gdk_draw_string(term->text,term->font,gc,offx, offy+(i-term->top+dy+1)*term->cheight-term->font->descent-1, e_get_text(term->a,i)); } term->top -= dy; } gtk_term_update_caret(term); if (term->editing) gtk_term_draw_caret(term,1); } } static void gtk_term_scroll(GtkWidget* widget, GdkEventScroll* event, gpointer user_data) { GtkAdjustment* sb_state; gdouble lower; gdouble upper; gdouble far; GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); sb_state = gtk_range_get_adjustment(GTK_RANGE(term->p_scroll)); lower = sb_state->lower; upper = sb_state->upper; if (sb_state->page_size >= upper) return; switch (event->direction) { case GDK_SCROLL_UP: if (sb_state->value <= lower) return; if ((sb_state->value - lower) < sb_state->step_increment) far = sb_state->value - lower; else far = sb_state->step_increment; gtk_adjustment_set_value(sb_state, sb_state->value - far); break; case GDK_SCROLL_DOWN: if (sb_state->value >= (upper - sb_state->page_size)) return; if (((upper - sb_state->page_size) - sb_state->value) < sb_state->step_increment) far = (upper - sb_state->page_size) - sb_state->value; else far = sb_state->step_increment; gtk_adjustment_set_value(sb_state, sb_state->value + far); break; default:{}; } } static void gtk_term_map (GtkWidget *widget) { GtkTerm *term; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TERM (widget)); term = GTK_TERM (widget); if (!GTK_WIDGET_MAPPED (widget)) { GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); gdk_window_show (widget->window); if (!GTK_WIDGET_HAS_FOCUS (widget)) gtk_widget_grab_focus (widget); } } static gint gtk_term_button_press (GtkWidget *widget, GdkEventButton *event) { GtkTerm * term; int n, p; g_return_val_if_fail (widget != NULL,FALSE); g_return_val_if_fail (GTK_IS_TERM (widget),FALSE); g_return_val_if_fail (event!=NULL,FALSE); if (event->button==1) { term = GTK_TERM (widget); if (!term->editing) return FALSE; n = term->top + (event->y - widget->style->ythickness - PADDING)/term->cheight; p = (event->x - term->xoff - widget->style->xthickness - PADDING)/term->cwidth; if (n>=e_get_length(term->a) || e_get_type(term->a,n)==E_OUTPUT || e_get_type(term->a,n)==E_COMMENT) return FALSE; if (((e_get_type(term->a,term->cur)==E_UDF && term->cur==n) || e_get_type(term->a,n)==E_PROMPT) && !nojump) { gtk_term_draw_caret(term,0); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); if (ppromptlen) p=term->promptlen; if (p>e_get_text_length(term->a,n)) p=e_get_text_length(term->a,n); term->cur = n; term->pos = term->epos = p; gtk_term_update_caret(term); gtk_term_scroll_to_pos(term); term->selecting = 1; } } else if (event->button==3) { term = GTK_TERM (widget); if (!term->editing) return FALSE; n = term->top + (event->y - widget->style->ythickness - PADDING)/term->cheight; p = (event->x - term->xoff - widget->style->xthickness - PADDING)/term->cwidth; if (n>=e_get_length(term->a) || e_get_type(term->a,n)==E_OUTPUT || e_get_type(term->a,n)==E_COMMENT) return FALSE; if (term->cur!=n) if (((e_get_type(term->a,term->cur)==E_UDF && term->cur==n) || e_get_type(term->a,n)==E_PROMPT) && !nojump) { gtk_term_draw_caret(term,0); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); if (ppromptlen) p=term->promptlen; if (p>e_get_text_length(term->a,n)) p=e_get_text_length(term->a,n); term->cur = n; term->pos = term->epos = p; gtk_term_update_caret(term); gtk_term_scroll_to_pos(term); } gtk_menu_popup(term->menu,NULL,NULL,NULL,NULL,event->button,event->time); } return FALSE; } static void gtk_term_scroll_to_epos(GtkTerm *term) { gint w,h,eposx; gdk_drawable_get_size(term->text,&w,&h); eposx = term->xoff+term->epos*term->cwidth+PADDING; if (eposx>w-40){ term->xoff-=40; term->xcaret = term->xoff+term->pos*term->cwidth+PADDING; gdk_window_clear(term->text); gtk_term_draw_text(term); } else if (eposxxoff+=40; term->xcaret = term->xoff+term->pos*term->cwidth+PADDING; gdk_window_clear(term->text); gtk_term_draw_text(term); } else gtk_term_redraw_current(term); } static gint gtk_term_motion_notify (GtkWidget *widget, GdkEventMotion *event) { GtkTerm * term; int p; g_return_val_if_fail (widget != NULL,FALSE); g_return_val_if_fail (GTK_IS_TERM (widget),FALSE); g_return_val_if_fail (event!=NULL,FALSE); term = GTK_TERM (widget); if (!term->editing || !term->selecting) return FALSE; p = (event->x - term->xoff - widget->style->xthickness - PADDING)/term->cwidth; if (ppromptlen) p=term->promptlen; if (p>e_get_text_length(term->a,term->cur)) p=e_get_text_length(term->a,term->cur); term->epos = p; gtk_term_scroll_to_epos(term); return FALSE; } static gint gtk_term_button_release (GtkWidget *widget, GdkEventButton *event) { GtkTerm * term; g_return_val_if_fail (widget != NULL,FALSE); g_return_val_if_fail (GTK_IS_TERM (widget),FALSE); g_return_val_if_fail (event!=NULL,FALSE); term = GTK_TERM (widget); switch (event->button) { case 1: term->selecting = 0; gtk_term_redraw_current(term); gtk_term_draw_caret(term,1); break; case 4: gtk_term_adjustment_safe_set_value(term, term->v_adj->value-term->theight+1); break; case 5: gtk_term_adjustment_safe_set_value(term, (gfloat)MIN(term->top+term->theight-1,e_get_length(term->a)-term->theight)); break; } return FALSE; } static gint gtk_term_focus_in(GtkWidget *widget, GdkEventFocus *event) { GtkTerm *term; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_TERM (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); term = GTK_TERM (widget); GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); if (term->timeout_id == -1 && term->editing) { term->timeout_id = gtk_timeout_add (500, gtk_term_blink_caret, term); gtk_term_draw_caret(term,1); } return FALSE; } static gint gtk_term_focus_out(GtkWidget *widget, GdkEventFocus *event) { GtkTerm *term; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_TERM (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); term = GTK_TERM (widget); GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); if (term->timeout_id != -1) { g_source_remove(term->timeout_id); term->timeout_id = -1; } gtk_term_draw_caret(term,0); return FALSE; } /* dohelp * Extend a start string in up to 16 ways to a command or function. * This function is called from the line editor, whenever the HELP * key is pressed. */ static char helpstart[256]; static char helpextend[16][16]; static int helpn=0,helpnext=0,helphist=-1; static char *p; extern commandtyp command_list[]; static int dohelp (char start[256], char extend[16][16]) { int count=0,ln,l; header *hd=(header *)ramstart; builtintyp *b=builtin_list; commandtyp *c=command_list; ln=(int)strlen(start); while (b->name) { if (!strncmp(start,b->name,ln)) { l=(int)strlen(b->name)-ln; if (l>0 && l<16) { strcpy(extend[count],b->name+ln); count++; } if (count>=16) return count; } b++; } while (hd<(header *)udfend) { if (!strncmp(start,hd->name,ln)) { l=(int)strlen(hd->name)-ln; if (l>0 && l<16) { strcpy(extend[count],hd->name+ln); count++; } if (count>=16) return count; } hd=nextof(hd); } while (c->name) { if (!strncmp(start,c->name,ln)) { l=(int)strlen(c->name)-ln; if (l>0 && l<16) { strcpy(extend[count],c->name+ln); count++; } if (count>=16) return count; } c++; } return count; } /* extend the command at cursor position */ static void gtk_term_edithelp (GtkTerm *term) { char *start,*end,*p; int i,l; /* search history */ l=e_get_text_length(term->a,term->cur); helphist=-1; for (i=e_get_length(term->history)-1; i>=0; i--) if (!strncmp(e_get_text(term->history,i),e_get_text(term->a,term->cur),l)) { helphist=i; break; } /* get the begining of the command to extend */ start=end=p=e_get_text(term->a,term->cur)+term->pos; while (start>e_get_text(term->a,term->cur) && (isalpha(*(start-1)) || isdigit(*(start-1)))) start--; while (isdigit(*start)) start++; while (isalpha(*end) || isdigit(*end)) end++; if (start>p || start>=end) return; while (ppos++; p++; } memmove(helpstart,start,end-start); helpstart[end-start]=0; helpn=dohelp(helpstart,helpextend); helpnext=0; } static void gtk_term_fkinsert (GtkTerm *term, int i) { char *p = fktext[i]; e_insert_text(term->a,term->cur,term->pos,p); gtk_term_redraw_current(term); term->pos += (int)strlen(p); gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } static void get_scan(GdkEventKey *event, GtkTerm *term) { switch (event->keyval) { case GDK_Escape: term->scan = escape; break; case GDK_KP_Up: case GDK_Up: term->scan = cursor_up; break; case GDK_KP_Down: case GDK_Down: term->scan = cursor_down; break; case GDK_KP_Right: case GDK_Right: if (event->state & GDK_SHIFT_MASK) { term->scan = word_right; } else { term->scan = cursor_right; } break; case GDK_KP_Left: case GDK_Left: if (event->state & GDK_SHIFT_MASK) { term->scan = word_left; } else { term->scan = cursor_left; } break; case GDK_BackSpace: term->scan = backspace; break; case GDK_Delete: case GDK_KP_Delete: term->scan = deletekey; break; case GDK_KP_Insert: case GDK_Insert: break; case GDK_KP_Home: case GDK_Home: term->scan = line_start; break; case GDK_KP_End: case GDK_End: term->scan = line_end; break; case GDK_KP_F1: case GDK_F1: term->scan = fk1; break; case GDK_KP_F2: case GDK_F2: term->scan = fk2; break; case GDK_KP_F3: case GDK_F3: term->scan = fk3; break; case GDK_KP_F4: case GDK_F4: term->scan = fk4; break; case GDK_F5: term->scan = fk5; break; case GDK_F6: term->scan = fk6; break; case GDK_F7: term->scan = fk7; break; case GDK_F8: term->scan = fk8; break; case GDK_F9: term->scan = fk9; break; case GDK_F10: term->scan = fk10; break; case GDK_F11: case GDK_F12: case GDK_F13: case GDK_F14: case GDK_F15: case GDK_F16: case GDK_F17: case GDK_F18: case GDK_F19: case GDK_F20: break; case GDK_KP_Page_Up: case GDK_Page_Up: break; case GDK_KP_Page_Down: case GDK_Page_Down: break; case GDK_Tab: term->scan = switch_screen; break; case GDK_KP_Enter: case GDK_Return: term->scan = enter; term->code = 13; break; default: if (event->string[0] && !(event->state & event->state & GDK_CONTROL_MASK || event->state & GDK_MOD1_MASK)) { char ch = event->string[0]; if (deadkey) { switch (deadkey) { case '^': switch (ch) { case ' ': ch = '^'; break; case 'a': ch = 'â'; break; case 'e': ch = 'ê'; break; case 'i': ch = 'î'; break; case 'o': ch = 'ô'; break; case 'u': ch = 'û'; break; case 'A': ch = 'Â'; break; case 'E': ch = 'Ê'; break; case 'I': ch = 'Î'; break; case 'O': ch = 'Ô'; break; case 'U': ch = 'Û'; break; default: {}; } deadkey=0; break; case '¨': switch (ch) { case ' ': ch = '¨'; break; case 'a': ch = 'ä'; break; case 'e': ch = 'ë'; break; case 'i': ch = 'ï'; break; case 'o': ch = 'ö'; break; case 'u': ch = 'ü'; break; case 'y': ch = 'ÿ'; break; case 'A': ch = 'Ä'; break; case 'E': ch = 'Ë'; break; case 'I': ch = 'Ï'; break; case 'O': ch = 'Ö'; break; case 'U': ch = 'Ü'; break; default: {}; } deadkey=0; break; } } else if (ch=='^' || ch=='¨') deadkey=ch; if (!deadkey) { if (ch==' ') term->scan = space; term->code = ch; } } break; } } static gint gtk_term_key_press (GtkWidget *widget, GdkEventKey *event) { GtkTerm *term; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_TERM (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); term = GTK_TERM (widget); term->code = 0; term->scan = 0; if (term->editing) { if (event->keyval!=GDK_KP_Insert && event->keyval!=GDK_Insert) helpn=0; gtk_term_draw_caret(term,0); switch (event->keyval) { case GDK_Escape: term->scan = escape; e_remove_text(term->a,term->cur,term->promptlen,e_get_text_length(term->a,term->cur)-term->promptlen); term->pos = term->epos = term->promptlen; if (e_get_type(term->a,term->cur)==E_UDF) { e_append_text(term->a,term->cur,"endfunction"); term->pos += 11; term->epos = term->pos; } gtk_term_update_caret(term); gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } break; case GDK_KP_Up: case GDK_Up: if (event->state & GDK_SHIFT_MASK) { term->scan = cursor_up; if (term->hist>0) { term->hist--; e_remove_text(term->a,term->cur,term->promptlen,e_get_text_length(term->a,term->cur)-term->promptlen); e_append_text(term->a,term->cur,e_get_text(term->history,term->hist)); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); term->pos = term->epos = e_get_text_length(term->a,term->cur); gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } } else { gtk_term_cursor_up(term); } break; case GDK_KP_Down: case GDK_Down: if (event->state & GDK_SHIFT_MASK) { term->scan = cursor_down; if (term->histhistory)-1) { term->hist++; e_remove_text(term->a,term->cur,term->promptlen,e_get_text_length(term->a,term->cur)-term->promptlen); e_append_text(term->a,term->cur,e_get_text(term->history,term->hist)); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); term->pos = term->epos = e_get_text_length(term->a,term->cur); gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } } else { gtk_term_cursor_down(term); } break; case GDK_KP_Right: case GDK_Right: if (event->state & GDK_SHIFT_MASK) { term->scan = word_right; while ((e_get_text(term->a,term->cur))[term->pos] && (e_get_text(term->a,term->cur))[term->pos]!=' ') term->pos++; while ((e_get_text(term->a,term->cur))[term->pos]==' ') term->pos++; gtk_term_scroll_to_pos(term); term->epos = term->pos; } else { term->scan = cursor_right; if (term->epos==term->pos) { if ((e_get_text(term->a,term->cur))[term->pos]) { term->pos++;term->epos++; } } else { if (term->epos>term->pos) term->pos = term->epos; else term->epos = term->pos; } gtk_term_scroll_to_pos(term); } break; case GDK_KP_Left: case GDK_Left: if (event->state & GDK_SHIFT_MASK) { term->scan = word_left; while (term->pos>term->promptlen && (e_get_text(term->a,term->cur))[term->pos]==' ') term->pos--; while (term->pos>term->promptlen && (e_get_text(term->a,term->cur))[term->pos]!=' ') term->pos--; gtk_term_scroll_to_pos(term); term->epos = term->pos; } else { term->scan = cursor_left; if (term->epos==term->pos) { if (term->pos>term->promptlen) { term->pos--;term->epos--; } } else { if (term->epos>term->pos) term->epos=term->pos; else term->pos=term->epos; } gtk_term_scroll_to_pos(term); } break; case GDK_BackSpace: term->scan = backspace; if (term->pos>term->promptlen) { if (term->pos==term->epos) { term->pos--;term->epos--; gtk_term_update_caret(term); e_remove_text(term->a,term->cur,term->pos,1); } else { if (term->epos>term->pos) { e_remove_text(term->a,term->cur,term->pos,term->epos-term->pos); term->epos = term->pos; } else { e_remove_text(term->a,term->cur,term->epos,term->pos-term->epos); term->pos = term->epos; } } gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } break; case GDK_Delete: case GDK_KP_Delete: term->scan = deletekey; if (term->posa,term->cur)) { if (term->pos==term->epos) { e_remove_text(term->a,term->cur,term->pos,1); } else { if (term->epos>term->pos) { e_remove_text(term->a,term->cur,term->pos,term->epos-term->pos); term->epos = term->pos; } else { e_remove_text(term->a,term->cur,term->epos,term->pos-term->epos); term->pos = term->epos; } } gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } break; case GDK_KP_Insert: case GDK_Insert: if (!helpn && helphist<0) { gtk_term_edithelp(term); p=0; } if (helphist>=0) { e_remove_text(term->a,term->cur,term->promptlen,e_get_text_length(term->a,term->cur)-term->promptlen); e_append_text(term->a,term->cur,e_get_text(term->history,helphist)); term->pos = term->epos = term->promptlen; gtk_term_update_caret(term); gtk_term_redraw_current(term); term->pos = term->epos = e_get_text_length(term->a,term->cur); gtk_term_scroll_to_pos(term); } else if (helpnextepos-=l; e_remove_text(term->a,term->cur,term->pos,l); gtk_term_update_caret(term); } p=helpextend[helpnext++]; e_insert_text(term->a,term->cur,term->pos,p); term->epos+=strlen(p); gtk_term_scroll_to_pos(term); } if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } break; case GDK_KP_Home: case GDK_Home: term->scan = line_start; term->pos = term->epos = term->promptlen; gtk_term_scroll_to_pos(term); break; case GDK_KP_End: case GDK_End: term->scan = line_end; term->pos = term->epos = e_get_text_length(term->a,term->cur); gtk_term_scroll_to_pos(term); break; case GDK_KP_F1: case GDK_F1: term->scan = fk1; gtk_term_fkinsert(term,0); break; case GDK_KP_F2: case GDK_F2: term->scan = fk2; gtk_term_fkinsert(term,1); break; case GDK_KP_F3: case GDK_F3: term->scan = fk3; gtk_term_fkinsert(term,2); break; case GDK_KP_F4: case GDK_F4: term->scan = fk4; gtk_term_fkinsert(term,3); break; case GDK_F5: term->scan = fk5; gtk_term_fkinsert(term,4); break; case GDK_F6: term->scan = fk6; gtk_term_fkinsert(term,5); break; case GDK_F7: term->scan = fk7; gtk_term_fkinsert(term,6); break; case GDK_F8: term->scan = fk8; gtk_term_fkinsert(term,7); break; case GDK_F9: term->scan = fk9; gtk_term_fkinsert(term,8); break; case GDK_F10: term->scan = fk10; gtk_term_fkinsert(term,9); break; case GDK_F11: case GDK_F12: case GDK_F13: case GDK_F14: case GDK_F15: case GDK_F16: case GDK_F17: case GDK_F18: case GDK_F19: case GDK_F20: break; case GDK_KP_Page_Up: case GDK_Page_Up: /* scroll the view a page up */ gtk_term_adjustment_safe_set_value(term, term->v_adj->value-term->theight+1); break; case GDK_KP_Page_Down: case GDK_Page_Down: gtk_term_adjustment_safe_set_value(term, (gfloat)MIN(term->top+term->theight-1,e_get_length(term->a)-term->theight)); /* scroll the view a page down */ break; case GDK_Tab: term->scan = switch_screen; break; case GDK_KP_Enter: case GDK_Return: term->scan = enter; e_insert(term->history,e_get_length(term->history)-1,e_get_text(term->a,term->cur)+term->promptlen,0); if (e_get_length(term->history) > term->max_history) e_remove(term->history,0); term->hist=e_get_length(term->history)-1; set_editline(e_get_text(term->a,term->cur)+term->promptlen); return TRUE; default: if (event->string[0] && !(event->state & event->state & GDK_CONTROL_MASK || event->state & GDK_MOD1_MASK)) { char ch = event->string[0]; if (deadkey) { switch (deadkey) { case '^': switch (ch) { case ' ': ch = '^'; break; case 'a': ch = 'â'; break; case 'e': ch = 'ê'; break; case 'i': ch = 'î'; break; case 'o': ch = 'ô'; break; case 'u': ch = 'û'; break; case 'A': ch = 'Â'; break; case 'E': ch = 'Ê'; break; case 'I': ch = 'Î'; break; case 'O': ch = 'Ô'; break; case 'U': ch = 'Û'; break; default: {}; } deadkey=0; break; case '¨': switch (ch) { case ' ': ch = '¨'; break; case 'a': ch = 'ä'; break; case 'e': ch = 'ë'; break; case 'i': ch = 'ï'; break; case 'o': ch = 'ö'; break; case 'u': ch = 'ü'; break; case 'y': ch = 'ÿ'; break; case 'A': ch = 'Ä'; break; case 'E': ch = 'Ë'; break; case 'I': ch = 'Ï'; break; case 'O': ch = 'Ö'; break; case 'U': ch = 'Ü'; break; default: {}; } deadkey=0; break; } } else if (ch=='^' || ch=='¨') deadkey=ch; if (!deadkey) { if (ch==' ') term->scan = space; term->code = ch; if (term->pos!=term->epos) { if (term->epos>term->pos) { e_remove_text(term->a,term->cur,term->pos,term->epos-term->pos); term->epos = term->pos; } else { e_remove_text(term->a,term->cur,term->epos,term->pos-term->epos); term->pos = term->epos; } } e_insert_char(term->a,term->cur,term->pos,ch); term->pos++;term->epos = term->pos; gtk_term_scroll_to_pos(term); if (!term->changed) { g_signal_emit(GTK_OBJECT(term),gtk_term_signals[GTK_TERM_CHANGED],0); term->changed = 1; } } } break; } gtk_term_draw_caret(term,1); } else get_scan(event,term); if (event->state & GDK_CONTROL_MASK || event->state & GDK_MOD1_MASK) return FALSE; return TRUE; } gint gtk_term_redraw(GtkWidget *widget) { GtkTerm *term; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_TERM (widget), FALSE); term = GTK_TERM (widget); gtk_term_redraw_current(term); return FALSE; }