Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1703)
+++ ChangeLog	(working copy)
@@ -10,6 +10,18 @@
 
 2007-10-08 Rich Burridge <rich.burridge@sun.com>
 
+    * gcalctool/calctool.h:
+      gcalctool/display.c:
+      gcalctool/functions.c:
+      gcalctool/ce_tokeniser.l:
+      gcalctool/get.c:
+      gcalctool/gtk.c:
+      With lots of help from Sami Pietila <sampie@utu.fi>
+      Fix for bug #326938 – Display cursor in input area; allow home
+      and end keys.
+
+2007-10-08 Rich Burridge <rich.burridge@sun.com>
+
     * gcalctool/graphics.c:
       Fix for bug #484158 – Setting Accuracy is incorrect via the 0-9 
       places menu items.
Index: gcalctool/calctool.h
===================================================================
--- gcalctool/calctool.h	(revision 1703)
+++ gcalctool/calctool.h	(working copy)
@@ -358,6 +358,8 @@
     int doing_mi;      /* Set if adjusting the "show zeroes" menu item. */
     int down;          /* Indicates is a mouse button is down. */
     int error;         /* Indicates some kind of display error. */
+    int ghost_zero;    /* Flag to indicate display with "0", actually 
+                           having empty content. */
     int math_error;    /* Math error (used in expression mode) */
     int hyperbolic;    /* If set, trig functions will be hyperbolic. */
     int iconic;        /* Set if window is currently iconic. */
@@ -549,7 +551,9 @@
 void mptanh(int *, int *);
 
 void make_exp(char *number, int t[MP_SIZE]);
+void exp_replace(char *text);
+void insert_to_cursor(char *text);
+void get_expr_from_display();
+void delete_from_cursor();
 
-
-
 #endif /*CALCTOOL_H*/
Index: gcalctool/display.c
===================================================================
--- gcalctool/display.c	(revision 1703)
+++ gcalctool/display.c	(working copy)
@@ -119,6 +119,7 @@
     STRNCPY(v->display, make_number(v->MPdisp_val, v->base, FALSE), 
             MAXLINE - 1);
     set_display(v->display, FALSE);
+    v->ghost_zero = 1;
 
     if (initialise == TRUE) {
         v->show_paren = 0;
@@ -635,11 +636,13 @@
                 }
                 write_display(str);
                 free(str);
+                v->ghost_zero = 0;
             } else {
                 int MP1[MP_SIZE];
 
                 do_zero(MP1);
                 show_display(MP1);
+                v->ghost_zero = 1;
             }
         }    
         break;
Index: gcalctool/functions.c
===================================================================
--- gcalctool/functions.c	(revision 1703)
+++ gcalctool/functions.c	(working copy)
@@ -281,6 +281,20 @@
 }
 
 
+void
+exp_insert(char *text)
+{
+    // struct exprm_state *e;
+    // e = get_state();
+    // write_display(e->expression);
+    if (v->ghost_zero) {
+        write_display("");
+        v->ghost_zero = 0;
+    }
+    insert_to_cursor(text);
+    get_expr_from_display();
+}
+
 void 
 exp_del() 
 {
@@ -332,7 +346,7 @@
 }
 
 
-static void
+void
 exp_replace(char *text)
 {
     struct exprm_state *e = get_state();
@@ -479,6 +493,7 @@
 void
 do_expression()
 {
+    int update_display = 0; // Update whole display. Looses cursor position.
     char *btext = NULL;
     struct exprm_state *e;
     int non_empty_expression;
@@ -500,6 +515,7 @@
 	if (!strcmp(e->expression, "Ans")) {
 	    if (e->button.flags & number) {
 		exp_del(); 
+                update_display = 1;
 	    }	
 	}
     } else {
@@ -508,7 +524,7 @@
 	    char *zero = NULL;
 	    do_zero(MP1);
 	    zero = make_number(MP1, v->base, FALSE);
-	    exp_append(zero);
+	    exp_insert(zero);
 	}
     }
 
