more simplification, got gtk.c under 3k lines
[gcalctool.git] / gcalctool / gtk.c
blob8be1e06b5301705329a56fbe624f6fc0318b881e
2 /* $Header$
4 * Copyright (c) 1987-2007 Sun Microsystems, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <limits.h>
26 #include <sys/param.h>
27 #include <sys/stat.h>
28 #include <netdb.h>
29 #include <gtk/gtk.h>
30 #include <gdk/gdkx.h>
31 #include <gdk/gdkkeysyms.h>
32 #include <glade/glade.h>
34 #include "ui.h"
36 #include "config.h"
37 #include "dsdefs.h"
38 #include "functions.h"
39 #include "lr_parser.h"
40 #include "ce_parser.h"
41 #include "mpmath.h"
42 #include "display.h"
43 #include "get.h"
45 #define MAX_ACCELERATORS 8
46 struct button_widget {
47 int key;
48 char *widget_name;
49 guint accelerator_mods[MAX_ACCELERATORS];
50 guint accelerator_keys[MAX_ACCELERATORS];
53 /* Window titles dependant on mode */
54 static char *titles[] = {
55 N_("Calculator"), N_("Calculator - Advanced"), N_("Calculator - Financial"),
56 N_("Calculator - Scientific")
59 /* Window titles dependant on mode and hostname */
60 static char *hostname_titles[] = {
61 N_("Calculator [%s]"), N_("Calculator [%s] - Advanced"), N_("Calculator [%s] - Financial"),
62 N_("Calculator [%s] - Scientific")
65 /* This table shows the keyboard values that are currently being used:
67 * | a b c d e f g h i j k l m n o p q r s t u v w x y z
68 *-----------+-----------------------------------------------------
69 * Lower: | a b c d e f i l m n p r s t u v x
70 * Upper: | A C D E F G J K L M N P R S T X Y
71 * Numeric: | 0 1 2 3 4 5 6 7 8 9
72 * Other: | @ . + - * / = % ( ) # < > [ ] { } | & ~ ^ ? ! :
73 * | BackSpace Delete Return
74 *-----------+-----------------------------------------------------
77 static struct button_widget button_widgets[] = {
78 {KEY_0, "0",
79 { 0, GDK_SHIFT_MASK, 0, 0, 0 },
80 { GDK_0, GDK_0, GDK_KP_0, GDK_KP_Insert, 0 }},
82 {KEY_1, "1",
83 { 0, GDK_SHIFT_MASK, 0, 0, 0, 0 },
84 { GDK_1, GDK_1, GDK_KP_1, GDK_KP_End, GDK_R13, 0 }},
86 {KEY_2, "2",
87 { 0, GDK_SHIFT_MASK, 0, 0, 0 },
88 { GDK_2, GDK_2, GDK_KP_2, GDK_KP_Down, 0 }},
90 {KEY_3, "3",
91 { 0, GDK_SHIFT_MASK, 0, 0, 0, 0 },
92 { GDK_3, GDK_3, GDK_KP_3, GDK_KP_Page_Down, GDK_R15, 0 }},
94 {KEY_4, "4",
95 { 0, GDK_SHIFT_MASK, 0, 0, 0 },
96 { GDK_4, GDK_4, GDK_KP_4, GDK_KP_Left, 0 }},
98 {KEY_5, "5",
99 { 0, GDK_SHIFT_MASK, 0, 0, 0, 0 },
100 { GDK_5, GDK_5, GDK_KP_5, GDK_KP_Begin, GDK_R11, 0 }},
102 {KEY_6, "6",
103 { 0, GDK_SHIFT_MASK, 0, 0, 0 },
104 { GDK_6, GDK_6, GDK_KP_6, GDK_KP_Right, 0 }},
106 {KEY_7, "7",
107 { 0, GDK_SHIFT_MASK, 0, 0, 0, 0 },
108 { GDK_7, GDK_7, GDK_KP_7, GDK_KP_Home, GDK_R7, 0 }},
110 {KEY_8, "8",
111 { 0, GDK_SHIFT_MASK, 0, 0, 0 },
112 { GDK_8, GDK_8, GDK_KP_8, GDK_KP_Up, 0 }},
114 {KEY_9, "9",
115 { 0, GDK_SHIFT_MASK, 0, 0, 0, 0 },
116 { GDK_9, GDK_9, GDK_KP_9, GDK_KP_Page_Up, GDK_R9, 0 }},
118 {KEY_A, "a",
119 { 0, 0 },
120 { GDK_a, 0 }},
122 {KEY_B, "b",
123 { 0, 0 },
124 { GDK_b, 0 }},
126 {KEY_C, "c",
127 { 0, 0 },
128 { GDK_c, 0 }},
130 {KEY_D, "d",
131 { 0, 0 },
132 { GDK_d, 0 }},
134 {KEY_E, "e",
135 { 0, 0 },
136 { GDK_e, 0 }},
138 {KEY_F, "f",
139 { 0, 0 },
140 { GDK_f, 0 }},
142 {KEY_CLEAR, "clear_simple",
143 { 0, 0 },
144 { GDK_Delete, 0 }},
146 {KEY_CLEAR, "clear_advanced",
147 { 0, 0 },
148 { GDK_Delete, 0 }},
150 {KEY_SHIFT, "shift_left",
151 { GDK_SHIFT_MASK, 0 },
152 { GDK_less, 0 }},
154 {KEY_SHIFT, "shift_right",
155 { GDK_SHIFT_MASK, 0 },
156 { GDK_greater, 0 }},
158 {KEY_SET_ACCURACY, "accuracy",
159 { GDK_SHIFT_MASK, 0 },
160 { GDK_A, 0 }},
162 {KEY_CONSTANT, "constants",
163 { GDK_SHIFT_MASK, 0, 0 },
164 { GDK_numbersign, GDK_numbersign, 0 }},
166 {KEY_FUNCTION, "functions",
167 { GDK_SHIFT_MASK, 0 },
168 { GDK_F, 0 }},
170 {KEY_STORE, "store",
171 { GDK_SHIFT_MASK, 0 },
172 { GDK_S, 0 }},
174 {KEY_RECALL, "recall",
175 { GDK_SHIFT_MASK, 0 },
176 { GDK_R, 0 }},
178 {KEY_EXCHANGE, "exchange",
179 { GDK_SHIFT_MASK, 0 },
180 { GDK_X, 0 }},
182 {KEY_CLEAR_ENTRY, "clear_entry_simple",
183 { GDK_CONTROL_MASK, 0, 0 },
184 { GDK_BackSpace, GDK_Escape, 0 }},
186 {KEY_CLEAR_ENTRY, "clear_entry_advanced",
187 { GDK_CONTROL_MASK, 0, 0 },
188 { GDK_BackSpace, GDK_Escape, 0 }},
190 {KEY_BACKSPACE, "backspace_simple",
191 { 0, 0 },
192 { GDK_BackSpace, 0 }},
194 {KEY_BACKSPACE, "backspace_advanced",
195 { 0, 0 },
196 { GDK_BackSpace, 0 }},
198 {KEY_NUMERIC_POINT, "numeric_point",
199 { 0, 0, 0, 0 },
200 { GDK_period, GDK_KP_Decimal, GDK_KP_Delete, GDK_KP_Separator, 0 }},
202 {KEY_CALCULATE, "result",
203 { 0, 0, 0, GDK_SHIFT_MASK, 0 },
204 { GDK_equal, GDK_KP_Enter, GDK_Return, GDK_equal, 0 }},
206 {KEY_START_BLOCK, "start_group",
207 { GDK_SHIFT_MASK, 0 },
208 { GDK_parenleft, 0 }},
210 {KEY_END_BLOCK, "end_group",
211 { GDK_SHIFT_MASK, 0 },
212 { GDK_parenright, 0 }},
214 {KEY_ADD, "add",
215 { GDK_SHIFT_MASK, 0, 0, 0 },
216 { GDK_plus, GDK_plus, GDK_KP_Add, 0 }},
218 {KEY_SUBTRACT, "subtract",
219 { 0, 0, 0, 0 },
220 { GDK_minus, GDK_KP_Subtract, GDK_R4, 0 }},
222 {KEY_MULTIPLY, "multiply",
223 { GDK_SHIFT_MASK, 0, 0, 0, 0 },
224 { GDK_asterisk, GDK_KP_Multiply, GDK_x, GDK_R6, 0 }},
226 {KEY_DIVIDE, "divide",
227 { 0, GDK_SHIFT_MASK, 0, 0, GDK_SHIFT_MASK, 0 },
228 { GDK_slash, GDK_slash, GDK_KP_Divide, GDK_R5, GDK_slash, 0 }},
230 {KEY_CHANGE_SIGN, "change_sign_simple",
231 { GDK_SHIFT_MASK, 0 },
232 { GDK_C, 0 }},
234 {KEY_CHANGE_SIGN, "change_sign_advanced",
235 { GDK_SHIFT_MASK, 0 },
236 { GDK_C, 0 }},
238 {KEY_INTEGER, "integer_portion",
239 { 0, 0 },
240 { GDK_i, 0 }},
242 {KEY_FRACTION, "fractional_portion",
243 { GDK_SHIFT_MASK, 0 },
244 { GDK_colon, 0 }},
246 {KEY_PERCENTAGE, "percentage",
247 { GDK_SHIFT_MASK, 0 },
248 { GDK_percent, 0 }},
250 {KEY_SQUARE, "square",
251 { GDK_SHIFT_MASK, 0 },
252 { GDK_at, 0 }},
254 {KEY_SQUARE_ROOT, "sqrt",
255 { 0, 0 },
256 { GDK_s, 0 }},
258 {KEY_RECIPROCAL, "reciprocal",
259 { 0, 0 },
260 { GDK_r, 0 }},
262 {KEY_ABSOLUTE_VALUE, "abs",
263 { 0, 0 },
264 { GDK_u, 0 }},
266 {KEY_MASK_16, "mask_16",
267 { 0, 0 },
268 { GDK_bracketright, 0 }},
270 {KEY_MASK_32, "mask_32",
271 { 0, 0 },
272 { GDK_bracketleft, 0 }},
274 {KEY_MODULUS_DIVIDE, "modulus_divide",
275 { GDK_SHIFT_MASK, 0 },
276 { GDK_M, 0 }},
278 {KEY_EXPONENTIAL, "exponential",
279 { GDK_SHIFT_MASK, 0 },
280 { GDK_E, 0 }},
282 {KEY_E_POW_X, "pow_e",
283 { GDK_SHIFT_MASK, 0 },
284 { GDK_braceleft, 0 }},
286 {KEY_10_POW_X, "pow_10",
287 { GDK_SHIFT_MASK, 0 },
288 { GDK_braceright, 0 }},
290 {KEY_X_POW_Y, "x_pow_y",
291 { GDK_SHIFT_MASK, GDK_SHIFT_MASK, 0 },
292 { GDK_caret, GDK_asciicircum, 0 }},
294 {KEY_NATURAL_LOGARITHM, "natural_logarithm",
295 { GDK_SHIFT_MASK, 0 },
296 { GDK_N, 0 }},
298 {KEY_LOGARITHM, "logarithm",
299 { GDK_SHIFT_MASK, 0 },
300 { GDK_G, 0 }},
302 {KEY_FACTORIAL, "factorial",
303 { GDK_SHIFT_MASK, 0 },
304 { GDK_exclam, 0 }},
306 {KEY_RANDOM, "random",
307 { GDK_SHIFT_MASK, 0 },
308 { GDK_question, 0 }},
310 {KEY_SIN, "sine",
311 { GDK_SHIFT_MASK, 0 },
312 { GDK_K, 0 }},
314 {KEY_COS, "cosine",
315 { GDK_SHIFT_MASK, 0 },
316 { GDK_J, 0 }},
318 {KEY_TAN, "tangent",
319 { GDK_SHIFT_MASK, 0 },
320 { GDK_L, 0 }},
322 {KEY_NOT, "not",
323 { GDK_SHIFT_MASK, 0 },
324 { GDK_asciitilde, 0 }},
326 {KEY_OR, "or",
327 { GDK_SHIFT_MASK, 0 },
328 { GDK_bar, 0 }},
330 {KEY_AND, "and",
331 { GDK_SHIFT_MASK, 0 },
332 { GDK_ampersand, 0 }},
334 {KEY_XOR, "xor",
335 { 0 },
336 { 0 }},
338 {KEY_XNOR, "xnor",
339 { 0, 0 },
340 { GDK_n, 0 }},
342 {KEY_FINC_CTRM, "finc_compounding_term",
343 { 0, 0 },
344 { GDK_m, 0 }},
346 {KEY_FINC_DDB, "finc_double_declining_depreciation",
347 { GDK_SHIFT_MASK, 0 },
348 { GDK_D, 0 }},
350 {KEY_FINC_FV, "finc_future_value",
351 { 0, 0 },
352 { GDK_v, 0 }},
354 {KEY_FINC_PMT, "finc_periodic_payment",
355 { GDK_SHIFT_MASK, 0 },
356 { GDK_P, 0 }},
358 {KEY_FINC_PV, "finc_present_value",
359 { 0, 0 },
360 { GDK_p, 0 }},
362 {KEY_FINC_RATE, "finc_periodic_interest_rate",
363 { GDK_SHIFT_MASK, 0 },
364 { GDK_T, 0 }},
366 {KEY_FINC_SLN, "finc_straight_line_depreciation",
367 { 0, 0 },
368 { GDK_l, 0 }},
370 {KEY_FINC_SYD, "finc_sum_of_the_years_digits_depreciation",
371 { 0, 0 },
372 { GDK_Y, 0 }},
374 {KEY_FINC_TERM, "finc_term",
375 { 0, 0 },
376 { GDK_T, 0 }},
378 #define NBUTTONS (sizeof(button_widgets) / sizeof(struct button_widget))
380 #define UI_FILE PACKAGE_GLADE_DIR "/gcalctool.glade"
382 #define MAXBITS 64 /* Bit panel: number of bit fields. */
384 #define GET_WIDGET(name) \
385 glade_xml_get_widget(X->ui, (name))
387 #define SET_MENUBAR_ITEM_STATE(name, state) \
388 g_object_set_data(G_OBJECT(GET_WIDGET(name)), "sensitive", \
389 GINT_TO_POINTER(state));
391 #define CONNECT_SIGNAL(name) glade_xml_signal_connect(X->ui, #name, \
392 G_CALLBACK(name))
394 struct Xobject { /* Gtk+/Xlib graphics object. */
395 GdkAtom clipboard_atom;
396 GdkAtom primary_atom;
398 GladeXML *ui;
400 GtkWidget *kframe; /* Main window. */
402 GtkTreeModel *constants_model;
403 GtkWidget *con_dialog; /* Edit constants dialog. */
405 GtkTreeModel *functions_model;
406 GtkWidget *fun_dialog; /* Edit functions dialog. */
407 GtkWidget *menubar; // FIXME: Why is this needed?
409 GtkWidget *bit_panel;
410 GtkWidget *bits[MAXBITS]; /* The 0/1 labels in the bit panel. */
412 GtkWidget *status_image; /* Statusbar image */
413 GtkWidget *statusbar;
415 GtkWidget *aframe; /* ASCII window. */
416 GtkWidget *aframe_ch;
418 GtkWidget *display_item; /* Calculator display. */
419 GtkTextBuffer *display_buffer; /* Buffer used in display */
420 GtkWidget *scrolledwindow; /* Scrolled window for display_item. */
422 GtkWidget *rframe; /* Register window. */
423 GtkWidget *regs[MAX_REGISTERS]; /* Memory registers. */
425 GtkWidget *spframe; /* Set Precision window. */
426 GtkWidget *precision_spin;
428 GtkWidget *buttons[NBUTTONS];
429 GtkWidget *digit_buttons[16];
430 GtkWidget *clear_buttons[2];
432 GtkWidget *bas_panel; /* Panel containing basic mode widgets. */
433 GtkWidget *adv_panel; /* Panel containing advanced mode widgets. */
434 GtkWidget *fin_panel; /* Panel containing financial mode widgets. */
435 GtkWidget *sci_panel; /* Panel containing scientific mode widgets. */
436 GtkWidget *mode_panel; /* Panel containing scientific mode widgets. */
438 /* Labels for popup menus */
439 GtkWidget *constant_menu_labels[MAX_CONSTANTS];
440 GtkWidget *function_menu_labels[MAX_FUNCTIONS];
441 GtkWidget *memory_store_labels[MAX_REGISTERS];
442 GtkWidget *memory_recall_labels[MAX_REGISTERS];
443 GtkWidget *memory_exchange_labels[MAX_REGISTERS];
445 /* Scientific mode widgets */
446 GtkWidget *hyperbolic_toggle; /* Hyperbolic mode. */
447 GtkWidget *inverse_toggle; /* Inverse mode. */
448 GtkWidget *base[MAXBASES]; /* Numeric base radio buttons. */
449 GtkWidget *disp[MAXDISPMODES]; /* Numeric display mode. */
450 GtkWidget *trig[MAXTRIGMODES]; /* Trigonometric mode. */
452 int menuval; /* Index to button array at menu time. */
453 char *lnp; /* Localized numerical point (UTF8 format) */
456 typedef struct Xobject *XVars;
458 enum {
459 COLUMN_NUMBER,
460 COLUMN_VALUE,
461 COLUMN_DESCRIPTION,
462 COLUMN_EDITABLE,
463 NUM_COLUMNS
466 static XVars X;
469 void
470 ui_set_syntax_mode(enum syntax mode)
472 struct exprm_state *e;
473 GtkWidget *widget;
475 /* TODO: Always do clear things when mode is changed. */
476 v->syntax = mode;
477 switch (v->syntax) {
478 case NPA:
479 v->noparens = 0;
480 MPstr_to_num("0", DEC, v->MPdisp_val);
481 show_display(v->MPdisp_val);
482 ui_set_statusbar(_("Activated no operator precedence mode"), "");
483 clear_undo_history();
484 break;
486 case EXPRS:
487 e = get_state();
488 MPstr_to_num("0", DEC, e->ans);
489 exp_del();
490 show_display(e->ans);
491 ui_set_statusbar(
492 _("Activated expression mode with operator precedence"), "");
493 break;
495 default:
496 assert(0);
498 set_resource(R_SYNTAX, Rsstr[v->syntax]);
499 ui_set_mode(v->modetype);
500 // FIXME: We can't allow the display to be editable. See bug #326938
501 gtk_text_view_set_editable(GTK_TEXT_VIEW(X->display_item),
502 (v->syntax == EXPRS));
504 /* Use loaded Arithmetic Precedence mode setting. */
505 // FIXME: Merge with arithmetic_mode_cb()
506 if (v->syntax == EXPRS) {
507 widget = GET_WIDGET("arithmetic_precedence_menu");
508 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE);
509 } else {
510 widget = GET_WIDGET("ltr_precedence_menu");
511 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE);
516 void
517 ui_set_accuracy(int accuracy)
519 GtkWidget *widget;
520 char text[MAXLINE];
521 char *desc, *current, *tooltip;
523 v->accuracy = accuracy;
525 SNPRINTF(text, MAXLINE, _("Other (%d) ..."), accuracy);
526 widget = gtk_bin_get_child(GTK_BIN(GET_WIDGET("acc_item_other")));
527 gtk_label_set_text(GTK_LABEL(widget), text);
529 desc = g_strdup_printf(ngettext("Set accuracy from 0 to %d numeric places.",
530 "Set accuracy from 0 to %d numeric places.",
531 MAXACC),
532 MAXACC);
534 /* Translator: This refers to the current accuracy setting */
535 current = g_strdup_printf(ngettext("Currently set to %d places.",
536 "Currently set to %d places.",
537 accuracy),
538 accuracy);
539 tooltip = g_strdup_printf ("%s %s [A]", desc, current);
540 gtk_widget_set_tooltip_text (GET_WIDGET("calc_accuracy_button"), tooltip);
541 g_free(desc);
542 g_free(current);
543 g_free(tooltip);
545 if (accuracy >= 0 && accuracy <= 9) {
546 SNPRINTF(text, MAXLINE, "acc_item%d", accuracy);
547 widget = GET_WIDGET(text);
548 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE);
551 gtk_spin_button_set_value(GTK_SPIN_BUTTON(X->precision_spin),
552 (double)accuracy);
554 set_int_resource(R_ACCURACY, accuracy);
556 ui_make_registers();
557 refresh_display();
561 static void
562 ui_update_trig_mode()
564 static char *sine_labels[] = {N_("Sin"), N_("Sinh"),
565 N_("Sin<sup>-1</sup>"),
566 N_("Sinh<sup>-1</sup>")};
567 static int sine_functions[] = {KEY_SIN, KEY_SINH, KEY_ASIN, KEY_ASINH};
568 static char *cosine_labels[] = {N_("Cos"), N_("Cosh"),
569 N_("Cos<sup>-1</sup>"),
570 N_("Cosh<sup>-1</sup>")};
571 static int cosine_functions[] = {KEY_COS, KEY_COSH, KEY_ACOS, KEY_ACOSH};
572 static char *tangent_labels[] = {N_("Tan"), N_("Tanh"),
573 N_("Tan<sup>-1</sup>"),
574 N_("Tanh<sup>-1</sup>")};
575 static int tangent_functions[] = {KEY_TAN, KEY_TANH, KEY_ATAN, KEY_ATANH};
576 int index = 0;
578 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X->hyperbolic_toggle))) {
579 index |= 0x1;
581 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X->inverse_toggle))) {
582 index |= 0x2;
585 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("sine_label")),
586 sine_labels[index]);
587 g_object_set_data(G_OBJECT(GET_WIDGET("calc_sine_button")), "calc_function",
588 GINT_TO_POINTER(sine_functions[index]));
590 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("cosine_label")),
591 cosine_labels[index]);
592 g_object_set_data(G_OBJECT(GET_WIDGET("calc_cosine_button")), "calc_function",
593 GINT_TO_POINTER(cosine_functions[index]));
595 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("tangent_label")),
596 tangent_labels[index]);
597 g_object_set_data(G_OBJECT(GET_WIDGET("calc_tangent_button")), "calc_function",
598 GINT_TO_POINTER(tangent_functions[index]));
602 void
603 ui_set_hyperbolic_state(gboolean state)
605 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->hyperbolic_toggle), state);
606 ui_update_trig_mode();
610 void
611 ui_set_inverse_state(gboolean state)
613 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->inverse_toggle), state);
614 ui_update_trig_mode();
618 void
619 ui_set_trigonometric_mode(enum trig_type mode)
621 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->trig[mode]), 1);
625 void
626 ui_set_numeric_mode(enum base_type mode)
628 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->disp[mode]), 1);
632 void
633 ui_set_show_thousands_seperator(gboolean visible)
635 GtkWidget *menu;
637 v->show_tsep = visible;
638 set_boolean_resource(R_TSEP, v->show_tsep);
640 menu = GET_WIDGET("show_thousands_separator_menu");
641 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), visible);
643 syntaxdep_show_display();
644 ui_make_registers();
648 void
649 ui_set_show_bitcalculating(gboolean visible)
651 GtkWidget *menu;
653 v->bitcalculating_mode = visible;
654 ui_set_mode(v->modetype);
655 set_resource(R_BITCALC, Rcstr[v->bitcalculating_mode]);
657 menu = GET_WIDGET("show_bitcalculating_menu");
658 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), visible);
662 void
663 ui_set_show_trailing_zeroes(gboolean visible)
665 GtkWidget *menu;
667 v->show_zeroes = visible;
668 set_boolean_resource(R_ZEROES, visible);
670 syntaxdep_show_display();
671 ui_make_registers();
673 menu = GET_WIDGET("show_trailing_zeroes_menu");
674 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), visible);
675 menu = GET_WIDGET("acc_trailing_zeroes_item");
676 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), visible);
680 void
681 ui_set_undo_enabled(gboolean undo, gboolean redo)
683 gtk_widget_set_sensitive(GET_WIDGET("undo_menu"), undo);
684 gtk_widget_set_sensitive(GET_WIDGET("redo_menu"), redo);
688 static char *
689 make_hostname()
691 Display *dpy = GDK_DISPLAY();
692 char client_hostname[MAXHOSTNAMELEN + 4];
693 char hostname[MAXHOSTNAMELEN];
694 char *display = DisplayString(dpy);
695 char *scanner = display;
697 GETHOSTNAME(hostname, MAXHOSTNAMELEN);
699 while (*scanner) {
700 scanner++;
703 while (*scanner != ':') {
704 scanner--;
707 *scanner = '\0';
709 if (strcmp(display, hostname) &&
710 strcmp(display, "localhost") &&
711 strcmp(display, "unix") &&
712 strcmp(display, "")) {
713 SPRINTF(client_hostname, " [%s] ", hostname);
714 } else {
715 STRCPY(client_hostname, "");
718 *scanner = ':';
720 if (client_hostname[0] == '\0')
721 return NULL;
722 else
723 return(strdup(client_hostname));
727 void
728 ui_set_mode(enum mode_type mode)
730 GtkRequisition *r;
731 gint w, h;
732 char *hostname, title[MAXLINE];
733 GtkWidget *menu;
735 switch (mode) {
736 case BASIC:
737 gtk_widget_show(X->bas_panel);
738 gtk_widget_hide(X->adv_panel);
739 gtk_widget_hide(X->fin_panel);
740 gtk_widget_hide(X->mode_panel);
741 gtk_widget_hide(X->bit_panel);
742 gtk_widget_hide(X->sci_panel);
743 menu = GET_WIDGET("view_basic_menu");
744 break;
746 case ADVANCED:
747 gtk_widget_hide(X->bas_panel);
748 gtk_widget_show(X->adv_panel);
749 gtk_widget_hide(X->fin_panel);
750 gtk_widget_hide(X->mode_panel);
751 gtk_widget_hide(X->bit_panel);
752 gtk_widget_hide(X->sci_panel);
753 menu = GET_WIDGET("view_advanced_menu");
754 break;
756 case FINANCIAL:
757 gtk_widget_hide(X->bas_panel);
758 gtk_widget_show(X->adv_panel);
759 gtk_widget_show(X->fin_panel);
760 gtk_widget_hide(X->mode_panel);
761 gtk_widget_hide(X->bit_panel);
762 gtk_widget_hide(X->sci_panel);
763 menu = GET_WIDGET("view_financial_menu");
764 break;
766 case SCIENTIFIC:
767 gtk_widget_hide(X->bas_panel);
768 gtk_widget_show(X->adv_panel);
769 gtk_widget_hide(X->fin_panel);
770 gtk_widget_show_all(X->mode_panel);
771 if (v->bitcalculating_mode) {
772 gtk_widget_show_all(X->bit_panel);
773 } else {
774 gtk_widget_hide(X->bit_panel);
776 gtk_widget_show(X->sci_panel);
777 menu = GET_WIDGET("view_scientific_menu");
778 break;
780 default:
781 assert(FALSE);
782 return;
786 r = g_new0(GtkRequisition, 1);
787 gtk_widget_size_request(X->menubar, r);
788 w = r->width;
789 h = r->height;
790 gtk_widget_size_request(X->display_item, r);
791 w = MAX(w, r->width);
792 h += r->height;
794 if (GTK_WIDGET_VISIBLE(X->fin_panel)) {
795 gtk_widget_size_request(X->fin_panel, r);
796 w = MAX(w, r->width);
797 h += r->height;
800 if (GTK_WIDGET_VISIBLE(X->mode_panel)) {
801 gtk_widget_size_request(X->mode_panel, r);
802 w = MAX(w, r->width);
803 h += r->height;
806 if (GTK_WIDGET_VISIBLE(X->sci_panel)) {
807 gtk_widget_size_request(X->sci_panel, r);
808 w = MAX(w, r->width);
809 h += r->height;
812 /* For initial display. */
813 gtk_window_set_default_size(GTK_WINDOW(X->kframe), w, h);
814 gtk_window_resize(GTK_WINDOW(X->kframe), w, h);
816 g_free(r);
818 if((hostname = make_hostname())) {
819 SNPRINTF(title, MAXLINE, hostname_titles[mode], hostname);
820 g_free(hostname);
821 } else {
822 SNPRINTF(title, MAXLINE, titles[mode]);
824 gtk_window_set_title(GTK_WINDOW(X->kframe), title);
826 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
830 void
831 ui_set_statusbar(gchar *text, const gchar *imagename)
833 GtkImage *image = GTK_IMAGE(X->status_image);
835 assert(text);
836 assert(imagename);
837 assert(image);
839 gtk_image_set_from_stock(image, imagename, GTK_ICON_SIZE_BUTTON);
840 gtk_statusbar_pop(GTK_STATUSBAR(X->statusbar), 0);
841 gtk_statusbar_push(GTK_STATUSBAR(X->statusbar), 0, text);
845 static void
846 bin_str(int MP_value[MP_SIZE], char *str, int maxbits)
848 int i, MP0[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MP3[MP_SIZE];
849 int neg = 0;
851 MPstr_to_num("0", DEC, MP0);
852 MPstr_to_num("1", DEC, MP1);
853 MPstr_to_num("2", DEC, MP2);
855 if (mplt(MP_value, MP0)) {
856 mpcmim(MP_value, MP0);
857 mpadd(MP0, MP1, MP0);
858 neg = 1;
859 } else {
860 mpcmim(MP_value, MP0);
863 for (i = 0; i < maxbits; i++) {
864 double lsb; /* Least significant bit. */
865 calc_and(MP3, MP0, MP1);
866 mpcmd(MP3, &lsb);
868 if (lsb == 0) {
869 str[maxbits - i -1] = (neg) ? '1' : '0';
870 } else {
871 str[maxbits - i -1] = (neg) ? '0' : '1';
874 mpdiv(MP0, MP2, MP3);
875 mpcmim(MP3, MP0);
878 return;
882 static void
883 set_bit_panel()
885 int bit_str_len, i, MP1[MP_SIZE], MP2[MP_SIZE];
886 int MP[MP_SIZE];
887 char str[64], label[3];
888 int ret = usable_num(MP);
890 switch (v->syntax) {
891 case NPA:
892 MPstr_to_num(v->display, v->base, MP1);
893 mpcmim(MP1, MP2);
894 if (mpeq(MP1, MP2)) {
895 char *bit_str, label[3], tmp[MAXLINE];
896 int toclear = (v->current == KEY_CLEAR_ENTRY)
897 ? TRUE : FALSE;
899 bit_str = make_fixed(MP1, tmp, BIN, MAXLINE, toclear);
900 bit_str_len = strlen(bit_str);
901 if (bit_str_len <= MAXBITS) {
902 gtk_widget_set_sensitive(X->bit_panel, TRUE);
904 STRCPY(label, " 0");
905 for (i = 0; i < MAXBITS; i++) {
906 label[1] = (i < bit_str_len) ? bit_str[bit_str_len-i-1] : '0';
907 gtk_label_set_text(GTK_LABEL(X->bits[MAXBITS - i - 1]), label);
910 return;
913 gtk_widget_set_sensitive(X->bit_panel, FALSE);
914 break;
916 case EXPRS:
917 if (ret || !is_integer(MP)) {
918 gtk_widget_set_sensitive(X->bit_panel, FALSE);
919 return;
921 bin_str(MP, str, 64);
922 gtk_widget_set_sensitive(X->bit_panel, TRUE);
924 STRCPY(label, " 0");
925 for (i = 0; i < 64; i++) {
926 label[1] = str[64 - i - 1];
927 gtk_label_set_text(GTK_LABEL(X->bits[64 - i - 1]), label);
929 break;
931 default:
932 assert(FALSE);
937 static void
938 scroll_right()
940 if (GTK_WIDGET_VISIBLE(
941 GTK_SCROLLED_WINDOW(X->scrolledwindow)->hscrollbar)) {
942 GtkAdjustment *set;
944 set = gtk_scrolled_window_get_hadjustment(
945 GTK_SCROLLED_WINDOW(X->scrolledwindow));
946 gtk_adjustment_set_value(set, set->upper);
947 gtk_scrolled_window_set_hadjustment(
948 GTK_SCROLLED_WINDOW(X->scrolledwindow), set);
953 void
954 ui_set_display(char *str)
956 char localized[MAX_LOCALIZED];
958 if (str == NULL || str[0] == '\0') {
959 str = " ";
960 } else {
961 if (v->noparens == 0) {
962 localize_number(localized, str);
963 str = localized;
966 gtk_text_buffer_set_text(X->display_buffer, str, -1);
967 scroll_right();
971 /* When an error condition occurs:
973 * - make insensitive all buttons except Clr.
974 * - make all Scientific mode toggles and checkboxes insensitive.
975 * - make all menubar items insensitive except:
976 * Calculator->Quit
977 * Help->Contents
979 * When the error condition is cleared, resensitise everything, setting
980 * the numeric base buttons correctly.
983 void
984 ui_set_error_state(gboolean error)
986 int i;
988 v->error = error;
990 for (i = 0; i < NBUTTONS; i++) {
991 gtk_widget_set_sensitive(X->buttons[i], !v->error);
993 /* Clr button always sensitive. */
994 gtk_widget_set_sensitive(X->clear_buttons[0], TRUE);
995 gtk_widget_set_sensitive(X->clear_buttons[1], TRUE);
997 if (!v->error) {
998 ui_set_base(v->base);
1001 gtk_widget_set_sensitive(X->mode_panel, !v->error);
1003 // FIXME: Isn't this missing a whole lot of widgets?
1004 SET_MENUBAR_ITEM_STATE("copy_menu", !v->error);
1005 SET_MENUBAR_ITEM_STATE("paste_menu", !v->error);
1006 SET_MENUBAR_ITEM_STATE("insert_ascii_menu", !v->error);
1007 SET_MENUBAR_ITEM_STATE("view_basic_menu", !v->error);
1008 SET_MENUBAR_ITEM_STATE("view_advanced_menu", !v->error);
1009 SET_MENUBAR_ITEM_STATE("view_financial_menu", !v->error);
1010 SET_MENUBAR_ITEM_STATE("view_scientific_menu", !v->error);
1011 SET_MENUBAR_ITEM_STATE("show_trailing_zeroes_menu",
1012 !v->error && (v->modetype == SCIENTIFIC));
1013 SET_MENUBAR_ITEM_STATE("show_thousands_separator_menu", !v->error);
1014 SET_MENUBAR_ITEM_STATE("show_registers_menu", !v->error);
1015 SET_MENUBAR_ITEM_STATE("arithmetic_precedence_menu", !v->error);
1016 SET_MENUBAR_ITEM_STATE("about_menu", !v->error);
1020 void
1021 ui_beep()
1023 gdk_beep();
1027 char *
1028 ui_get_localized_numeric_point(void)
1030 const char *decimal_point;
1032 decimal_point = localeconv()->decimal_point;
1034 return(g_locale_to_utf8(decimal_point, -1, NULL, NULL, NULL));
1038 void
1039 ui_set_base(enum base_type base)
1041 int i, baseval = basevals[(int) base];
1043 v->base = base;
1045 for (i = 0; i < 16; i++) {
1046 gtk_widget_set_sensitive(X->digit_buttons[i], i < baseval);
1048 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->base[base]), 1);
1052 void
1053 ui_set_registers_visible(gboolean visible)
1055 GtkWidget *menu;
1056 ui_make_registers();
1058 menu = GET_WIDGET("show_registers_menu");
1059 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), visible);
1061 gtk_widget_realize(X->rframe);
1063 if (visible) {
1064 if (gdk_window_is_visible(X->rframe->window)) {
1065 gdk_window_raise(X->rframe->window);
1066 return;
1068 ds_position_popup(X->kframe, X->rframe, DS_POPUP_ABOVE);
1069 gtk_widget_show(X->rframe);
1070 } else {
1071 gtk_widget_hide(X->rframe);
1074 set_boolean_resource(R_REGS, visible);
1078 gchar *
1079 ui_get_display(void)
1081 GtkTextIter start, end;
1082 gtk_text_buffer_get_bounds(X->display_buffer, &start, &end);
1083 return gtk_text_buffer_get_text(X->display_buffer,
1084 &start,
1085 &end,
1086 FALSE);
1091 ui_get_cursor(void)
1093 gint pos;
1094 g_object_get(G_OBJECT(X->display_buffer), "cursor-position", &pos, NULL);
1095 return pos;
1099 /*ARGSUSED*/
1100 static void
1101 about_cb(GtkWidget *widget)
1103 const gchar *authors[] = {
1104 "Rich Burridge <rich.burridge@sun.com>",
1105 "Sami Pietila <sampie@ariana-dsl.utu.fi>",
1106 "Robert Ancell <robert.ancell@gmail.com>",
1107 NULL
1109 const gchar *documenters[] = {
1110 "Sun Microsystems",
1111 NULL
1113 const gchar *translator_credits = _("translator-credits");
1115 const char *license[] = {
1116 N_("Gcalctool is free software; you can redistribute it and/or modify\n"
1117 "it under the terms of the GNU General Public License as published by\n"
1118 "the Free Software Foundation; either version 2 of the License, or\n"
1119 "(at your option) any later version.\n"),
1120 N_("Gcalctool is distributed in the hope that it will be useful,\n"
1121 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1122 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1123 "GNU General Public License for more details.\n"),
1124 N_("You should have received a copy of the GNU General Public License\n"
1125 "along with Gcalctool; if not, write to the Free Software Foundation, Inc.,\n"
1126 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n")
1129 char *license_trans = g_strconcat(_(license[0]), "\n",
1130 _(license[1]), "\n",
1131 _(license[2]), "\n",
1132 NULL);
1134 gtk_show_about_dialog(GTK_WINDOW(X->kframe),
1135 "name",_("Gcalctool"),
1136 "version", VERSION,
1137 "copyright", _("\xc2\xa9 1986-2007 The Gcalctool authors"),
1138 "license", license_trans,
1139 "comments", _("Calculator with financial and scientific modes."),
1140 "authors", authors,
1141 "documenters", documenters,
1142 "translator_credits", translator_credits,
1143 "logo-icon-name", "gnome-calculator",
1144 NULL);
1148 static void
1149 cell_edited_cb(GtkCellRendererText *cell, const gchar *path_string,
1150 const gchar *new_text, gpointer data)
1152 GtkTreeModel *model = (GtkTreeModel *) data;
1153 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1154 GtkTreeIter iter;
1155 gchar *old_text;
1156 gint *column;
1158 column = g_object_get_data(G_OBJECT(cell), "column");
1160 gtk_tree_model_get_iter(model, &iter, path);
1162 switch (GPOINTER_TO_INT(column)) {
1163 case COLUMN_VALUE:
1164 gtk_tree_model_get(model, &iter, column, &old_text, -1);
1165 g_free(old_text);
1166 gtk_list_store_set(GTK_LIST_STORE(model), &iter, column,
1167 g_strdup(new_text), -1);
1168 break;
1170 case COLUMN_DESCRIPTION:
1171 gtk_tree_model_get(model, &iter, column, &old_text, -1);
1172 g_free(old_text);
1173 gtk_list_store_set(GTK_LIST_STORE(model), &iter, column,
1174 g_strdup(new_text), -1);
1175 break;
1178 gtk_tree_path_free(path);
1182 static void
1183 add_cf_column(GtkTreeView *treeview, gchar *name, gint colno, gboolean editable)
1185 GtkCellRenderer *renderer;
1186 GtkTreeModel *model = gtk_tree_view_get_model(treeview);
1188 renderer = gtk_cell_renderer_text_new();
1189 if (editable) {
1190 g_signal_connect(G_OBJECT(renderer), "edited",
1191 G_CALLBACK(cell_edited_cb), model);
1193 g_object_set_data(G_OBJECT(renderer), "column", GINT_TO_POINTER(colno));
1195 if (editable) {
1196 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
1197 -1, name, renderer,
1198 "text", colno,
1199 "editable", COLUMN_EDITABLE,
1200 NULL);
1201 } else {
1202 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
1203 -1, name, renderer,
1204 "text", colno,
1205 NULL);
1210 /*ARGSUSED*/
1211 static void
1212 aframe_response_cb(GtkWidget *dialog, gint response_id)
1214 char *ch;
1215 int val;
1217 if (response_id == GTK_RESPONSE_OK) {
1218 ch = (char *) gtk_entry_get_text(GTK_ENTRY(X->aframe_ch));
1219 val = ch[0];
1220 mpcim(&val, v->MPdisp_val);
1221 show_display(v->MPdisp_val);
1224 gtk_widget_hide(dialog);
1228 static gboolean
1229 aframe_delete_cb(GtkWidget *dialog)
1231 aframe_response_cb(dialog, GTK_RESPONSE_CANCEL);
1232 return(TRUE);
1236 /*ARGSUSED*/
1237 static void
1238 aframe_activate_cb(GtkWidget *entry)
1240 aframe_response_cb(X->aframe, GTK_RESPONSE_OK);
1244 /*ARGSUSED*/
1245 static void
1246 rframe_response_cb(GtkWidget *dialog, int response_id)
1248 ui_set_registers_visible(FALSE);
1252 static gboolean
1253 rframe_delete_cb(GtkWidget *dialog)
1255 rframe_response_cb(dialog, GTK_RESPONSE_OK);
1256 return(TRUE);
1260 /*ARGSUSED*/
1261 void
1262 disp_cb(GtkWidget *widget)
1264 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1265 do_numtype((enum num_type) g_object_get_data(G_OBJECT(widget), "numeric_mode"));
1269 /*ARGSUSED*/
1270 void
1271 base_cb(GtkWidget *widget)
1273 enum base_type base;
1275 base = (enum base_type) g_object_get_data(G_OBJECT(widget),
1276 "base_mode");
1277 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
1278 do_base(base);
1283 static void do_button(int function, int arg)
1285 struct exprm_state *e;
1287 switch (v->syntax) {
1288 case NPA:
1289 process_item(&buttons[function], arg);
1290 set_bit_panel();
1291 if (v->new_input && v->dtype == FIX) {
1292 STRNCPY(v->fnum, v->display, MAX_DIGITS - 1);
1293 ui_set_display(v->fnum);
1295 break;
1297 case EXPRS:
1298 e = get_state();
1299 e->value = arg;
1300 MEMCPY(&(e->button), &buttons[function], sizeof(struct button));
1301 new_state();
1302 do_expression();
1303 set_bit_panel();
1304 break;
1306 default:
1307 assert(0);
1312 static void
1313 help_display(void)
1315 GError *error = NULL;
1316 char *command;
1317 const char *lang;
1318 char *uri = NULL;
1319 GdkScreen *gscreen;
1321 int i;
1323 const char * const * langs = g_get_language_names ();
1325 for (i = 0; langs[i]; i++) {
1326 lang = langs[i];
1327 if (strchr (lang, '.')) {
1328 continue;
1331 uri = g_build_filename(PACKAGE_DATA_DIR,
1332 "/gnome/help/gcalctool/",
1333 lang,
1334 "/gcalctool.xml",
1335 NULL);
1337 if (g_file_test (uri, G_FILE_TEST_EXISTS)) {
1338 break;
1342 command = g_strconcat ("gnome-open ghelp://", uri, NULL);
1343 gscreen = gdk_screen_get_default();
1344 gdk_spawn_command_line_on_screen (gscreen, command, &error);
1345 if (error) {
1346 GtkWidget *d;
1348 d = gtk_message_dialog_new(NULL,
1349 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1350 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1351 error->message);
1352 gtk_dialog_run(GTK_DIALOG(d));
1353 gtk_widget_destroy(d);
1354 g_error_free(error);
1355 error = NULL;
1358 g_free (command);
1359 g_free (uri);
1363 static void
1364 put_constant(int n, char *con_value, char *con_name)
1366 char key[MAXLINE];
1367 char *cstr = g_strdup(con_value);
1369 /* Constants are written out with no thousands seaparator and with a radix
1370 * character of ".".
1373 SNPRINTF(key, MAXLINE, "constant%1dvalue", n);
1374 set_resource(key, cstr);
1375 g_free(cstr);
1377 SNPRINTF(key, MAXLINE, "constant%1dname", n);
1378 set_resource(key, con_name);
1382 static void
1383 put_function(int n, char *fun_value, char *fun_name)
1385 char key[MAXLINE];
1387 SNPRINTF(key, MAXLINE, "function%1dvalue", n);
1388 set_resource(key, fun_value);
1390 SNPRINTF(key, MAXLINE, "function%1dname", n);
1391 set_resource(key, fun_name);
1395 /*ARGSUSED*/
1396 static void
1397 constant_menu_cb(GtkMenuItem *menu)
1399 int arg = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "constant_id"));
1400 do_button(KEY_CONSTANT, arg);
1404 /*ARGSUSED*/
1405 static void
1406 function_menu_cb(GtkMenuItem *menu)
1408 int arg = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "function_id"));
1409 do_button(KEY_FUNCTION, arg);
1413 /*ARGSUSED*/
1414 static void
1415 store_menu_cb(GtkMenuItem *menu)
1417 int arg = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "register_id"));
1418 do_button(KEY_STORE, arg);
1422 /*ARGSUSED*/
1423 static void
1424 recall_menu_cb(GtkMenuItem *menu)
1426 int arg = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "register_id"));
1427 do_button(KEY_RECALL, arg);
1431 /*ARGSUSED*/
1432 static void
1433 exchange_menu_cb(GtkMenuItem *menu)
1435 int arg = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "register_id"));
1436 do_button(KEY_EXCHANGE, arg);
1440 static void
1441 update_constants_menu(void)
1443 char mline[MAXLINE];
1444 int i;
1446 for (i = 0; i < MAX_CONSTANTS; i++) {
1447 SNPRINTF(mline, MAXLINE,
1448 "<span weight=\"bold\">%s_%1d:</span> %s [%s]", _("C"), i,
1449 make_number(v->MPcon_vals[i], DEC, TRUE),
1450 v->con_names[i]);
1451 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X->constant_menu_labels[i]), mline);
1456 static void
1457 update_functions_menu(void)
1459 char mline[MAXLINE];
1460 int i;
1462 for (i = 0; i < MAX_FUNCTIONS; i++) {
1463 if (strlen(v->fun_vals[i]) != 0) {
1464 SNPRINTF(mline, MAXLINE,
1465 "<span weight=\"bold\">%s_%1d:</span> %s [%s]",
1466 _("F"), i, v->fun_vals[i], v->fun_names[i]);
1467 gtk_widget_show(gtk_widget_get_parent(X->function_menu_labels[i]));
1468 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X->function_menu_labels[i]), mline);
1470 else
1471 gtk_widget_hide(gtk_widget_get_parent(X->function_menu_labels[i]));
1476 static void
1477 edit_constants_response_cb(GtkDialog *dialog, gint id)
1479 GtkTreeIter iter;
1480 gint number;
1481 gchar *value;
1482 gchar *description;
1484 if (id == GTK_RESPONSE_HELP) {
1485 help_display();
1488 if (id == GTK_RESPONSE_ACCEPT) {
1489 if (gtk_tree_model_get_iter_first(X->constants_model, &iter)) {
1490 do {
1491 gtk_tree_model_get(X->constants_model, &iter,
1492 COLUMN_NUMBER, &number,
1493 COLUMN_VALUE, &value,
1494 COLUMN_DESCRIPTION, &description, -1);
1495 MPstr_to_num(value, DEC, v->MPcon_vals[number]);
1496 STRNCPY(v->con_names[number], description, MAXLINE - 1);
1497 put_constant(number, value, description);
1498 } while (gtk_tree_model_iter_next(X->constants_model, &iter));
1502 gtk_widget_hide(GTK_WIDGET(dialog));
1506 static void
1507 edit_functions_response_cb(GtkDialog *dialog, gint id)
1509 GtkTreeIter iter;
1510 gint number;
1511 gchar *value;
1512 gchar *description;
1514 if (id == GTK_RESPONSE_HELP) {
1515 help_display();
1518 if (id == GTK_RESPONSE_ACCEPT) {
1519 if (gtk_tree_model_get_iter_first(X->functions_model, &iter)) {
1520 do {
1521 gtk_tree_model_get(X->functions_model, &iter,
1522 COLUMN_NUMBER, &number,
1523 COLUMN_VALUE, &value,
1524 COLUMN_DESCRIPTION, &description, -1);
1525 STRNCPY(v->fun_vals[number], convert(value), MAXLINE - 1);
1526 STRNCPY(v->fun_names[number], description, MAXLINE - 1);
1527 put_function(number, value, description);
1528 } while (gtk_tree_model_iter_next(X->functions_model, &iter));
1532 gtk_widget_hide(GTK_WIDGET(dialog));
1536 /*ARGSUSED*/
1537 static GtkTreeModel *
1538 create_constants_model()
1540 gint i = 0;
1541 GtkListStore *model;
1542 GtkTreeIter iter;
1544 model = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING,
1545 G_TYPE_STRING, G_TYPE_BOOLEAN);
1546 for (i = 0; i < MAX_CONSTANTS; i++) {
1547 gtk_list_store_append(model, &iter);
1549 gtk_list_store_set(model, &iter,
1550 COLUMN_NUMBER, i,
1551 COLUMN_EDITABLE, TRUE,
1552 -1);
1555 return(GTK_TREE_MODEL(model));
1559 /*ARGSUSED*/
1560 static GtkTreeModel *
1561 create_functions_model()
1563 gint i = 0;
1564 GtkListStore *model;
1565 GtkTreeIter iter;
1567 model = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING,
1568 G_TYPE_STRING, G_TYPE_BOOLEAN);
1569 for (i = 0; i < MAX_FUNCTIONS; i++) {
1570 gtk_list_store_append(model, &iter);
1572 gtk_list_store_set(model, &iter,
1573 COLUMN_NUMBER, i,
1574 COLUMN_EDITABLE, TRUE,
1575 -1);
1578 return(GTK_TREE_MODEL(model));
1582 void
1583 ui_make_registers() /* Calculate memory register frame values. */
1585 char *mval, key[MAXLINE];
1586 int n;
1588 for (n = 0; n < MAX_REGISTERS; n++) {
1589 mval = make_number(v->MPmvals[n], v->base, TRUE);
1590 gtk_entry_set_width_chars(GTK_ENTRY(X->regs[n]), strlen(mval));
1591 gtk_entry_set_text(GTK_ENTRY(X->regs[n]), mval);
1592 SNPRINTF(key, MAXLINE, "register%d", n);
1593 set_resource(key, mval);
1598 static void
1599 reset_mode_display(void)
1601 switch (v->syntax) {
1602 case NPA:
1603 show_display(v->MPdisp_val);
1604 break;
1606 case EXPRS:
1607 refresh_display();
1608 break;
1610 default:
1611 assert(FALSE);
1613 ui_make_registers();
1617 static void
1618 save_win_position()
1620 int x, y;
1622 (void) gdk_window_get_origin(X->kframe->window, &x, &y);
1623 set_int_resource(R_XPOS, x);
1624 set_int_resource(R_YPOS, y);
1628 static void
1629 change_mode(int mode)
1631 v->modetype = mode;
1633 ui_set_base(DEC);
1634 ui_set_numeric_mode(FIX);
1635 ui_set_accuracy(9);
1636 ui_set_show_thousands_seperator(FALSE);
1637 ui_set_show_trailing_zeroes(FALSE);
1639 reset_mode_display();
1640 do_mode(TRUE);
1644 static gboolean
1645 request_change_mode()
1647 GtkWidget *dialog, *request_check, *button;
1648 gint response;
1650 if (!v->warn_change_mode)
1651 return TRUE;
1653 dialog = gtk_message_dialog_new(GTK_WINDOW(X->kframe),
1654 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
1655 GTK_MESSAGE_WARNING,
1656 GTK_BUTTONS_CANCEL,
1657 "%s",
1658 _("Changing Modes Clears Calculation"));
1659 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1660 "%s",
1661 _("When you change modes, the current calculation "
1662 "will be cleared, and the base will be reset to "
1663 "decimal."));
1665 request_check = gtk_check_button_new_with_mnemonic(_("_Do not warn me again"));
1666 gtk_box_pack_end(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1667 request_check, FALSE, FALSE, 0);
1669 button = gtk_dialog_add_button(GTK_DIALOG(dialog),
1670 _("C_hange Mode"), GTK_RESPONSE_ACCEPT);
1671 gtk_button_set_image(GTK_BUTTON(button),
1672 gtk_image_new_from_stock(GTK_STOCK_REFRESH,
1673 GTK_ICON_SIZE_BUTTON));
1674 /* Set default focus on affirmative button */
1675 gtk_widget_grab_focus(button);
1677 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
1678 GTK_RESPONSE_ACCEPT,
1679 GTK_RESPONSE_CANCEL,
1680 -1);
1682 gtk_window_set_position(GTK_WINDOW(dialog),
1683 GTK_WIN_POS_CENTER_ON_PARENT);
1685 gtk_widget_show_all(dialog);
1686 response = gtk_dialog_run(GTK_DIALOG(dialog));
1688 // FIXME: Save this in GConf
1689 v->warn_change_mode = !gtk_toggle_button_get_active(
1690 GTK_TOGGLE_BUTTON(request_check));
1692 gtk_widget_destroy(dialog);
1694 return response == GTK_RESPONSE_ACCEPT;
1698 /*ARGSUSED*/
1699 static gboolean
1700 bit_toggle_cb(GtkWidget *event_box, GdkEventButton *event)
1702 double number;
1703 unsigned long long lval;
1704 int n, MP1[MP_SIZE], index;
1706 index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box),
1707 "bit_index"));
1708 n = MAXBITS - index - 1;
1709 MPstr_to_num(v->display, v->base, MP1);
1710 mpcmd(MP1, &number);
1711 lval = (long long) number;
1713 if (lval & (1LL << n)) {
1714 lval &= ~(1LL << n);
1715 gtk_label_set_text(GTK_LABEL(X->bits[index]), " 0");
1716 } else {
1717 lval |= (1LL << n);
1718 gtk_label_set_text(GTK_LABEL(X->bits[index]), " 1");
1721 number = (double) lval;
1722 mpcdm(&number, v->MPdisp_val);
1723 show_display(v->MPdisp_val);
1724 v->toclear = 0;
1726 return(TRUE);
1730 static void
1731 menu_item_select_cb(GtkWidget *widget)
1733 GtkStatusbar *statusbar = GTK_STATUSBAR(X->statusbar);
1734 gchar *tooltip;
1735 guint context_id;
1737 context_id = gtk_statusbar_get_context_id(statusbar, "menuhelp");
1739 tooltip = (gchar *)g_object_get_data(G_OBJECT(widget), "tooltip");
1740 if (tooltip) {
1741 gtk_statusbar_push(statusbar, context_id, tooltip);
1746 /*ARGSUSED*/
1747 static void
1748 menu_item_deselect_cb(GtkWidget *widget)
1750 GtkStatusbar *statusbar = GTK_STATUSBAR(X->statusbar);
1751 guint context_id;
1753 context_id = gtk_statusbar_get_context_id(statusbar, "menuhelp");
1754 gtk_statusbar_pop(statusbar, context_id);
1758 static void
1759 set_menubar_tooltip(gchar *menu_name)
1761 GtkWidget *menu;
1762 gchar *tooltip;
1764 menu = GET_WIDGET(menu_name);
1765 tooltip = gtk_widget_get_tooltip_text(menu);
1766 g_object_set_data(G_OBJECT(menu), "tooltip", tooltip);
1767 gtk_widget_set_tooltip_text(menu, NULL);
1771 static void
1772 update_memory_menus()
1774 char mstr[MAXLINE];
1775 int i;
1777 for (i = 0; i < MAX_REGISTERS; i++) {
1778 SNPRINTF(mstr, MAXLINE, "<span weight=\"bold\">%s_%d:</span> %s",
1779 /* translators: R is the short form of register used inter alia
1780 in popup menus */
1781 _("R"), i, make_number(v->MPmvals[i], v->base, TRUE));
1782 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X->memory_store_labels[i]), mstr);
1783 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X->memory_recall_labels[i]), mstr);
1784 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X->memory_exchange_labels[i]), mstr);
1789 static void
1790 get_constant(int n)
1792 char nkey[MAXLINE], *nline;
1793 char vkey[MAXLINE], *vline;
1795 SNPRINTF(nkey, MAXLINE, "constant%1dname", n);
1796 if ((nline = get_resource(nkey)) == NULL) {
1797 return;
1800 SNPRINTF(vkey, MAXLINE, "constant%1dvalue", n);
1801 if ((vline = get_resource(vkey)) == NULL) {
1802 return;
1805 MPstr_to_num(vline, DEC, v->MPcon_vals[n]);
1806 STRNCPY(v->con_names[n], nline, MAXLINE - 1);
1810 static void
1811 get_display() /* The Copy function key has been pressed. */
1813 gchar *string = NULL;
1814 GtkTextIter start, end;
1816 if (gtk_text_buffer_get_selection_bounds(X->display_buffer, &start, &end) == TRUE) {
1817 string = gtk_text_buffer_get_text(X->display_buffer, &start, &end, FALSE);
1818 } else {
1819 string = ui_get_display();
1822 if (v->shelf != NULL) {
1823 free(v->shelf);
1825 v->shelf = g_locale_from_utf8(string, strlen(string), NULL, NULL, NULL);
1826 g_free(string);
1828 gtk_clipboard_set_text(gtk_clipboard_get(X->clipboard_atom), v->shelf, -1);
1832 static void
1833 get_function(int n)
1835 char nkey[MAXLINE], *nline;
1836 char vkey[MAXLINE], *vline;
1838 SNPRINTF(nkey, MAXLINE, "function%1dname", n);
1839 if ((nline = get_resource(nkey)) == NULL) {
1840 return;
1843 SNPRINTF(vkey, MAXLINE, "function%1dvalue", n);
1844 if ((vline = get_resource(vkey)) == NULL) {
1845 return;
1848 STRNCPY(v->fun_vals[n], convert(vline), MAXLINE - 1);
1849 STRNCPY(v->fun_names[n], nline, MAXLINE - 1);
1853 static gboolean
1854 check_for_localized_numeric_point(int keyval)
1856 gchar outbuf[10]; /* Minumum size 6. */
1857 gunichar ch;
1859 ch = gdk_keyval_to_unicode(keyval);
1860 g_return_val_if_fail(g_unichar_validate(ch), FALSE);
1862 outbuf[g_unichar_to_utf8(ch, outbuf)] = '\0';
1864 return(strcmp(outbuf, X->lnp) == 0);
1868 /*ARGSUSED*/
1869 static void
1870 help_cb(GtkWidget *widget)
1872 help_display();
1876 /*ARGSUSED*/
1877 void
1878 hyp_cb(GtkWidget *widget)
1880 ui_update_trig_mode();
1884 /*ARGSUSED*/
1885 void
1886 inv_cb(GtkWidget *widget)
1888 ui_update_trig_mode();
1892 /*ARGSUSED*/
1893 static gboolean
1894 display_focus_out_cb(GtkWidget *widget, GdkEventKey *event)
1896 if (v->syntax == EXPRS) {
1897 exp_replace(ui_get_display());
1899 return(FALSE);
1903 /*ARGSUSED*/
1904 static gboolean
1905 display_focus_in_cb(GtkWidget *widget, GdkEventKey *event)
1907 v->ghost_zero = 0;
1908 return(FALSE);
1912 /*ARGSUSED*/
1913 static void
1914 menu_pos_func(GtkMenu *menu, gint *x, gint *y,
1915 gboolean *push_in, gpointer user_data)
1917 GdkPoint *loc = (GdkPoint *) user_data;
1919 *x = loc->x;
1920 *y = loc->y;
1924 /*ARGSUSED*/
1925 static void
1926 button_cb(GtkWidget *widget, GdkEventButton *event)
1928 int function;
1929 GtkWidget *menu;
1930 GdkPoint loc;
1932 function = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
1933 "calc_function"));
1934 menu = (GtkWidget *)g_object_get_data(G_OBJECT(widget), "calc_menu");
1936 if (menu == NULL) {
1937 do_button(function, 0);
1938 } else {
1939 /* If gcalctool is being driven by gok, the on-screen keyboard
1940 * assistive technology, it's possible that the event returned by
1941 * gtk_get_current_event() is NULL. If this is the case, we need
1942 * to fudge the popping up on the menu associated with this menu
1943 * button.
1946 update_constants_menu();
1947 update_functions_menu();
1948 update_memory_menus();
1950 if (event == NULL) {
1951 gdk_window_get_origin(widget->window, &loc.x, &loc.y);
1952 loc.x += widget->allocation.x;
1953 loc.y += widget->allocation.y;
1954 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, menu_pos_func,
1955 (gpointer) &loc, 0, gtk_get_current_event_time());
1956 } else if (event->button == 1) {
1957 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1958 event->button, event->time);
1964 /*ARGSUSED*/
1965 static void
1966 select_display_entry(int offset)
1968 GtkTextIter iter;
1970 gtk_text_buffer_get_iter_at_offset(X->display_buffer, &iter, offset);
1971 gtk_text_buffer_place_cursor(X->display_buffer, &iter);
1972 gtk_widget_grab_focus(X->display_item);
1976 /*ARGSUSED*/
1977 static gboolean
1978 kframe_key_press_cb(GtkWidget *widget, GdkEventKey *event)
1980 int i, j, state;
1981 GtkWidget *button;
1983 if (check_for_localized_numeric_point(event->keyval) == TRUE) {
1984 event->state = 0;
1985 event->keyval = GDK_KP_Decimal;
1988 state = event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK);
1990 /* Accuracy shortcuts */
1991 if (state == GDK_CONTROL_MASK && v->modetype == SCIENTIFIC) {
1992 switch (event->keyval) {
1993 case GDK_0:
1994 do_accuracy(0);
1995 return (TRUE);
1996 case GDK_1:
1997 do_accuracy(1);
1998 return (TRUE);
1999 case GDK_2:
2000 do_accuracy(2);
2001 return (TRUE);
2002 case GDK_3:
2003 do_accuracy(3);
2004 return (TRUE);
2005 case GDK_4:
2006 do_accuracy(4);
2007 return (TRUE);
2008 case GDK_5:
2009 do_accuracy(5);
2010 return (TRUE);
2011 case GDK_6:
2012 do_accuracy(6);
2013 return (TRUE);
2014 case GDK_7:
2015 do_accuracy(7);
2016 return (TRUE);
2017 case GDK_8:
2018 do_accuracy(8);
2019 return (TRUE);
2020 case GDK_9:
2021 do_accuracy(9);
2022 return (TRUE);
2026 /* Connect home and end keys to move into the display entry */
2027 if (event->keyval == GDK_Home) {
2028 select_display_entry(0);
2029 return (TRUE);
2030 } else if (event->keyval == GDK_End) {
2031 select_display_entry(-1);
2032 return (TRUE);
2035 for (i = 0; i < NBUTTONS; i++) {
2036 button = X->buttons[i];
2038 /* Check any parent widgets are visible */
2039 if (!GTK_WIDGET_VISIBLE(gtk_widget_get_parent(button)) ||
2040 !GTK_WIDGET_VISIBLE(button) || !GTK_WIDGET_IS_SENSITIVE(button)) {
2041 continue;
2044 j = 0;
2045 while (button_widgets[i].accelerator_keys[j] != 0) {
2046 if (button_widgets[i].accelerator_keys[j] == event->keyval &&
2047 (button_widgets[i].accelerator_mods[j] & ~GDK_SHIFT_MASK) == state) {
2048 button_cb(button, NULL);
2049 return(TRUE);
2051 j++;
2055 return(FALSE);
2059 /*ARGSUSED*/
2060 static void
2061 edit_cb(GtkWidget *widget)
2063 gboolean can_paste, can_copy;
2065 can_copy = gtk_text_buffer_get_has_selection(X->display_buffer);
2066 can_paste = gtk_clipboard_wait_is_text_available(
2067 gtk_clipboard_get(X->clipboard_atom));
2069 gtk_widget_set_sensitive(GET_WIDGET("copy_menu"), can_copy);
2070 gtk_widget_set_sensitive(GET_WIDGET("paste_menu"), can_paste);
2074 /*ARGSUSED*/
2075 static void
2076 copy_cb(GtkWidget *widget)
2078 get_display();
2082 /*ARGSUSED*/
2083 static void
2084 get_proc(GtkClipboard *clipboard, const gchar *buffer, gpointer data)
2086 int ret;
2087 gchar *dstp, *end_buffer, *srcp, *text;
2089 if (buffer == NULL) {
2090 return;
2093 end_buffer = (gchar *) (buffer + strlen(buffer));
2094 text = malloc(strlen(buffer)+1);
2096 srcp = (gchar *) buffer;
2097 dstp = text;
2098 while (srcp < end_buffer) {
2100 /* If the clipboard buffer contains any occurances of the "thousands
2101 * separator", remove them.
2103 if (*srcp == v->tsep[0]) {
2104 if (strstr(srcp, v->tsep) == srcp) {
2105 srcp += strlen(v->tsep);
2106 } else {
2107 *dstp++ = *srcp++;
2109 } else {
2111 /* If an "A", "B", "C", "D" or "F" character is encountered, it
2112 * will be converted to its lowercase equivalent. If an "E" is
2113 * found, and the next character is a "-" or a "+", then it
2114 * remains as an upper case "E" (it's assumed to be a possible
2115 * exponential number), otherwise its converted to a lower case
2116 * "e". See bugs #455889 and #469245 for more details.
2118 switch (*srcp) {
2119 case 'A':
2120 case 'B':
2121 case 'C':
2122 case 'D':
2123 case 'F': *dstp++ = tolower(*srcp);
2124 srcp++;
2125 break;
2127 case 'E': if (srcp < (end_buffer-1)) {
2128 if (*(srcp+1) != '-' &&
2129 *(srcp+1) != '+') {
2130 *dstp++ = tolower(*srcp);
2131 srcp++;
2132 break;
2135 /*FALLTHROUGH*/
2137 default: *dstp++ = *srcp++;
2141 *dstp++ = '\0';
2143 switch (v->syntax) {
2144 case NPA:
2145 ret = lr_parse((char *) text, v->MPdisp_val);
2146 if (!ret) {
2147 show_display(v->MPdisp_val);
2148 } else {
2149 ui_set_statusbar(_("Clipboard contained malformed calculation"),
2150 "gtk-dialog-error");
2152 break;
2154 case EXPRS:
2155 exp_append((char *) text);
2156 refresh_display();
2157 break;
2159 default:
2160 assert(0);
2162 free(text);
2166 /*ARGSUSED*/
2167 static gboolean
2168 mouse_button_cb(GtkWidget *widget, GdkEventButton *event)
2170 if (event->button == 2) {
2171 gtk_clipboard_request_text(gtk_clipboard_get(X->primary_atom),
2172 get_proc, NULL);
2175 return(FALSE);
2179 /*ARGSUSED*/
2180 static void
2181 paste_cb(GtkWidget *widget)
2183 gtk_clipboard_request_text(gtk_clipboard_get(X->clipboard_atom),
2184 get_proc, NULL);
2188 /*ARGSUSED*/
2189 static void
2190 popup_paste_cb(GtkWidget *menu)
2192 paste_cb(menu);
2196 /*ARGSUSED*/
2197 static void
2198 undo_cb(GtkWidget *widget)
2200 perform_undo();
2201 refresh_display();
2205 /*ARGSUSED*/
2206 static void
2207 redo_cb(GtkWidget *widget)
2209 perform_redo();
2210 refresh_display();
2214 //FIXME
2215 /*ARGSUSED*/
2216 static void
2217 for_each_menu(GtkWidget *widget, gpointer data)
2219 /* Find the "Paste" entry and activate it (see bug #317786). */
2220 if (strcmp(G_OBJECT_TYPE_NAME(widget), "GtkImageMenuItem") == 0) {
2221 GtkWidget *label = gtk_bin_get_child(GTK_BIN(widget));
2223 if (strcmp(gtk_label_get_text(GTK_LABEL(label)), _("Paste")) == 0) {
2224 if (gtk_clipboard_wait_is_text_available(
2225 gtk_clipboard_get(X->clipboard_atom))) {
2226 gtk_widget_set_sensitive(GTK_WIDGET(widget), TRUE);
2227 g_signal_connect(GTK_OBJECT(widget), "activate",
2228 G_CALLBACK(popup_paste_cb), NULL);
2235 /*ARGSUSED*/
2236 static void
2237 buffer_populate_popup_cb(GtkTextView *textview, GtkMenu *menu)
2239 gtk_container_foreach(GTK_CONTAINER(menu), for_each_menu, NULL);
2243 /*ARGSUSED*/
2244 static void
2245 insert_ascii_cb(GtkWidget *widget)
2247 if (!GTK_WIDGET_VISIBLE(X->aframe)) {
2248 ds_position_popup(X->kframe, X->aframe, DS_POPUP_LEFT);
2250 gtk_window_set_focus(GTK_WINDOW(X->kframe), GTK_WIDGET(X->aframe_ch));
2251 gtk_widget_show(X->aframe);
2255 static void
2256 shift_cb(GtkWidget *widget)
2258 int count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
2259 "shiftcount"));
2260 do_button(KEY_SHIFT, count);
2264 /*ARGSUSED*/
2265 static void
2266 show_bitcalculating_cb(GtkWidget *widget)
2268 gboolean visible;
2269 visible = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
2270 ui_set_show_bitcalculating(visible);
2274 /*ARGSUSED*/
2275 static void
2276 show_registers_cb(GtkWidget *widget)
2278 gboolean visible;
2279 visible = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
2280 ui_set_registers_visible(visible);
2284 static void
2285 arithmetic_mode_cb(GtkWidget *widget)
2287 enum syntax mode;
2288 mode = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)) ? EXPRS : NPA;
2289 ui_set_syntax_mode(mode);
2293 /*ARGSUSED*/
2294 static void
2295 mode_radio_cb(GtkWidget *menu)
2297 struct exprm_state *e;
2298 int mode; /* The new mode. */
2299 int immediate = 0; /* Set if we can change mode without warning user. */
2300 int complete = 0; /* Set if the user has completed a calculation. */
2302 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu))) {
2303 return;
2306 mode = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "calcmode"));
2308 /* If the user has completed a calculation and we are going to a
2309 * new mode that is "compatible" with this one, then just change
2310 * modes. Otherwise display a dialog warning the user that the
2311 * current calculation will be cleared.
2313 * Incompatible modes are:
2315 * Scientific -> Basic
2316 * Scientific -> Advanced
2317 * Scientific -> Financial
2319 * (unless we are in Scientific mode with Decimal numeric base and Fixed).
2322 switch (v->syntax) {
2323 case NPA:
2324 if (v->old_cal_value < 0 ||
2325 v->old_cal_value == KEY_CALCULATE) {
2326 complete = 1; /* Calculation is complete. */
2328 break;
2330 case EXPRS:
2331 e = get_state();
2332 if (!e->expression || !strcmp(e->expression, "Ans")) {
2333 complete = 1; /* Calculation is complete. */
2335 break;
2337 default:
2338 assert(FALSE);
2341 if (complete) {
2342 if ((v->modetype != SCIENTIFIC) ||
2343 (v->dtype == FIX && v->base == DEC)) {
2344 immediate = 1;
2348 if (immediate) {
2349 v->modetype = mode;
2350 reset_mode_display();
2351 do_mode(FALSE);
2352 } else if (request_change_mode()) {
2353 change_mode(mode);
2358 /*ARGSUSED*/
2359 static void
2360 accuracy_radio_cb(GtkWidget *widget)
2362 int count;
2363 count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "accuracy"));
2364 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
2365 do_accuracy(count);
2370 /*ARGSUSED*/
2371 static void
2372 accuracy_other_cb(GtkWidget *widget)
2374 if (!GTK_WIDGET_VISIBLE(X->spframe)) {
2375 ds_position_popup(X->kframe, X->spframe, DS_POPUP_LEFT);
2377 gtk_window_set_focus(GTK_WINDOW(X->spframe), GTK_WIDGET(X->precision_spin));
2378 gtk_widget_show(X->spframe);
2382 /*ARGSUSED*/
2383 static void
2384 show_trailing_zeroes_cb(GtkWidget *widget)
2386 gboolean visible;
2387 visible = gtk_check_menu_item_get_active(
2388 GTK_CHECK_MENU_ITEM(widget));
2389 ui_set_show_trailing_zeroes(visible);
2393 /*ARGSUSED*/
2394 static void
2395 quit_cb(GtkWidget *widget)
2397 save_win_position();
2398 gtk_main_quit();
2402 static void
2403 spframe_response_cb(GtkWidget *dialog, gint response_id)
2405 int val;
2406 if (response_id == GTK_RESPONSE_OK) {
2407 val = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(X->precision_spin));
2408 ui_set_accuracy(val);
2411 gtk_widget_hide(dialog);
2415 static gboolean
2416 spframe_delete_cb(GtkWidget *dialog)
2418 spframe_response_cb(dialog, GTK_RESPONSE_CANCEL);
2419 return(TRUE);
2423 /*ARGSUSED*/
2424 static void
2425 spframe_activate_cb(GtkWidget *spin)
2427 spframe_response_cb(X->spframe, GTK_RESPONSE_OK);
2431 /*ARGSUSED*/
2432 void
2433 trig_cb(GtkWidget *widget)
2435 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2436 do_trigtype((enum trig_type) g_object_get_data(G_OBJECT(widget),
2437 "trig_mode"));
2441 /*ARGSUSED*/
2442 static void
2443 show_thousands_separator_cb(GtkWidget *widget)
2445 gboolean visible;
2447 visible = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
2448 ui_set_show_thousands_seperator(visible);
2452 /*ARGSUSED*/
2453 static void
2454 edit_constants_cb(GtkMenuItem *item)
2456 gtk_widget_show(X->con_dialog);
2460 /*ARGSUSED*/
2461 static void
2462 edit_functions_cb(GtkMenuItem *item)
2464 gtk_widget_show(X->fun_dialog);
2468 static void
2469 set_win_position()
2471 int intval, screen_height, screen_width;
2472 int x = 0, y = 0;
2474 screen_width = gdk_screen_get_width(gdk_screen_get_default());
2475 screen_height = gdk_screen_get_height(gdk_screen_get_default());
2477 if (get_int_resource(R_XPOS, &intval)) {
2478 x = intval;
2479 if (x < 0 || x > screen_width) {
2480 x = 0;
2484 if (get_int_resource(R_YPOS, &intval)) {
2485 y = intval;
2486 if (y < 0 || y > screen_height) {
2487 y = 0;
2491 gtk_window_move(GTK_WINDOW(X->kframe), x, y);
2495 static void
2496 create_kframe()
2498 int i;
2499 char name[MAXLINE];
2500 GtkWidget *widget;
2501 PangoFontDescription *font_desc;
2502 GtkSizeGroup *size_group;
2503 GtkAccelGroup *accel_group;
2504 GtkWidget *treeview;
2506 X->ui = glade_xml_new(UI_FILE, NULL, NULL);
2507 if (X->ui == NULL) {
2508 GtkWidget *dialog;
2510 dialog = gtk_message_dialog_new(NULL, 0,
2511 GTK_MESSAGE_ERROR,
2512 GTK_BUTTONS_NONE,
2513 N_("Error loading user interface"));
2514 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
2515 N_("The user interace file %s is missing or unable to be loaded. Please check your installation."), UI_FILE);
2516 gtk_dialog_add_buttons(GTK_DIALOG(dialog), GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT, NULL);
2518 gtk_dialog_run(GTK_DIALOG(dialog));
2519 exit(0);
2522 /* When connecting up signals, would ideally use autoconnect but not
2523 * sure how to get the build process working.
2524 * See http://library.gnome.org/devel/libglade/unstable and
2525 * http://www.jamesh.id.au/software/libglade/
2526 * for some information on how to get this to work
2527 * glade_xml_signal_autoconnect(X->ui);
2529 CONNECT_SIGNAL(kframe_key_press_cb);
2530 CONNECT_SIGNAL(button_cb);
2531 CONNECT_SIGNAL(menu_item_select_cb);
2532 CONNECT_SIGNAL(menu_item_deselect_cb);
2533 CONNECT_SIGNAL(mode_radio_cb);
2534 CONNECT_SIGNAL(inv_cb);
2535 CONNECT_SIGNAL(hyp_cb);
2536 CONNECT_SIGNAL(trig_cb);
2537 CONNECT_SIGNAL(base_cb);
2538 CONNECT_SIGNAL(disp_cb);
2539 CONNECT_SIGNAL(quit_cb);
2540 CONNECT_SIGNAL(edit_cb);
2541 CONNECT_SIGNAL(copy_cb);
2542 CONNECT_SIGNAL(paste_cb);
2543 CONNECT_SIGNAL(insert_ascii_cb);
2544 CONNECT_SIGNAL(undo_cb);
2545 CONNECT_SIGNAL(redo_cb);
2546 CONNECT_SIGNAL(help_cb);
2547 CONNECT_SIGNAL(about_cb);
2548 CONNECT_SIGNAL(show_trailing_zeroes_cb);
2549 CONNECT_SIGNAL(show_thousands_separator_cb);
2550 CONNECT_SIGNAL(show_bitcalculating_cb);
2551 CONNECT_SIGNAL(show_registers_cb);
2552 CONNECT_SIGNAL(accuracy_radio_cb);
2553 CONNECT_SIGNAL(accuracy_other_cb);
2554 CONNECT_SIGNAL(constant_menu_cb);
2555 CONNECT_SIGNAL(function_menu_cb);
2556 CONNECT_SIGNAL(store_menu_cb);
2557 CONNECT_SIGNAL(recall_menu_cb);
2558 CONNECT_SIGNAL(exchange_menu_cb);
2559 CONNECT_SIGNAL(arithmetic_mode_cb);
2560 CONNECT_SIGNAL(mouse_button_cb);
2561 CONNECT_SIGNAL(display_focus_in_cb);
2562 CONNECT_SIGNAL(display_focus_out_cb);
2563 /* Detect when populating the right-click menu to enable pasting */
2564 CONNECT_SIGNAL(buffer_populate_popup_cb);
2565 CONNECT_SIGNAL(shift_cb);
2566 CONNECT_SIGNAL(bit_toggle_cb);
2567 CONNECT_SIGNAL(aframe_delete_cb);
2568 CONNECT_SIGNAL(aframe_activate_cb);
2569 CONNECT_SIGNAL(aframe_response_cb);
2570 CONNECT_SIGNAL(spframe_delete_cb);
2571 CONNECT_SIGNAL(spframe_activate_cb);
2572 CONNECT_SIGNAL(spframe_response_cb);
2573 CONNECT_SIGNAL(rframe_delete_cb);
2574 CONNECT_SIGNAL(rframe_response_cb);
2575 CONNECT_SIGNAL(edit_constants_cb);
2576 CONNECT_SIGNAL(edit_functions_cb);
2577 CONNECT_SIGNAL(edit_constants_response_cb);
2578 CONNECT_SIGNAL(edit_functions_response_cb);
2580 X->clipboard_atom = gdk_atom_intern("CLIPBOARD", FALSE);
2581 X->primary_atom = gdk_atom_intern("PRIMARY", FALSE);
2582 X->kframe = GET_WIDGET("calc_window");
2583 X->aframe = GET_WIDGET("ascii_dialog");
2584 X->aframe_ch = GET_WIDGET("ascii_entry");
2585 X->spframe = GET_WIDGET("precision_dialog");
2586 X->precision_spin = GET_WIDGET("spframe_spin");
2587 X->rframe = GET_WIDGET("register_dialog");
2588 X->con_dialog = GET_WIDGET("edit_constants_dialog");
2589 X->fun_dialog = GET_WIDGET("edit_functions_dialog");
2590 X->menubar = GET_WIDGET("menubar");
2591 X->scrolledwindow = GET_WIDGET("display_scroll"),
2592 X->display_item = GET_WIDGET("displayitem"),
2593 X->bas_panel = GET_WIDGET("basic_panel");
2594 X->sci_panel = GET_WIDGET("scientific_panel");
2595 X->adv_panel = GET_WIDGET("advanced_panel");
2596 X->fin_panel = GET_WIDGET("financial_panel");
2597 X->bit_panel = GET_WIDGET("bit_panel");
2598 X->clear_buttons[0] = GET_WIDGET("calc_clear_simple_button");
2599 X->clear_buttons[1] = GET_WIDGET("calc_clear_advanced_button");
2600 X->mode_panel = GET_WIDGET("mode_panel");
2601 X->trig[0] = GET_WIDGET("degrees_radio");
2602 X->trig[1] = GET_WIDGET("gradians_radio");
2603 X->trig[2] = GET_WIDGET("radians_radio");
2604 X->base[0] = GET_WIDGET("binary_radio");
2605 X->base[1] = GET_WIDGET("octal_radio");
2606 X->base[2] = GET_WIDGET("decimal_radio");
2607 X->base[3] = GET_WIDGET("hexadecimal_radio");
2608 X->disp[0] = GET_WIDGET("engineering_radio");
2609 X->disp[1] = GET_WIDGET("fixed_point_radio");
2610 X->disp[2] = GET_WIDGET("scientific_radio");
2611 X->inverse_toggle = GET_WIDGET("inverse_check");
2612 X->hyperbolic_toggle = GET_WIDGET("hyperbolic_check");
2613 X->statusbar = GET_WIDGET("statusbar");
2614 for (i = 0; i < 16; i++) {
2615 SNPRINTF(name, MAXLINE, "calc_%x_button", i);
2616 X->digit_buttons[i] = GET_WIDGET(name);
2618 for (i = 0; i < MAX_REGISTERS; i++) {
2619 SNPRINTF(name, MAXLINE, "register_entry_%d", i);
2620 X->regs[i] = GET_WIDGET(name);
2623 /* Load buttons and set them all to be the same size */
2624 size_group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
2625 for (i = 0; i < NBUTTONS; i++) {
2626 SNPRINTF(name, MAXLINE, "calc_%s_button",
2627 button_widgets[i].widget_name);
2628 X->buttons[i] = GET_WIDGET(name);
2629 assert(X->buttons[i] != NULL);
2631 gtk_size_group_add_widget(size_group, X->buttons[i]);
2633 g_object_set_data(G_OBJECT(X->buttons[i]), "calc_function",
2634 GINT_TO_POINTER(button_widgets[i].key));
2637 /* Make popup buttons */
2638 g_object_set_data(G_OBJECT(GET_WIDGET("calc_accuracy_button")),
2639 "calc_menu", GET_WIDGET("accuracy_popup"));
2640 g_object_set_data(G_OBJECT(GET_WIDGET("calc_shift_left_button")),
2641 "calc_menu", GET_WIDGET("left_shift_popup"));
2642 g_object_set_data(G_OBJECT(GET_WIDGET("calc_shift_right_button")),
2643 "calc_menu", GET_WIDGET("right_shift_popup"));
2645 g_object_set_data(G_OBJECT(GET_WIDGET("calc_constants_button")),
2646 "calc_menu", GET_WIDGET("constants_popup"));
2647 for (i = 0; i < MAX_CONSTANTS; i++) {
2648 SNPRINTF(name, MAXLINE, "constant_menu_item%d", i);
2649 widget = GET_WIDGET(name);
2650 g_object_set_data(G_OBJECT(widget), "constant_id", GINT_TO_POINTER(i));
2651 X->constant_menu_labels[i] = gtk_bin_get_child(GTK_BIN(widget));
2654 g_object_set_data(G_OBJECT(GET_WIDGET("calc_functions_button")),
2655 "calc_menu", GET_WIDGET("functions_popup"));
2656 for (i = 0; i < MAX_FUNCTIONS; i++) {
2657 SNPRINTF(name, MAXLINE, "function_menu_item%d", i);
2658 widget = GET_WIDGET(name);
2659 g_object_set_data(G_OBJECT(widget), "function_id", GINT_TO_POINTER(i));
2660 X->function_menu_labels[i] = gtk_bin_get_child(GTK_BIN(widget));
2663 g_object_set_data(G_OBJECT(GET_WIDGET("calc_store_button")),
2664 "calc_menu", GET_WIDGET("memory_store_popup"));
2665 g_object_set_data(G_OBJECT(GET_WIDGET("calc_recall_button")),
2666 "calc_menu", GET_WIDGET("memory_recall_popup"));
2667 g_object_set_data(G_OBJECT(GET_WIDGET("calc_exchange_button")),
2668 "calc_menu", GET_WIDGET("memory_exchange_popup"));
2669 for (i = 0; i < MAX_REGISTERS; i++) {
2670 SNPRINTF(name, MAXLINE, "store_menu_item%d", i);
2671 widget = GET_WIDGET(name);
2672 g_object_set_data(G_OBJECT(widget), "register_id", GINT_TO_POINTER(i));
2673 X->memory_store_labels[i] = gtk_bin_get_child(GTK_BIN(widget));
2675 SNPRINTF(name, MAXLINE, "recall_menu_item%d", i);
2676 widget = GET_WIDGET(name);
2677 g_object_set_data(G_OBJECT(widget), "register_id", GINT_TO_POINTER(i));
2678 X->memory_recall_labels[i] = gtk_bin_get_child(GTK_BIN(widget));
2680 SNPRINTF(name, MAXLINE, "exchange_menu_item%d", i);
2681 widget = GET_WIDGET(name);
2682 g_object_set_data(G_OBJECT(widget), "register_id", GINT_TO_POINTER(i));
2683 X->memory_exchange_labels[i] = gtk_bin_get_child(GTK_BIN(widget));
2686 /* Load bit panel */
2687 for (i = 0; i < MAXBITS; i++)
2689 SNPRINTF(name, MAXLINE, "bit_label_%d", i);
2690 X->bits[i] = GET_WIDGET(name);
2691 SNPRINTF(name, MAXLINE, "bit_eventbox_%d", i);
2692 g_object_set_data(G_OBJECT(GET_WIDGET(name)),
2693 "bit_index", GINT_TO_POINTER(i));
2696 /* Make menu tooltips displayed in the status bar */
2697 set_menubar_tooltip("quit_menu");
2698 set_menubar_tooltip("copy_menu");
2699 set_menubar_tooltip("paste_menu");
2700 set_menubar_tooltip("insert_ascii_menu");
2701 set_menubar_tooltip("undo_menu");
2702 set_menubar_tooltip("redo_menu");
2703 set_menubar_tooltip("view_basic_menu");
2704 set_menubar_tooltip("view_advanced_menu");
2705 set_menubar_tooltip("view_financial_menu");
2706 set_menubar_tooltip("view_scientific_menu");
2707 set_menubar_tooltip("show_trailing_zeroes_menu");
2708 set_menubar_tooltip("show_thousands_separator_menu");
2709 set_menubar_tooltip("show_bitcalculating_menu");
2710 set_menubar_tooltip("show_registers_menu");
2711 set_menubar_tooltip("ltr_precedence_menu");
2712 set_menubar_tooltip("arithmetic_precedence_menu");
2713 set_menubar_tooltip("help_menu");
2714 set_menubar_tooltip("about_menu");
2716 // ???
2717 widget = GET_WIDGET("kvbox");
2718 gtk_widget_set_direction(widget, GTK_TEXT_DIR_LTR);
2719 gtk_widget_set_direction(X->fin_panel, GTK_TEXT_DIR_LTR);
2721 /* Make dialogs transient of the main window */
2722 gtk_window_set_transient_for(GTK_WINDOW(X->aframe), GTK_WINDOW(X->kframe));
2723 gtk_window_set_transient_for(GTK_WINDOW(X->spframe), GTK_WINDOW(X->kframe));
2724 gtk_window_set_transient_for(GTK_WINDOW(X->rframe), GTK_WINDOW(X->kframe));
2725 gtk_window_set_transient_for(GTK_WINDOW(X->con_dialog),
2726 GTK_WINDOW(X->kframe));
2728 /* Can't set max length for spin buttons in Glade 2 */
2729 gtk_entry_set_max_length(GTK_ENTRY(X->precision_spin), 2);
2731 gtk_dialog_set_default_response(GTK_DIALOG(X->con_dialog),
2732 GTK_RESPONSE_ACCEPT);
2734 /* Make constant tree model */
2735 X->constants_model = create_constants_model();
2736 treeview = GET_WIDGET("edit_constants_treeview");
2737 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), X->constants_model);
2738 gtk_tree_selection_set_mode(
2739 gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)),
2740 GTK_SELECTION_SINGLE);
2741 add_cf_column(GTK_TREE_VIEW(treeview), _("No."),
2742 COLUMN_NUMBER, FALSE);
2743 add_cf_column(GTK_TREE_VIEW(treeview), _("Value"),
2744 COLUMN_VALUE, TRUE);
2745 add_cf_column(GTK_TREE_VIEW(treeview), _("Description"),
2746 COLUMN_DESCRIPTION, TRUE);
2748 /* Make function tree model */
2749 X->functions_model = create_functions_model();
2750 treeview = GET_WIDGET("edit_functions_treeview");
2751 gtk_dialog_set_default_response(GTK_DIALOG(X->fun_dialog),
2752 GTK_RESPONSE_ACCEPT);
2753 gtk_window_set_transient_for(GTK_WINDOW(X->fun_dialog),
2754 GTK_WINDOW(X->kframe));
2755 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), X->functions_model);
2756 gtk_tree_selection_set_mode(
2757 gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)),
2758 GTK_SELECTION_SINGLE);
2759 add_cf_column(GTK_TREE_VIEW(treeview), _("No."),
2760 COLUMN_NUMBER, FALSE);
2761 add_cf_column(GTK_TREE_VIEW(treeview), _("Value"),
2762 COLUMN_VALUE, TRUE);
2763 add_cf_column(GTK_TREE_VIEW(treeview), _("Description"),
2764 COLUMN_DESCRIPTION, TRUE);
2767 X->display_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
2768 gtk_widget_ensure_style(X->display_item);
2769 font_desc = pango_font_description_copy(X->display_item->style->font_desc);
2770 pango_font_description_set_size(font_desc, 16 * PANGO_SCALE);
2771 gtk_widget_modify_font(X->display_item, font_desc);
2772 pango_font_description_free(font_desc);
2773 gtk_widget_set_name(X->display_item, "displayitem");
2774 // FIXME: We can't allow the display to be editable. See bug #326938
2775 gtk_text_view_set_editable(GTK_TEXT_VIEW(X->display_item),
2776 (v->syntax == EXPRS));
2777 atk_object_set_role(gtk_widget_get_accessible(X->display_item),
2778 ATK_ROLE_EDITBAR);
2780 gtk_widget_realize(X->kframe);
2781 set_win_position();
2783 for (i = 0; i < 3; i++)
2784 g_object_set_data(G_OBJECT(X->trig[i]),
2785 "trig_mode", GINT_TO_POINTER(i));
2786 for (i = 0; i < 4; i++)
2787 g_object_set_data(G_OBJECT(X->base[i]),
2788 "base_mode", GINT_TO_POINTER(i));
2789 for (i = 0; i < 3; i++)
2790 g_object_set_data(G_OBJECT(X->disp[i]),
2791 "numeric_mode", GINT_TO_POINTER(i));
2793 /* Put status image into statusbar (glade doesn't support child widgets
2794 * in statusbars) */
2795 X->status_image = gtk_image_new_from_stock("", GTK_ICON_SIZE_BUTTON);
2796 gtk_widget_show(X->status_image);
2797 gtk_box_pack_start(GTK_BOX(X->statusbar), X->status_image, FALSE, TRUE, 0);
2799 /* Set modes for menu items */
2800 for (i = 1; i < 16; i++) {
2801 SNPRINTF(name, MAXLINE, "shift_left%d_menu", i);
2802 g_object_set_data(G_OBJECT(GET_WIDGET(name)),
2803 "shiftcount", GINT_TO_POINTER(i));
2804 SNPRINTF(name, MAXLINE, "shift_right%d_menu", i);
2805 g_object_set_data(G_OBJECT(GET_WIDGET(name)),
2806 "shiftcount", GINT_TO_POINTER(-i));
2808 g_object_set_data(G_OBJECT(GET_WIDGET("view_basic_menu")),
2809 "calcmode", GINT_TO_POINTER(BASIC));
2810 g_object_set_data(G_OBJECT(GET_WIDGET("view_advanced_menu")),
2811 "calcmode", GINT_TO_POINTER(ADVANCED));
2812 g_object_set_data(G_OBJECT(GET_WIDGET("view_financial_menu")),
2813 "calcmode", GINT_TO_POINTER(FINANCIAL));
2814 g_object_set_data(G_OBJECT(GET_WIDGET("view_scientific_menu")),
2815 "calcmode", GINT_TO_POINTER(SCIENTIFIC));
2817 /* Make shortcuts for accuracy menus */
2818 accel_group = gtk_accel_group_new();
2819 gtk_window_add_accel_group(GTK_WINDOW(X->kframe), accel_group);
2820 for (i = 0; i < 10; i++) {
2821 SNPRINTF(name, MAXLINE, "acc_item%d", i);
2822 widget = GET_WIDGET(name);
2823 g_object_set_data(G_OBJECT(widget), "accuracy", GINT_TO_POINTER(i));
2828 static void
2829 read_cfdefs() /* Read constant/function definitions. */
2831 int n;
2833 for (n = 0; n < MAX_CONSTANTS; n++) {
2834 get_constant(n);
2836 for (n = 0; n < MAX_FUNCTIONS; n++) {
2837 STRCPY(v->fun_vals[n], ""); /* Initially empty function strings. */
2838 get_function(n);
2843 void
2844 ui_init(int *argc, char ***argv)
2846 X = (XVars) LINT_CAST(calloc(1, sizeof(struct Xobject)));
2848 gtk_init(argc, argv);
2850 X->lnp = ui_get_localized_numeric_point();
2852 gtk_rc_get_default_files();
2854 v->home = (char *) g_get_home_dir();
2855 gtk_rc_parse(g_build_path(v->home, RCNAME, NULL));
2857 gtk_window_set_default_icon_name("gnome-calculator");
2861 void
2862 ui_load()
2864 int boolval;
2866 read_cfdefs();
2868 /* Create main gcalctool window. */
2869 create_kframe();
2871 ui_set_show_thousands_seperator(v->show_tsep);
2872 ui_set_show_trailing_zeroes(v->show_zeroes);
2873 ui_set_show_bitcalculating(v->bitcalculating_mode);
2875 ui_set_syntax_mode(v->syntax);
2876 ui_set_display("0.00");
2877 ui_set_mode(v->modetype);
2878 ui_set_numeric_mode(FIX);
2879 ui_set_base(v->base);
2880 ui_set_accuracy(v->accuracy);
2881 ui_set_undo_enabled(FALSE, FALSE);
2882 ui_update_trig_mode();
2884 /* Show the memory register window? */
2885 ui_make_registers();
2886 if (get_boolean_resource(R_REGS, &boolval))
2887 ui_set_registers_visible(boolval);
2889 /* Focus on the clear button */
2890 if (v->modetype == BASIC) {
2891 gtk_window_set_focus(GTK_WINDOW(X->kframe),
2892 GTK_WIDGET(X->clear_buttons[0]));
2893 } else {
2894 gtk_window_set_focus(GTK_WINDOW(X->kframe),
2895 GTK_WIDGET(X->clear_buttons[1]));
2899 void
2900 ui_start()
2902 struct exprm_state *e;
2904 ui_set_base(v->base);
2905 ui_set_trigonometric_mode(v->ttype);
2906 ui_set_numeric_mode(v->dtype);
2908 gtk_widget_show(X->kframe);
2910 switch (v->syntax) {
2911 case NPA:
2912 break;
2914 case EXPRS:
2915 /* Init expression mode.
2916 * This must be executed after do_base is called at init.
2917 * FIXME: The init code here is duplicated elsewhere.
2919 e = get_state();
2920 MPstr_to_num("0", DEC, e->ans);
2921 exp_del();
2922 show_display(e->ans);
2923 break;
2925 default:
2926 assert(0);
2929 gtk_main();