@@ -518,8 +534,10 @@
 	    char buf[1024];
 	    snprintf(buf, 128, "%s(Ans)", btext);
 	    exp_replace(buf);
+            update_display = 1;
     } else if (e->button.flags & clear) {
         exp_del();
+        update_display = 1;
         set_error_state(FALSE);
         MPstr_to_num("0", DEC, e->ans);
     } else if (e->button.flags & regrcl) {
@@ -528,11 +546,11 @@
         int n = '0' +  i;
 
         snprintf(reg, 3, "R%c", n);
-        exp_append(reg);
+        exp_insert(reg);
     } else if (e->button.flags & con) {
         int *MPval = v->MPcon_vals[char_val(e->button.value[0])];
 
-        exp_append(make_number(MPval, v->base, FALSE));
+        exp_insert(make_number(MPval, v->base, FALSE));
     } else if (e->button.flags & bsp) {
         if (exp_has_postfix(e->expression, "Ans")) { 
             char *ans = make_number(e->ans, v->base, FALSE);   
@@ -553,15 +571,17 @@
                     reg_val = make_number(MP_reg, v->base, FALSE);
                     /* Remove "Rx" postfix. */
                     exp_del_char(&e->expression, 2);
-                    exp_append(reg_val);
+                    exp_insert(reg_val);
                 }
             }
         }
-        exp_del_char(&e->expression, 1);
+        delete_from_cursor();
     } else if (e->button.flags & neg) {
         exp_negate();
+        update_display = 1;
     } else if (e->button.flags & inv) {
         exp_inv();
+        update_display = 1;
     } else if (e->button.flags & enter) {
 	  if (e->expression) {
 	    if (strcmp(e->expression, "Ans")) {
@@ -571,6 +591,7 @@
 		  if (!ret) {
 			mpstr(MPval, e->ans);
 			exp_replace("Ans");
+                        update_display = 1;
 		  } else {
 			char *message = NULL;
 
@@ -604,20 +625,22 @@
 		  perform_undo();
 		  if (is_undo_step()) {
 			perform_undo();
+                        update_display = 1;
 		  }
 	    }
 	  }
     } else {
-	exp_append(btext);
+	exp_insert(btext);
 	if (e->button.flags & func) {
-	    exp_append("(");
+	    exp_insert("(");
 	}
     }
 
     free(btext);
     btext = NULL;
-    refresh_display();
-    return;
+    if (update_display) {
+        refresh_display();
+    }
 }
 
 
@@ -830,7 +853,7 @@
 	if (ret) {
 	    update_statusbar(_("No sane value to convert"), 
 			     "gtk-dialog-error");
-	} else {
+	} else if (!v->ghost_zero) {
 	    mpstr(MP, e->ans);
 	    exp_replace("Ans");
 	    make_registers();
@@ -1211,7 +1234,7 @@
         if (ret) {
             update_statusbar(_("No sane value to convert"),
                              "gtk-dialog-error");
-        } else {
+        } else if (!v->ghost_zero) {
             mpstr(MP, e->ans);
             exp_replace("Ans");
             make_registers();
Index: gcalctool/get.c
===================================================================
--- gcalctool/get.c	(revision 1703)
+++ gcalctool/get.c	(working copy)
@@ -246,6 +246,7 @@
 {
     int acc, i, n, size;
 
+    v->ghost_zero    = 1;      /* Display initially has empty content. */
     v->accuracy      = 9;      /* Initial accuracy. */
     v->show_zeroes   = FALSE;  /* Don't show trailing zeroes. */
     v->base          = DEC;    /* Initial base. */
Index: gcalctool/ce_tokeniser.l
===================================================================
--- gcalctool/ce_tokeniser.l	(revision 1703)
+++ gcalctool/ce_tokeniser.l	(working copy)
@@ -49,50 +49,50 @@
 
 %%
 
-"Abs" {return tABS;}
-"Acosh" {return tACOSH;}
-"Acos" {return tACOS;}
-"AND" {return tAND;}
-"Ans" {return tANS;}
-"Asinh" {return tASINH;}
-"Asin" {return tASIN;}
-"Atanh" {return tATANH;}
-"Atan" {return tATAN;}
-"Cbrt" {return tCBRT;}
-"Chs" {return tCHS;}
-"Clr" {return tCLR;}
-"Cosh" {return tCOSH;}
-"Cos" {return tCOS;}
-"Ctrm" {return tCTRM;}
-"Ddb" {return tDDB;}
-"Eng" {return tEXP;}
-"Frac" {return tFRAC;}
-"Fv" {return tFV;}
-"Int" {return tINT;}
-"Ln" {return tLN;}
-"Log" {return tLOG10;}
-"Mod" {return tMOD;}
-"NOT" {return tNOT;}
-"OR" {return tOR;}
-"Pi" {return tPI;}
-"Pmt" {return tPMT;}
-"Pv" {return tPV;}
-"Rand" {return tRAND;}
-"Rate" {return tRATE;}
-"Rcl" {return tRCL;}
-"Sinh" {return tSINH;}
-"Sin" {return tSIN;}
-"Sln" {return tSLN;}
-"Sqrt" {return tSQRT;}
-"Sto" {return tSTO;}
-"Syd" {return tSYD;}
-"Tanh" {return tTANH;}
-"Tan" {return tTAN;}
-"Term" {return tTERM;}
-"u16" {return tU16;}
-"u32" {return tU32;}
-"XNOR" {return tXNOR;}
-"XOR" {return tXOR;}
+"abs"|"Abs"|"ABS" {return tABS;}
+"acosh"|"Acosh"|"ACOSH" {return tACOSH;}
+"acos"|"Acos"|"ACOS" {return tACOS;}
+"and"|"And"|"AND" {return tAND;}
+"ans"|"Ans"|"ANS" {return tANS;}
+"asinh"|"Asinh"|"ASINH" {return tASINH;}
+"asin"|"Asin"|"ASIN" {return tASIN;}
+"atanh"|"Atanh"|"ATANH" {return tATANH;}
+"atan"|"Atan"|"ATAN" {return tATAN;}
+"cbrt"|"Cbrt"|"CBRT" {return tCBRT;}
+"chs"|"Chs"|"CHS" {return tCHS;}
+"clr"|"Clr"|"CLR" {return tCLR;}
+"cosh"|"Cosh"|"COSH" {return tCOSH;}
+"cos"|"Cos"|"COS" {return tCOS;}
+"ctrm"|"Ctrm"|"CTRM" {return tCTRM;}
+"dbg"|"Ddb"|"DDB" {return tDDB;}
+"eng"|"Eng"|"ENG" {return tEXP;}
+"frac"|"Frac"|"FRAC" {return tFRAC;}
+"fv"|"Fv"|"FV" {return tFV;}
+"int"|"Int"|"INT" {return tINT;}
+"ln"|"Ln"|"LN" {return tLN;}
+"log"|"Log"|"LOG" {return tLOG10;}
+"mod"|"Mod"|"MOD" {return tMOD;}
+"not"|"Not"|"NOT" {return tNOT;}
+"or"|"Or"|"OR" {return tOR;}
+"pi"|"Pi"|"PI" {return tPI;}
+"pmt"|"Pmt"|"PMT" {return tPMT;}
+"pv"|"Pv"|"PV" {return tPV;}
+"rand"|"Rand"|"RAND" {return tRAND;}
+"rate"|"Rate"|"RATE" {return tRATE;}
+"rcl"|"Rcl"|"RCL" {return tRCL;}
+"sinh"|"Sinh"|"SINH" {return tSINH;}
+"sin"|"Sin"|"SIN" {return tSIN;}
+"sln"|"Sln"|"SLN" {return tSLN;}
+"sqrt"|"Sqrt"|"SQRT" {return tSQRT;}
+"sto"|"Sto"|"STO" {return tSTO;}
+"syd"|"Syd"|"SYD" {return tSYD;}
+"tanh"|"Tanh"|"TANH" {return tTANH;}
+"tan"|"Tan"|"TAN" {return tTAN;}
+"term"|"Term"|"TERM" {return tTERM;}
+"u16"|"u16"|"U16" {return tU16;}
+"u32"|"u32"|"U32" {return tU32;}
+"xnor"|"Xnor"|"XNOR" {return tXNOR;}
+"xor"|"Xor"|"XOR" {return tXOR;}
 
 "R"{DEC}+ {
 celval.integer = atoi(yytext+1);  
Index: gcalctool/gtk.c
===================================================================
--- gcalctool/gtk.c	(revision 1703)
+++ gcalctool/gtk.c	(working copy)
@@ -178,6 +178,8 @@
 static gboolean dismiss_rframe(GtkWidget *, GdkEvent *, gpointer);
 static gboolean dismiss_spframe(GtkWidget *, GdkEvent *, gpointer);
 static gboolean kframe_key_press_cb(GtkWidget *, GdkEventKey *, gpointer);
+static gboolean display_focus_in_cb(GtkWidget *, GdkEventKey *, gpointer);
+static gboolean display_focus_out_cb(GtkWidget *, GdkEventKey *, gpointer);
 static gboolean mouse_button_cb(GtkWidget *, GdkEventButton *, gpointer);
 static gboolean spframe_key_cb(GtkWidget *, GdkEventKey *, gpointer);
 
@@ -1360,8 +1362,8 @@
     char *hn;
     GError *error;
     GtkWidget *event_box, *view_widget;
-    GtkTextBuffer *buffer;
     AtkObject *aob;
+    PangoFontDescription *font_desc;
 
     v->tool_label = NULL;
     if (v->titleline == NULL) {
@@ -1443,11 +1445,26 @@
 
     event_box = gtk_event_box_new();
     X->display_item = gtk_text_view_new();
+    gtk_widget_ensure_style(X->display_item);
+    font_desc = pango_font_description_copy(X->display_item->style->font_desc);
+    pango_font_description_set_size(font_desc, 16 * PANGO_SCALE);
+    gtk_widget_modify_font(X->display_item, font_desc);
+    pango_font_description_free(font_desc);
+
     gtk_widget_set_name(X->display_item, "displayitem");
     g_signal_connect(G_OBJECT(X->display_item), "button_release_event",
                      G_CALLBACK(mouse_button_cb),
                      NULL);
 
+    g_signal_connect(G_OBJECT(X->display_item), "focus_in_event",
+                     G_CALLBACK(display_focus_in_cb), NULL);
+
+    g_signal_connect(G_OBJECT(X->display_item), "focus_out_event",
+                     G_CALLBACK(display_focus_out_cb), NULL);
+
+    g_signal_connect(G_OBJECT(X->display_item), "focus_out_event",
+                     G_CALLBACK(display_focus_out_cb), NULL);
+
     /* Detect when populating the right-click menu to enable pasting */
     g_signal_connect(G_OBJECT(X->display_item), "populate-popup",
                      G_CALLBACK(buffer_populate_popup_cb), NULL);
@@ -1455,12 +1472,10 @@
     gtk_text_view_set_justification(GTK_TEXT_VIEW(X->display_item),
                                     GTK_JUSTIFY_RIGHT);
     gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(X->display_item), GTK_WRAP_NONE);
-    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
-    gtk_text_buffer_create_tag(buffer, "x-large", "scale", PANGO_SCALE_X_LARGE, 
-                               NULL);			       
 
     gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(X->display_item), TRUE);
-    gtk_text_view_set_editable(GTK_TEXT_VIEW(X->display_item), FALSE);
+    gtk_text_view_set_editable(GTK_TEXT_VIEW(X->display_item), 
+                               (v->syntax == exprs));
     aob = gtk_widget_get_accessible(GTK_WIDGET(X->display_item));
     atk_object_set_description(aob, "Result Region");
 
@@ -2213,12 +2228,96 @@
     return(FALSE);
 }
 
+
+void
+get_expr_from_display()
+{
+    char *text;
+    GtkTextBuffer *buffer;
+    GtkTextIter start, end;
+
+    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
+    gtk_text_buffer_get_bounds(buffer, &start, &end);
+    
+    text = gtk_text_buffer_get_text(
+                 gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item)),
+                                 &start,
+                                 &end,
+                                 FALSE);
+    exp_replace(text);
+}
+
+
+void
+delete_from_cursor()
+{
+    GtkTextBuffer *buffer;
+    GtkTextIter start, end, loc;
+    gint pos;
+
+    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
+    gtk_text_buffer_get_bounds(buffer, &start, &end);
+
+    g_object_get(G_OBJECT(buffer), "cursor-position", &pos, NULL);
+
+    gtk_text_buffer_get_iter_at_offset(buffer,
+                                       &loc,
+                                       pos);
+
+    gtk_text_buffer_backspace(buffer, &loc, TRUE, TRUE);
+
+}
+
+
+void
+insert_to_cursor(char *text)
+{
+    GtkTextBuffer *buffer = NULL;
+    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
+    gtk_text_buffer_insert_at_cursor(buffer,
+                                     text,
+                                     strlen(text));
+}
+
+
+static gboolean
+display_focus_out_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+    if (v->syntax == exprs) {
+        get_expr_from_display();
+    } 
+
+    return(FALSE);
+}
+
+
+static gboolean
+display_focus_in_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+    v->ghost_zero = 0;
+
+    return(FALSE);
+}
+
+
 /*ARGSUSED*/
 static gboolean
 kframe_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
     int retval = FALSE;
 
+    if (gtk_widget_is_focus(X->display_item) && (v->syntax == exprs)) {
+
+        if ((event->keyval == GDK_equal) || 
+            (event->keyval == GDK_KP_Enter) || 
+            (event->keyval == GDK_Return) || 
+            (event->keyval == GDK_equal)) {
+            get_expr_from_display();
+        } else {
+            return(FALSE);
+        }
+    }
+
     if (check_for_localized_numeric_point(event->keyval) == TRUE) {
         event->state = 0;
         event->keyval = GDK_KP_Decimal;
@@ -2650,6 +2749,8 @@
     }
     put_resource(R_SYNTAX, Rsstr[v->syntax]);
     set_mode(v->modetype);
+    gtk_text_view_set_editable(GTK_TEXT_VIEW(X->display_item), 
+                               (v->syntax == exprs));
 }
 
 
@@ -3180,12 +3281,7 @@
         if (minimize_changes) {
             if (len1 < len2 && strncmp(text, str, len1) == 0) {
                 /* Text insertion */
-                gtk_text_buffer_insert_with_tags_by_name(buffer,
-                                                         &end,
-                                                         str + len1,
-                                                         -1,
-                                                         "x-large",
-                                                         NULL);
+                gtk_text_buffer_insert(buffer, &end, str + len1, -1);
                 done = TRUE;
             } else if (len1 > len2 && strncmp(text, str, len2) == 0) {
                /* Text deletion */
@@ -3199,12 +3295,7 @@
         if (!done) {
             gtk_text_buffer_delete(buffer, &start, &end);
 
-            gtk_text_buffer_insert_with_tags_by_name(buffer,
-                                                     &end,
-                                                     str,
-                                                     -1,
-                                                     "x-large",
-                                                     NULL);
+            gtk_text_buffer_insert(buffer, &end, str, -1);
         }
     }
     scroll_right();
@@ -3227,12 +3318,7 @@
 
     gtk_text_buffer_delete(buffer, &start, &end);
     
-    gtk_text_buffer_insert_with_tags_by_name(buffer,
-					     &end,
-					     str,
-					     -1,
-					     "x-large",
-					     NULL);
+    gtk_text_buffer_insert(buffer, &end, str, -1);
     scroll_right();
     g_free(text);
 }
