4 * Copyright (c) 1987-2007 Sun Microsystems, Inc. All Rights Reserved.
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)
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
26 #include <sys/param.h>
31 #include <gdk/gdkkeysyms.h>
32 #include <glade/glade.h>
38 #include "functions.h"
39 #include "lr_parser.h"
40 #include "ce_parser.h"
45 #define MAX_ACCELERATORS 8
46 struct button_widget
{
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 /* FIXME: Config value for boolean bitcalculating mode is a string... */
66 static char *Rcstr
[MAXBITCALC
] = { "NO_BITCALCULATING_MODE", "BITCALCULATING_MODE" };
68 /* This table shows the keyboard values that are currently being used:
70 * | 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
71 *-----------+-----------------------------------------------------
72 * Lower: | a b c d e f i l m n p r s t u v x
73 * Upper: | A C D E F G J K L M N P R S T X Y
74 * Numeric: | 0 1 2 3 4 5 6 7 8 9
75 * Other: | @ . + - * / = % ( ) # < > [ ] { } | & ~ ^ ? ! :
76 * | BackSpace Delete Return
77 *-----------+-----------------------------------------------------
80 static struct button_widget button_widgets
[] = {
82 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
83 { GDK_0
, GDK_0
, GDK_KP_0
, GDK_KP_Insert
, 0 }},
86 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
87 { GDK_1
, GDK_1
, GDK_KP_1
, GDK_KP_End
, GDK_R13
, 0 }},
90 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
91 { GDK_2
, GDK_2
, GDK_KP_2
, GDK_KP_Down
, 0 }},
94 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
95 { GDK_3
, GDK_3
, GDK_KP_3
, GDK_KP_Page_Down
, GDK_R15
, 0 }},
98 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
99 { GDK_4
, GDK_4
, GDK_KP_4
, GDK_KP_Left
, 0 }},
102 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
103 { GDK_5
, GDK_5
, GDK_KP_5
, GDK_KP_Begin
, GDK_R11
, 0 }},
106 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
107 { GDK_6
, GDK_6
, GDK_KP_6
, GDK_KP_Right
, 0 }},
110 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
111 { GDK_7
, GDK_7
, GDK_KP_7
, GDK_KP_Home
, GDK_R7
, 0 }},
114 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
115 { GDK_8
, GDK_8
, GDK_KP_8
, GDK_KP_Up
, 0 }},
118 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
119 { GDK_9
, GDK_9
, GDK_KP_9
, GDK_KP_Page_Up
, GDK_R9
, 0 }},
145 {KEY_CLEAR
, "clear_simple",
149 {KEY_CLEAR
, "clear_advanced",
153 {KEY_SHIFT
, "shift_left",
154 { GDK_SHIFT_MASK
, 0 },
157 {KEY_SHIFT
, "shift_right",
158 { GDK_SHIFT_MASK
, 0 },
161 {KEY_SET_ACCURACY
, "accuracy",
162 { GDK_SHIFT_MASK
, 0 },
165 {KEY_CONSTANT
, "constants",
166 { GDK_SHIFT_MASK
, 0, 0 },
167 { GDK_numbersign
, GDK_numbersign
, 0 }},
169 {KEY_FUNCTION
, "functions",
170 { GDK_SHIFT_MASK
, 0 },
174 { GDK_SHIFT_MASK
, 0 },
177 {KEY_RECALL
, "recall",
178 { GDK_SHIFT_MASK
, 0 },
181 {KEY_EXCHANGE
, "exchange",
182 { GDK_SHIFT_MASK
, 0 },
185 {KEY_CLEAR_ENTRY
, "clear_entry_simple",
186 { GDK_CONTROL_MASK
, 0, 0 },
187 { GDK_BackSpace
, GDK_Escape
, 0 }},
189 {KEY_CLEAR_ENTRY
, "clear_entry_advanced",
190 { GDK_CONTROL_MASK
, 0, 0 },
191 { GDK_BackSpace
, GDK_Escape
, 0 }},
193 {KEY_BACKSPACE
, "backspace_simple",
195 { GDK_BackSpace
, 0 }},
197 {KEY_BACKSPACE
, "backspace_advanced",
199 { GDK_BackSpace
, 0 }},
201 {KEY_NUMERIC_POINT
, "numeric_point",
203 { GDK_period
, GDK_KP_Decimal
, GDK_KP_Delete
, GDK_KP_Separator
, 0 }},
205 {KEY_CALCULATE
, "result",
206 { 0, 0, 0, GDK_SHIFT_MASK
, 0 },
207 { GDK_equal
, GDK_KP_Enter
, GDK_Return
, GDK_equal
, 0 }},
209 {KEY_START_BLOCK
, "start_group",
210 { GDK_SHIFT_MASK
, 0 },
211 { GDK_parenleft
, 0 }},
213 {KEY_END_BLOCK
, "end_group",
214 { GDK_SHIFT_MASK
, 0 },
215 { GDK_parenright
, 0 }},
218 { GDK_SHIFT_MASK
, 0, 0, 0 },
219 { GDK_plus
, GDK_plus
, GDK_KP_Add
, 0 }},
221 {KEY_SUBTRACT
, "subtract",
223 { GDK_minus
, GDK_KP_Subtract
, GDK_R4
, 0 }},
225 {KEY_MULTIPLY
, "multiply",
226 { GDK_SHIFT_MASK
, 0, 0, 0, 0 },
227 { GDK_asterisk
, GDK_KP_Multiply
, GDK_x
, GDK_R6
, 0 }},
229 {KEY_DIVIDE
, "divide",
230 { 0, GDK_SHIFT_MASK
, 0, 0, GDK_SHIFT_MASK
, 0 },
231 { GDK_slash
, GDK_slash
, GDK_KP_Divide
, GDK_R5
, GDK_slash
, 0 }},
233 {KEY_CHANGE_SIGN
, "change_sign_simple",
234 { GDK_SHIFT_MASK
, 0 },
237 {KEY_CHANGE_SIGN
, "change_sign_advanced",
238 { GDK_SHIFT_MASK
, 0 },
241 {KEY_INTEGER
, "integer_portion",
245 {KEY_FRACTION
, "fractional_portion",
246 { GDK_SHIFT_MASK
, 0 },
249 {KEY_PERCENTAGE
, "percentage",
250 { GDK_SHIFT_MASK
, 0 },
253 {KEY_SQUARE
, "square",
254 { GDK_SHIFT_MASK
, 0 },
257 {KEY_SQUARE_ROOT
, "sqrt",
261 {KEY_RECIPROCAL
, "reciprocal",
265 {KEY_ABSOLUTE_VALUE
, "abs",
269 {KEY_MASK_16
, "mask_16",
271 { GDK_bracketright
, 0 }},
273 {KEY_MASK_32
, "mask_32",
275 { GDK_bracketleft
, 0 }},
277 {KEY_MODULUS_DIVIDE
, "modulus_divide",
278 { GDK_SHIFT_MASK
, 0 },
281 {KEY_EXPONENTIAL
, "exponential",
282 { GDK_SHIFT_MASK
, 0 },
285 {KEY_E_POW_X
, "pow_e",
286 { GDK_SHIFT_MASK
, 0 },
287 { GDK_braceleft
, 0 }},
289 {KEY_10_POW_X
, "pow_10",
290 { GDK_SHIFT_MASK
, 0 },
291 { GDK_braceright
, 0 }},
293 {KEY_X_POW_Y
, "x_pow_y",
294 { GDK_SHIFT_MASK
, GDK_SHIFT_MASK
, 0 },
295 { GDK_caret
, GDK_asciicircum
, 0 }},
297 {KEY_NATURAL_LOGARITHM
, "natural_logarithm",
298 { GDK_SHIFT_MASK
, 0 },
301 {KEY_LOGARITHM
, "logarithm",
302 { GDK_SHIFT_MASK
, 0 },
305 {KEY_FACTORIAL
, "factorial",
306 { GDK_SHIFT_MASK
, 0 },
309 {KEY_RANDOM
, "random",
310 { GDK_SHIFT_MASK
, 0 },
311 { GDK_question
, 0 }},
314 { GDK_SHIFT_MASK
, 0 },
318 { GDK_SHIFT_MASK
, 0 },
322 { GDK_SHIFT_MASK
, 0 },
326 { GDK_SHIFT_MASK
, 0 },
327 { GDK_asciitilde
, 0 }},
330 { GDK_SHIFT_MASK
, 0 },
334 { GDK_SHIFT_MASK
, 0 },
335 { GDK_ampersand
, 0 }},
345 {KEY_FINC_CTRM
, "finc_compounding_term",
349 {KEY_FINC_DDB
, "finc_double_declining_depreciation",
350 { GDK_SHIFT_MASK
, 0 },
353 {KEY_FINC_FV
, "finc_future_value",
357 {KEY_FINC_PMT
, "finc_periodic_payment",
358 { GDK_SHIFT_MASK
, 0 },
361 {KEY_FINC_PV
, "finc_present_value",
365 {KEY_FINC_RATE
, "finc_periodic_interest_rate",
366 { GDK_SHIFT_MASK
, 0 },
369 {KEY_FINC_SLN
, "finc_straight_line_depreciation",
373 {KEY_FINC_SYD
, "finc_sum_of_the_years_digits_depreciation",
377 {KEY_FINC_TERM
, "finc_term",
381 #define NBUTTONS (sizeof(button_widgets) / sizeof(struct button_widget))
383 #define UI_FILE PACKAGE_GLADE_DIR "/gcalctool.glade"
385 #define MAXBITS 64 /* Bit panel: number of bit fields. */
387 #define GET_WIDGET(name) \
388 glade_xml_get_widget(X->ui, (name))
390 #define SET_MENUBAR_ITEM_STATE(name, state) \
391 g_object_set_data(G_OBJECT(GET_WIDGET(name)), "sensitive", \
392 GINT_TO_POINTER(state));
394 #define CONNECT_SIGNAL(name) glade_xml_signal_connect(X->ui, #name, \
397 struct Xobject
{ /* Gtk+/Xlib graphics object. */
398 GdkAtom clipboard_atom
;
399 GdkAtom primary_atom
;
403 GtkWidget
*kframe
; /* Main window. */
405 GtkTreeModel
*constants_model
;
406 GtkWidget
*con_dialog
; /* Edit constants dialog. */
408 GtkTreeModel
*functions_model
;
409 GtkWidget
*fun_dialog
; /* Edit functions dialog. */
410 GtkWidget
*menubar
; // FIXME: Why is this needed?
412 GtkWidget
*bit_panel
;
413 GtkWidget
*bits
[MAXBITS
]; /* The 0/1 labels in the bit panel. */
415 GtkWidget
*status_image
; /* Statusbar image */
416 GtkWidget
*statusbar
;
418 GtkWidget
*aframe
; /* ASCII window. */
419 GtkWidget
*aframe_ch
;
421 GtkWidget
*display_item
; /* Calculator display. */
422 GtkTextBuffer
*display_buffer
; /* Buffer used in display */
423 GtkWidget
*scrolledwindow
; /* Scrolled window for display_item. */
425 GtkWidget
*rframe
; /* Register window. */
426 GtkWidget
*regs
[MAX_REGISTERS
]; /* Memory registers. */
428 GtkWidget
*spframe
; /* Set Precision window. */
429 GtkWidget
*precision_spin
;
431 GtkWidget
*buttons
[NBUTTONS
];
432 GtkWidget
*digit_buttons
[16];
433 GtkWidget
*clear_buttons
[2];
435 GtkWidget
*bas_panel
; /* Panel containing basic mode widgets. */
436 GtkWidget
*adv_panel
; /* Panel containing advanced mode widgets. */
437 GtkWidget
*fin_panel
; /* Panel containing financial mode widgets. */
438 GtkWidget
*sci_panel
; /* Panel containing scientific mode widgets. */
439 GtkWidget
*mode_panel
; /* Panel containing scientific mode widgets. */
441 /* Labels for popup menus */
442 GtkWidget
*constant_menu_labels
[MAX_CONSTANTS
];
443 GtkWidget
*function_menu_labels
[MAX_FUNCTIONS
];
444 GtkWidget
*memory_store_labels
[MAX_REGISTERS
];
445 GtkWidget
*memory_recall_labels
[MAX_REGISTERS
];
446 GtkWidget
*memory_exchange_labels
[MAX_REGISTERS
];
448 /* Scientific mode widgets */
449 GtkWidget
*hyperbolic_toggle
; /* Hyperbolic mode. */
450 GtkWidget
*inverse_toggle
; /* Inverse mode. */
451 GtkWidget
*base
[MAXBASES
]; /* Numeric base radio buttons. */
452 GtkWidget
*disp
[MAXDISPMODES
]; /* Numeric display mode. */
453 GtkWidget
*trig
[MAXTRIGMODES
]; /* Trigonometric mode. */
455 char *lnp
; /* Localized numerical point (UTF8 format) */
457 gboolean warn_change_mode
; /* Should we warn user when changing modes? */
458 gboolean bitcalculating_mode
;
461 typedef struct Xobject
*XVars
;
474 /* FIXME: Move this into display.c (reset_display) */
478 struct exprm_state
*e
;
483 MPstr_to_num("0", DEC
, v
->MPdisp_val
);
484 show_display(v
->MPdisp_val
);
485 clear_undo_history();
490 MPstr_to_num("0", DEC
, e
->ans
);
492 show_display(e
->ans
);
501 ui_set_syntax_mode(enum syntax mode
)
510 ui_set_statusbar(_("Activated no operator precedence mode"), "");
513 _("Activated expression mode with operator precedence"), "");
516 /* Save the syntax mode */
517 set_resource(R_SYNTAX
, Rsstr
[v
->syntax
]);
520 ui_set_mode(v
->modetype
);
523 if (v
->syntax
== EXPRS
) {
524 widget
= GET_WIDGET("arithmetic_precedence_menu");
525 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget
), TRUE
);
527 widget
= GET_WIDGET("ltr_precedence_menu");
528 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget
), TRUE
);
534 ui_set_accuracy(int accuracy
)
538 char *desc
, *current
, *tooltip
;
540 v
->accuracy
= accuracy
;
542 SNPRINTF(text
, MAXLINE
, _("Other (%d) ..."), accuracy
);
543 widget
= gtk_bin_get_child(GTK_BIN(GET_WIDGET("acc_item_other")));
544 gtk_label_set_text(GTK_LABEL(widget
), text
);
546 desc
= g_strdup_printf(ngettext("Set accuracy from 0 to %d numeric places.",
547 "Set accuracy from 0 to %d numeric places.",
551 /* Translator: This refers to the current accuracy setting */
552 current
= g_strdup_printf(ngettext("Currently set to %d places.",
553 "Currently set to %d places.",
556 tooltip
= g_strdup_printf ("%s %s [A]", desc
, current
);
557 gtk_widget_set_tooltip_text (GET_WIDGET("calc_accuracy_button"), tooltip
);
562 if (accuracy
>= 0 && accuracy
<= 9) {
563 SNPRINTF(text
, MAXLINE
, "acc_item%d", accuracy
);
564 widget
= GET_WIDGET(text
);
565 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget
), TRUE
);
568 gtk_spin_button_set_value(GTK_SPIN_BUTTON(X
->precision_spin
),
571 set_int_resource(R_ACCURACY
, accuracy
);
576 /* Hide the manual dialog */
577 gtk_widget_hide(X
->spframe
);
582 ui_update_trig_mode()
584 static char *sine_labels
[] = {N_("Sin"), N_("Sinh"),
585 N_("Sin<sup>-1</sup>"),
586 N_("Sinh<sup>-1</sup>")};
587 static int sine_functions
[] = {KEY_SIN
, KEY_SINH
, KEY_ASIN
, KEY_ASINH
};
588 static char *cosine_labels
[] = {N_("Cos"), N_("Cosh"),
589 N_("Cos<sup>-1</sup>"),
590 N_("Cosh<sup>-1</sup>")};
591 static int cosine_functions
[] = {KEY_COS
, KEY_COSH
, KEY_ACOS
, KEY_ACOSH
};
592 static char *tangent_labels
[] = {N_("Tan"), N_("Tanh"),
593 N_("Tan<sup>-1</sup>"),
594 N_("Tanh<sup>-1</sup>")};
595 static int tangent_functions
[] = {KEY_TAN
, KEY_TANH
, KEY_ATAN
, KEY_ATANH
};
598 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X
->hyperbolic_toggle
))) {
601 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X
->inverse_toggle
))) {
605 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("sine_label")),
607 g_object_set_data(G_OBJECT(GET_WIDGET("calc_sine_button")), "calc_function",
608 GINT_TO_POINTER(sine_functions
[index
]));
610 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("cosine_label")),
611 cosine_labels
[index
]);
612 g_object_set_data(G_OBJECT(GET_WIDGET("calc_cosine_button")), "calc_function",
613 GINT_TO_POINTER(cosine_functions
[index
]));
615 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("tangent_label")),
616 tangent_labels
[index
]);
617 g_object_set_data(G_OBJECT(GET_WIDGET("calc_tangent_button")), "calc_function",
618 GINT_TO_POINTER(tangent_functions
[index
]));
623 ui_set_hyperbolic_state(gboolean state
)
625 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->hyperbolic_toggle
), state
);
626 ui_update_trig_mode();
631 ui_set_inverse_state(gboolean state
)
633 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->inverse_toggle
), state
);
634 ui_update_trig_mode();
639 ui_set_trigonometric_mode(enum trig_type mode
)
641 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->trig
[mode
]), 1);
646 ui_set_numeric_mode(enum base_type mode
)
648 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->disp
[mode
]), 1);
653 ui_set_show_thousands_seperator(gboolean visible
)
657 v
->show_tsep
= visible
;
658 set_boolean_resource(R_TSEP
, v
->show_tsep
);
660 menu
= GET_WIDGET("show_thousands_separator_menu");
661 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
663 syntaxdep_show_display();
669 ui_set_show_bitcalculating(gboolean visible
)
673 X
->bitcalculating_mode
= visible
;
674 ui_set_mode(v
->modetype
);
675 set_resource(R_BITCALC
, Rcstr
[visible
? 1 : 0]);
677 menu
= GET_WIDGET("show_bitcalculating_menu");
678 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
683 ui_set_show_trailing_zeroes(gboolean visible
)
687 v
->show_zeroes
= visible
;
688 set_boolean_resource(R_ZEROES
, visible
);
690 syntaxdep_show_display();
693 menu
= GET_WIDGET("show_trailing_zeroes_menu");
694 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
695 menu
= GET_WIDGET("acc_trailing_zeroes_item");
696 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
701 ui_set_undo_enabled(gboolean undo
, gboolean redo
)
703 gtk_widget_set_sensitive(GET_WIDGET("undo_menu"), undo
);
704 gtk_widget_set_sensitive(GET_WIDGET("redo_menu"), redo
);
711 Display
*dpy
= GDK_DISPLAY();
712 char client_hostname
[MAXHOSTNAMELEN
+ 4];
713 char hostname
[MAXHOSTNAMELEN
];
714 char *display
= DisplayString(dpy
);
715 char *scanner
= display
;
717 GETHOSTNAME(hostname
, MAXHOSTNAMELEN
);
723 while (*scanner
!= ':') {
729 if (strcmp(display
, hostname
) &&
730 strcmp(display
, "localhost") &&
731 strcmp(display
, "unix") &&
732 strcmp(display
, "")) {
733 SPRINTF(client_hostname
, " [%s] ", hostname
);
735 STRCPY(client_hostname
, "");
740 if (client_hostname
[0] == '\0')
743 return (strdup(client_hostname
));
748 ui_set_mode(enum mode_type mode
)
752 char *hostname
, title
[MAXLINE
];
759 set_resource(R_MODE
, Rmstr
[(int) v
->modetype
]);
761 /* Show/enable the widgets used in this mode */
762 g_object_set(G_OBJECT(X
->bas_panel
), "visible", mode
== BASIC
, NULL
);
763 g_object_set(G_OBJECT(X
->adv_panel
), "visible", mode
!= BASIC
, NULL
);
764 g_object_set(G_OBJECT(X
->fin_panel
), "visible", mode
== FINANCIAL
, NULL
);
765 g_object_set(G_OBJECT(X
->mode_panel
), "visible", mode
== SCIENTIFIC
, NULL
);
766 g_object_set(G_OBJECT(X
->sci_panel
), "visible", mode
== SCIENTIFIC
, NULL
);
767 g_object_set(G_OBJECT(X
->bit_panel
), "visible",
768 mode
== SCIENTIFIC
&& X
->bitcalculating_mode
, NULL
);
769 gtk_widget_set_sensitive(GET_WIDGET("show_bitcalculating_menu"),
771 gtk_widget_set_sensitive(GET_WIDGET("show_trailing_zeroes_menu"),
773 gtk_widget_set_sensitive(GET_WIDGET("show_registers_menu"),
776 /* HACK: Some horrible hack down below to keep the buttons the same size.
777 * There must be a safer way of doing this... */
778 r
= g_new0(GtkRequisition
, 1);
779 gtk_widget_size_request(X
->menubar
, r
);
782 gtk_widget_size_request(X
->display_item
, r
);
783 w
= MAX(w
, r
->width
);
786 if (GTK_WIDGET_VISIBLE(X
->fin_panel
)) {
787 gtk_widget_size_request(X
->fin_panel
, r
);
788 w
= MAX(w
, r
->width
);
792 if (GTK_WIDGET_VISIBLE(X
->mode_panel
)) {
793 gtk_widget_size_request(X
->mode_panel
, r
);
794 w
= MAX(w
, r
->width
);
798 if (GTK_WIDGET_VISIBLE(X
->sci_panel
)) {
799 gtk_widget_size_request(X
->sci_panel
, r
);
800 w
= MAX(w
, r
->width
);
805 /* For initial display. */
806 gtk_window_set_default_size(GTK_WINDOW(X
->kframe
), w
, h
);
807 gtk_window_resize(GTK_WINDOW(X
->kframe
), w
, h
);
810 if((hostname
= make_hostname())) {
811 SNPRINTF(title
, MAXLINE
, hostname_titles
[mode
], hostname
);
814 SNPRINTF(title
, MAXLINE
, titles
[mode
]);
816 gtk_window_set_title(GTK_WINDOW(X
->kframe
), title
);
818 /* Update the menu */
821 menu
= GET_WIDGET("view_basic_menu");
825 menu
= GET_WIDGET("view_advanced_menu");
829 menu
= GET_WIDGET("view_financial_menu");
833 menu
= GET_WIDGET("view_scientific_menu");
840 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), TRUE
);
845 ui_set_statusbar(gchar
*text
, const gchar
*imagename
)
847 GtkImage
*image
= GTK_IMAGE(X
->status_image
);
853 gtk_image_set_from_stock(image
, imagename
, GTK_ICON_SIZE_BUTTON
);
854 gtk_statusbar_pop(GTK_STATUSBAR(X
->statusbar
), 0);
855 gtk_statusbar_push(GTK_STATUSBAR(X
->statusbar
), 0, text
);
860 bin_str(int MP_value
[MP_SIZE
], char *str
, int maxbits
)
862 int i
, MP0
[MP_SIZE
], MP1
[MP_SIZE
], MP2
[MP_SIZE
], MP3
[MP_SIZE
];
865 MPstr_to_num("0", DEC
, MP0
);
866 MPstr_to_num("1", DEC
, MP1
);
867 MPstr_to_num("2", DEC
, MP2
);
869 if (mplt(MP_value
, MP0
)) {
870 mpcmim(MP_value
, MP0
);
871 mpadd(MP0
, MP1
, MP0
);
874 mpcmim(MP_value
, MP0
);
877 for (i
= 0; i
< maxbits
; i
++) {
878 double lsb
; /* Least significant bit. */
879 calc_and(MP3
, MP0
, MP1
);
883 str
[maxbits
- i
-1] = (neg
) ? '1' : '0';
885 str
[maxbits
- i
-1] = (neg
) ? '0' : '1';
888 mpdiv(MP0
, MP2
, MP3
);
899 int bit_str_len
, i
, MP1
[MP_SIZE
], MP2
[MP_SIZE
];
901 char str
[64], label
[3];
902 int ret
= usable_num(MP
);
906 MPstr_to_num(v
->display
, v
->base
, MP1
);
908 if (mpeq(MP1
, MP2
)) {
909 char *bit_str
, label
[3], tmp
[MAXLINE
];
910 int toclear
= (v
->current
== KEY_CLEAR_ENTRY
)
913 bit_str
= make_fixed(MP1
, tmp
, BIN
, MAXLINE
, toclear
);
914 bit_str_len
= strlen(bit_str
);
915 if (bit_str_len
<= MAXBITS
) {
916 gtk_widget_set_sensitive(X
->bit_panel
, TRUE
);
919 for (i
= 0; i
< MAXBITS
; i
++) {
920 label
[1] = (i
< bit_str_len
) ? bit_str
[bit_str_len
-i
-1] : '0';
921 gtk_label_set_text(GTK_LABEL(X
->bits
[MAXBITS
- i
- 1]), label
);
927 gtk_widget_set_sensitive(X
->bit_panel
, FALSE
);
931 if (ret
|| !is_integer(MP
)) {
932 gtk_widget_set_sensitive(X
->bit_panel
, FALSE
);
935 bin_str(MP
, str
, 64);
936 gtk_widget_set_sensitive(X
->bit_panel
, TRUE
);
939 for (i
= 0; i
< 64; i
++) {
940 label
[1] = str
[64 - i
- 1];
941 gtk_label_set_text(GTK_LABEL(X
->bits
[64 - i
- 1]), label
);
954 if (GTK_WIDGET_VISIBLE(
955 GTK_SCROLLED_WINDOW(X
->scrolledwindow
)->hscrollbar
)) {
958 set
= gtk_scrolled_window_get_hadjustment(
959 GTK_SCROLLED_WINDOW(X
->scrolledwindow
));
960 gtk_adjustment_set_value(set
, set
->upper
);
961 gtk_scrolled_window_set_hadjustment(
962 GTK_SCROLLED_WINDOW(X
->scrolledwindow
), set
);
968 ui_set_display(char *str
, int cursor
)
970 char localized
[MAX_LOCALIZED
];
973 if (str
== NULL
|| str
[0] == '\0') {
976 if (v
->noparens
== 0) {
977 localize_number(localized
, str
);
981 gtk_text_buffer_set_text(X
->display_buffer
, str
, -1);
984 gtk_text_buffer_get_end_iter(X
->display_buffer
, &iter
);
986 gtk_text_buffer_get_iter_at_offset(X
->display_buffer
, &iter
, cursor
);
988 gtk_text_buffer_place_cursor(X
->display_buffer
, &iter
);
996 /* When an error condition occurs:
998 * - make insensitive all buttons except Clr.
999 * - make all Scientific mode toggles and checkboxes insensitive.
1000 * - make all menubar items insensitive except:
1004 * When the error condition is cleared, resensitise everything, setting
1005 * the numeric base buttons correctly.
1009 ui_set_error_state(gboolean error
)
1015 for (i
= 0; i
< NBUTTONS
; i
++) {
1016 gtk_widget_set_sensitive(X
->buttons
[i
], !v
->error
);
1018 /* Clr button always sensitive. */
1019 gtk_widget_set_sensitive(X
->clear_buttons
[0], TRUE
);
1020 gtk_widget_set_sensitive(X
->clear_buttons
[1], TRUE
);
1023 ui_set_base(v
->base
);
1026 gtk_widget_set_sensitive(X
->mode_panel
, !v
->error
);
1028 // FIXME: Isn't this missing a whole lot of widgets?
1029 SET_MENUBAR_ITEM_STATE("copy_menu", !v
->error
);
1030 SET_MENUBAR_ITEM_STATE("paste_menu", !v
->error
);
1031 SET_MENUBAR_ITEM_STATE("insert_ascii_menu", !v
->error
);
1032 SET_MENUBAR_ITEM_STATE("view_basic_menu", !v
->error
);
1033 SET_MENUBAR_ITEM_STATE("view_advanced_menu", !v
->error
);
1034 SET_MENUBAR_ITEM_STATE("view_financial_menu", !v
->error
);
1035 SET_MENUBAR_ITEM_STATE("view_scientific_menu", !v
->error
);
1036 SET_MENUBAR_ITEM_STATE("show_trailing_zeroes_menu",
1037 !v
->error
&& (v
->modetype
== SCIENTIFIC
));
1038 SET_MENUBAR_ITEM_STATE("show_thousands_separator_menu", !v
->error
);
1039 SET_MENUBAR_ITEM_STATE("show_registers_menu", !v
->error
);
1040 SET_MENUBAR_ITEM_STATE("arithmetic_precedence_menu", !v
->error
);
1041 SET_MENUBAR_ITEM_STATE("about_menu", !v
->error
);
1053 ui_get_localized_numeric_point(void)
1055 const char *decimal_point
;
1057 decimal_point
= localeconv()->decimal_point
;
1059 return (g_locale_to_utf8(decimal_point
, -1, NULL
, NULL
, NULL
));
1064 ui_set_base(enum base_type base
)
1066 int i
, baseval
= basevals
[(int) base
];
1070 for (i
= 0; i
< 16; i
++) {
1071 gtk_widget_set_sensitive(X
->digit_buttons
[i
], i
< baseval
);
1073 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->base
[base
]), 1);
1078 ui_set_registers_visible(gboolean visible
)
1082 ui_make_registers();
1084 menu
= GET_WIDGET("show_registers_menu");
1085 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
1087 gtk_widget_realize(X
->rframe
);
1090 if (gdk_window_is_visible(X
->rframe
->window
)) {
1091 gdk_window_raise(X
->rframe
->window
);
1094 ds_position_popup(X
->kframe
, X
->rframe
, DS_POPUP_ABOVE
);
1095 gtk_widget_show(X
->rframe
);
1097 gtk_widget_hide(X
->rframe
);
1100 set_boolean_resource(R_REGS
, visible
);
1105 ui_get_display(void)
1107 GtkTextIter start
, end
;
1108 gtk_text_buffer_get_bounds(X
->display_buffer
, &start
, &end
);
1109 return (gtk_text_buffer_get_text(X
->display_buffer
,
1120 g_object_get(G_OBJECT(X
->display_buffer
), "cursor-position", &pos
, NULL
);
1122 /* Convert the last position to -1 */
1123 if (pos
== gtk_text_buffer_get_char_count(X
->display_buffer
)) {
1133 about_cb(GtkWidget
*widget
)
1135 const gchar
*authors
[] = {
1136 "Rich Burridge <rich.burridge@sun.com>",
1137 "Sami Pietila <sampie@ariana-dsl.utu.fi>",
1138 "Robert Ancell <robert.ancell@gmail.com>",
1141 const gchar
*documenters
[] = {
1145 const gchar
*translator_credits
= _("translator-credits");
1147 const char *license
[] = {
1148 N_("Gcalctool is free software; you can redistribute it and/or modify\n"
1149 "it under the terms of the GNU General Public License as published by\n"
1150 "the Free Software Foundation; either version 2 of the License, or\n"
1151 "(at your option) any later version.\n"),
1152 N_("Gcalctool is distributed in the hope that it will be useful,\n"
1153 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1154 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1155 "GNU General Public License for more details.\n"),
1156 N_("You should have received a copy of the GNU General Public License\n"
1157 "along with Gcalctool; if not, write to the Free Software Foundation, Inc.,\n"
1158 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n")
1161 char *license_trans
= g_strconcat(_(license
[0]), "\n",
1162 _(license
[1]), "\n",
1163 _(license
[2]), "\n",
1166 gtk_show_about_dialog(GTK_WINDOW(X
->kframe
),
1167 "name",_("Gcalctool"),
1169 "copyright", _("\xc2\xa9 1986-2007 The Gcalctool authors"),
1170 "license", license_trans
,
1171 "comments", _("Calculator with financial and scientific modes."),
1173 "documenters", documenters
,
1174 "translator_credits", translator_credits
,
1175 "logo-icon-name", "gnome-calculator",
1181 cell_edited_cb(GtkCellRendererText
*cell
, const gchar
*path_string
,
1182 const gchar
*new_text
, gpointer data
)
1184 GtkTreeModel
*model
= (GtkTreeModel
*) data
;
1185 GtkTreePath
*path
= gtk_tree_path_new_from_string(path_string
);
1190 column
= g_object_get_data(G_OBJECT(cell
), "column");
1192 gtk_tree_model_get_iter(model
, &iter
, path
);
1194 switch (GPOINTER_TO_INT(column
)) {
1196 gtk_tree_model_get(model
, &iter
, column
, &old_text
, -1);
1198 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, column
,
1199 g_strdup(new_text
), -1);
1202 case COLUMN_DESCRIPTION
:
1203 gtk_tree_model_get(model
, &iter
, column
, &old_text
, -1);
1205 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, column
,
1206 g_strdup(new_text
), -1);
1210 gtk_tree_path_free(path
);
1215 add_cf_column(GtkTreeView
*treeview
, gchar
*name
, gint colno
, gboolean editable
)
1217 GtkCellRenderer
*renderer
;
1218 GtkTreeModel
*model
= gtk_tree_view_get_model(treeview
);
1220 renderer
= gtk_cell_renderer_text_new();
1222 g_signal_connect(G_OBJECT(renderer
), "edited",
1223 G_CALLBACK(cell_edited_cb
), model
);
1225 g_object_set_data(G_OBJECT(renderer
), "column", GINT_TO_POINTER(colno
));
1228 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview
),
1231 "editable", COLUMN_EDITABLE
,
1234 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview
),
1244 aframe_response_cb(GtkWidget
*dialog
, gint response_id
)
1249 if (response_id
== GTK_RESPONSE_OK
) {
1250 ch
= (char *) gtk_entry_get_text(GTK_ENTRY(X
->aframe_ch
));
1252 mpcim(&val
, v
->MPdisp_val
);
1253 show_display(v
->MPdisp_val
);
1256 gtk_widget_hide(dialog
);
1261 aframe_delete_cb(GtkWidget
*dialog
)
1263 aframe_response_cb(dialog
, GTK_RESPONSE_CANCEL
);
1270 aframe_activate_cb(GtkWidget
*entry
)
1272 aframe_response_cb(X
->aframe
, GTK_RESPONSE_OK
);
1278 rframe_response_cb(GtkWidget
*dialog
, int response_id
)
1280 ui_set_registers_visible(FALSE
);
1285 rframe_delete_cb(GtkWidget
*dialog
)
1287 rframe_response_cb(dialog
, GTK_RESPONSE_OK
);
1294 disp_cb(GtkWidget
*widget
)
1296 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
)))
1297 do_numtype((enum num_type
) g_object_get_data(G_OBJECT(widget
), "numeric_mode"));
1303 base_cb(GtkWidget
*widget
)
1305 enum base_type base
;
1307 base
= (enum base_type
) g_object_get_data(G_OBJECT(widget
),
1309 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
))) {
1315 static void do_button(int function
, int arg
)
1317 switch (v
->syntax
) {
1319 process_item(&buttons
[function
], arg
);
1321 if (v
->new_input
&& v
->dtype
== FIX
) {
1322 STRNCPY(v
->fnum
, v
->display
, MAX_DIGITS
- 1);
1323 ui_set_display(v
->fnum
, -1);
1328 do_expression(function
, arg
, get_cursor());
1341 GError
*error
= NULL
;
1348 const char * const * langs
= g_get_language_names ();
1350 for (i
= 0; langs
[i
]; i
++) {
1352 if (strchr (lang
, '.')) {
1356 uri
= g_build_filename(PACKAGE_DATA_DIR
,
1357 "/gnome/help/gcalctool/",
1362 if (g_file_test (uri
, G_FILE_TEST_EXISTS
)) {
1367 command
= g_strconcat ("gnome-open ghelp://", uri
, NULL
);
1368 gscreen
= gdk_screen_get_default();
1369 gdk_spawn_command_line_on_screen (gscreen
, command
, &error
);
1373 d
= gtk_message_dialog_new(NULL
,
1374 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1375 GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
,
1377 gtk_dialog_run(GTK_DIALOG(d
));
1378 gtk_widget_destroy(d
);
1379 g_error_free(error
);
1389 put_constant(int n
, char *con_value
, char *con_name
)
1392 char *cstr
= g_strdup(con_value
);
1394 /* Constants are written out with no thousands seaparator and with a radix
1398 SNPRINTF(key
, MAXLINE
, "constant%1dvalue", n
);
1399 set_resource(key
, cstr
);
1402 SNPRINTF(key
, MAXLINE
, "constant%1dname", n
);
1403 set_resource(key
, con_name
);
1408 put_function(int n
, char *fun_value
, char *fun_name
)
1412 SNPRINTF(key
, MAXLINE
, "function%1dvalue", n
);
1413 set_resource(key
, fun_value
);
1415 SNPRINTF(key
, MAXLINE
, "function%1dname", n
);
1416 set_resource(key
, fun_name
);
1422 constant_menu_cb(GtkMenuItem
*menu
)
1424 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "constant_id"));
1425 do_button(KEY_CONSTANT
, arg
);
1431 function_menu_cb(GtkMenuItem
*menu
)
1433 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "function_id"));
1434 do_button(KEY_FUNCTION
, arg
);
1440 store_menu_cb(GtkMenuItem
*menu
)
1442 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "register_id"));
1443 do_button(KEY_STORE
, arg
);
1449 recall_menu_cb(GtkMenuItem
*menu
)
1451 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "register_id"));
1452 do_button(KEY_RECALL
, arg
);
1458 exchange_menu_cb(GtkMenuItem
*menu
)
1460 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "register_id"));
1461 do_button(KEY_EXCHANGE
, arg
);
1466 update_constants_menu(void)
1468 char mline
[MAXLINE
];
1471 for (i
= 0; i
< MAX_CONSTANTS
; i
++) {
1472 SNPRINTF(mline
, MAXLINE
,
1473 "<span weight=\"bold\">%s_%1d:</span> %s [%s]", _("C"), i
,
1474 make_number(v
->MPcon_vals
[i
], DEC
, TRUE
),
1476 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->constant_menu_labels
[i
]), mline
);
1482 update_functions_menu(void)
1484 char mline
[MAXLINE
];
1487 for (i
= 0; i
< MAX_FUNCTIONS
; i
++) {
1488 if (strlen(v
->fun_vals
[i
]) != 0) {
1489 SNPRINTF(mline
, MAXLINE
,
1490 "<span weight=\"bold\">%s_%1d:</span> %s [%s]",
1491 _("F"), i
, v
->fun_vals
[i
], v
->fun_names
[i
]);
1492 gtk_widget_show(gtk_widget_get_parent(X
->function_menu_labels
[i
]));
1493 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->function_menu_labels
[i
]), mline
);
1496 gtk_widget_hide(gtk_widget_get_parent(X
->function_menu_labels
[i
]));
1502 edit_constants_response_cb(GtkDialog
*dialog
, gint id
)
1509 if (id
== GTK_RESPONSE_HELP
) {
1513 if (id
== GTK_RESPONSE_ACCEPT
) {
1514 if (gtk_tree_model_get_iter_first(X
->constants_model
, &iter
)) {
1516 gtk_tree_model_get(X
->constants_model
, &iter
,
1517 COLUMN_NUMBER
, &number
,
1518 COLUMN_VALUE
, &value
,
1519 COLUMN_DESCRIPTION
, &description
, -1);
1520 MPstr_to_num(value
, DEC
, v
->MPcon_vals
[number
]);
1521 STRNCPY(v
->con_names
[number
], description
, MAXLINE
- 1);
1522 put_constant(number
, value
, description
);
1523 } while (gtk_tree_model_iter_next(X
->constants_model
, &iter
));
1527 gtk_widget_hide(GTK_WIDGET(dialog
));
1532 edit_constants_delete_cb(GtkDialog
*dialog
)
1534 edit_constants_response_cb(dialog
, GTK_RESPONSE_CANCEL
);
1540 edit_functions_response_cb(GtkDialog
*dialog
, gint id
)
1547 if (id
== GTK_RESPONSE_HELP
) {
1551 if (id
== GTK_RESPONSE_ACCEPT
) {
1552 if (gtk_tree_model_get_iter_first(X
->functions_model
, &iter
)) {
1554 gtk_tree_model_get(X
->functions_model
, &iter
,
1555 COLUMN_NUMBER
, &number
,
1556 COLUMN_VALUE
, &value
,
1557 COLUMN_DESCRIPTION
, &description
, -1);
1558 STRNCPY(v
->fun_vals
[number
], convert(value
), MAXLINE
- 1);
1559 STRNCPY(v
->fun_names
[number
], description
, MAXLINE
- 1);
1560 put_function(number
, value
, description
);
1561 } while (gtk_tree_model_iter_next(X
->functions_model
, &iter
));
1565 gtk_widget_hide(GTK_WIDGET(dialog
));
1570 edit_functions_delete_cb(GtkDialog
*dialog
)
1572 edit_functions_response_cb(dialog
, GTK_RESPONSE_CANCEL
);
1578 static GtkTreeModel
*
1579 create_constants_model()
1582 GtkListStore
*model
;
1585 model
= gtk_list_store_new(NUM_COLUMNS
, G_TYPE_INT
, G_TYPE_STRING
,
1586 G_TYPE_STRING
, G_TYPE_BOOLEAN
);
1587 for (i
= 0; i
< MAX_CONSTANTS
; i
++) {
1588 gtk_list_store_append(model
, &iter
);
1590 gtk_list_store_set(model
, &iter
,
1592 COLUMN_EDITABLE
, TRUE
,
1596 return (GTK_TREE_MODEL(model
));
1601 static GtkTreeModel
*
1602 create_functions_model()
1605 GtkListStore
*model
;
1608 model
= gtk_list_store_new(NUM_COLUMNS
, G_TYPE_INT
, G_TYPE_STRING
,
1609 G_TYPE_STRING
, G_TYPE_BOOLEAN
);
1610 for (i
= 0; i
< MAX_FUNCTIONS
; i
++) {
1611 gtk_list_store_append(model
, &iter
);
1613 gtk_list_store_set(model
, &iter
,
1615 COLUMN_EDITABLE
, TRUE
,
1619 return (GTK_TREE_MODEL(model
));
1624 ui_make_registers() /* Calculate memory register frame values. */
1626 char *mval
, key
[MAXLINE
];
1629 for (n
= 0; n
< MAX_REGISTERS
; n
++) {
1630 mval
= make_number(v
->MPmvals
[n
], v
->base
, TRUE
);
1631 gtk_entry_set_width_chars(GTK_ENTRY(X
->regs
[n
]), strlen(mval
));
1632 gtk_entry_set_text(GTK_ENTRY(X
->regs
[n
]), mval
);
1633 SNPRINTF(key
, MAXLINE
, "register%d", n
);
1634 set_resource(key
, mval
);
1644 (void) gdk_window_get_origin(X
->kframe
->window
, &x
, &y
);
1645 set_int_resource(R_XPOS
, x
);
1646 set_int_resource(R_YPOS
, y
);
1651 change_mode(int mode
)
1656 ui_set_numeric_mode(FIX
);
1658 ui_set_show_thousands_seperator(FALSE
);
1659 ui_set_show_trailing_zeroes(FALSE
);
1660 ui_set_mode(v
->modetype
);
1668 request_change_mode()
1670 GtkWidget
*dialog
, *request_check
, *button
;
1673 if (!X
->warn_change_mode
) {
1677 dialog
= gtk_message_dialog_new(GTK_WINDOW(X
->kframe
),
1678 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1679 GTK_MESSAGE_WARNING
,
1682 _("Changing Modes Clears Calculation"));
1683 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog
),
1685 _("When you change modes, the current calculation "
1686 "will be cleared, and the base will be reset to "
1689 request_check
= gtk_check_button_new_with_mnemonic(_("_Do not warn me again"));
1690 gtk_box_pack_end(GTK_BOX(GTK_DIALOG(dialog
)->vbox
),
1691 request_check
, FALSE
, FALSE
, 0);
1693 button
= gtk_dialog_add_button(GTK_DIALOG(dialog
),
1694 _("C_hange Mode"), GTK_RESPONSE_ACCEPT
);
1695 gtk_button_set_image(GTK_BUTTON(button
),
1696 gtk_image_new_from_stock(GTK_STOCK_REFRESH
,
1697 GTK_ICON_SIZE_BUTTON
));
1698 /* Set default focus on affirmative button */
1699 gtk_widget_grab_focus(button
);
1701 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog
),
1702 GTK_RESPONSE_ACCEPT
,
1703 GTK_RESPONSE_CANCEL
,
1706 gtk_window_set_position(GTK_WINDOW(dialog
),
1707 GTK_WIN_POS_CENTER_ON_PARENT
);
1709 gtk_widget_show_all(dialog
);
1710 response
= gtk_dialog_run(GTK_DIALOG(dialog
));
1712 // FIXME: Save this in GConf
1713 X
->warn_change_mode
= !gtk_toggle_button_get_active(
1714 GTK_TOGGLE_BUTTON(request_check
));
1716 gtk_widget_destroy(dialog
);
1718 return (response
== GTK_RESPONSE_ACCEPT
);
1724 bit_toggle_cb(GtkWidget
*event_box
, GdkEventButton
*event
)
1727 unsigned long long lval
;
1728 int n
, MP1
[MP_SIZE
], index
;
1730 index
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box
),
1732 n
= MAXBITS
- index
- 1;
1733 MPstr_to_num(v
->display
, v
->base
, MP1
);
1734 mpcmd(MP1
, &number
);
1735 lval
= (long long) number
;
1737 if (lval
& (1LL << n
)) {
1738 lval
&= ~(1LL << n
);
1739 gtk_label_set_text(GTK_LABEL(X
->bits
[index
]), " 0");
1742 gtk_label_set_text(GTK_LABEL(X
->bits
[index
]), " 1");
1745 number
= (double) lval
;
1746 mpcdm(&number
, v
->MPdisp_val
);
1747 show_display(v
->MPdisp_val
);
1755 menu_item_select_cb(GtkWidget
*widget
)
1757 GtkStatusbar
*statusbar
= GTK_STATUSBAR(X
->statusbar
);
1761 context_id
= gtk_statusbar_get_context_id(statusbar
, "menuhelp");
1763 tooltip
= (gchar
*)g_object_get_data(G_OBJECT(widget
), "tooltip");
1765 gtk_statusbar_push(statusbar
, context_id
, tooltip
);
1772 menu_item_deselect_cb(GtkWidget
*widget
)
1774 GtkStatusbar
*statusbar
= GTK_STATUSBAR(X
->statusbar
);
1777 context_id
= gtk_statusbar_get_context_id(statusbar
, "menuhelp");
1778 gtk_statusbar_pop(statusbar
, context_id
);
1783 set_menubar_tooltip(gchar
*menu_name
)
1788 menu
= GET_WIDGET(menu_name
);
1789 tooltip
= gtk_widget_get_tooltip_text(menu
);
1790 g_object_set_data(G_OBJECT(menu
), "tooltip", tooltip
);
1791 gtk_widget_set_tooltip_text(menu
, NULL
);
1796 update_memory_menus()
1801 for (i
= 0; i
< MAX_REGISTERS
; i
++) {
1802 SNPRINTF(mstr
, MAXLINE
, "<span weight=\"bold\">%s_%d:</span> %s",
1803 /* translators: R is the short form of register used inter alia
1805 _("R"), i
, make_number(v
->MPmvals
[i
], v
->base
, TRUE
));
1806 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->memory_store_labels
[i
]), mstr
);
1807 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->memory_recall_labels
[i
]), mstr
);
1808 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->memory_exchange_labels
[i
]), mstr
);
1816 char nkey
[MAXLINE
], *nline
;
1817 char vkey
[MAXLINE
], *vline
;
1819 SNPRINTF(nkey
, MAXLINE
, "constant%1dname", n
);
1820 if ((nline
= get_resource(nkey
)) == NULL
) {
1824 SNPRINTF(vkey
, MAXLINE
, "constant%1dvalue", n
);
1825 if ((vline
= get_resource(vkey
)) == NULL
) {
1829 MPstr_to_num(vline
, DEC
, v
->MPcon_vals
[n
]);
1830 STRNCPY(v
->con_names
[n
], nline
, MAXLINE
- 1);
1835 get_display() /* The Copy function key has been pressed. */
1837 gchar
*string
= NULL
;
1838 GtkTextIter start
, end
;
1840 if (gtk_text_buffer_get_selection_bounds(X
->display_buffer
, &start
, &end
) == TRUE
) {
1841 string
= gtk_text_buffer_get_text(X
->display_buffer
, &start
, &end
, FALSE
);
1843 string
= ui_get_display();
1846 if (v
->shelf
!= NULL
) {
1849 v
->shelf
= g_locale_from_utf8(string
, strlen(string
), NULL
, NULL
, NULL
);
1852 gtk_clipboard_set_text(gtk_clipboard_get(X
->clipboard_atom
), v
->shelf
, -1);
1859 char nkey
[MAXLINE
], *nline
;
1860 char vkey
[MAXLINE
], *vline
;
1862 SNPRINTF(nkey
, MAXLINE
, "function%1dname", n
);
1863 if ((nline
= get_resource(nkey
)) == NULL
) {
1867 SNPRINTF(vkey
, MAXLINE
, "function%1dvalue", n
);
1868 if ((vline
= get_resource(vkey
)) == NULL
) {
1872 STRNCPY(v
->fun_vals
[n
], convert(vline
), MAXLINE
- 1);
1873 STRNCPY(v
->fun_names
[n
], nline
, MAXLINE
- 1);
1878 check_for_localized_numeric_point(int keyval
)
1880 gchar outbuf
[10]; /* Minumum size 6. */
1883 ch
= gdk_keyval_to_unicode(keyval
);
1884 g_return_val_if_fail(g_unichar_validate(ch
), FALSE
);
1886 outbuf
[g_unichar_to_utf8(ch
, outbuf
)] = '\0';
1888 return (strcmp(outbuf
, X
->lnp
) == 0);
1894 help_cb(GtkWidget
*widget
)
1902 hyp_cb(GtkWidget
*widget
)
1904 ui_update_trig_mode();
1910 inv_cb(GtkWidget
*widget
)
1912 ui_update_trig_mode();
1918 display_focus_out_cb(GtkWidget
*widget
)
1920 if (v
->syntax
== EXPRS
) {
1921 exp_replace(ui_get_display());
1929 display_focus_in_cb(GtkWidget
*widget
, GdkEventKey
*event
)
1938 menu_pos_func(GtkMenu
*menu
, gint
*x
, gint
*y
,
1939 gboolean
*push_in
, gpointer user_data
)
1941 GdkPoint
*loc
= (GdkPoint
*) user_data
;
1950 button_cb(GtkWidget
*widget
, GdkEventButton
*event
)
1956 function
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
),
1958 menu
= (GtkWidget
*)g_object_get_data(G_OBJECT(widget
), "calc_menu");
1961 do_button(function
, 0);
1963 /* If gcalctool is being driven by gok, the on-screen keyboard
1964 * assistive technology, it's possible that the event returned by
1965 * gtk_get_current_event() is NULL. If this is the case, we need
1966 * to fudge the popping up on the menu associated with this menu
1970 update_constants_menu();
1971 update_functions_menu();
1972 update_memory_menus();
1974 if (event
== NULL
) {
1975 gdk_window_get_origin(widget
->window
, &loc
.x
, &loc
.y
);
1976 loc
.x
+= widget
->allocation
.x
;
1977 loc
.y
+= widget
->allocation
.y
;
1978 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, menu_pos_func
,
1979 (gpointer
) &loc
, 0, gtk_get_current_event_time());
1980 } else if (event
->button
== 1) {
1981 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
,
1982 event
->button
, event
->time
);
1990 select_display_entry(int offset
)
1994 gtk_text_buffer_get_iter_at_offset(X
->display_buffer
, &iter
, offset
);
1995 gtk_text_buffer_place_cursor(X
->display_buffer
, &iter
);
1996 gtk_widget_grab_focus(X
->display_item
);
2002 kframe_key_press_cb(GtkWidget
*widget
, GdkEventKey
*event
)
2007 if (check_for_localized_numeric_point(event
->keyval
) == TRUE
) {
2009 event
->keyval
= GDK_KP_Decimal
;
2012 state
= event
->state
& (GDK_CONTROL_MASK
| GDK_MOD1_MASK
);
2014 /* Accuracy shortcuts */
2015 if (state
== GDK_CONTROL_MASK
&& v
->modetype
== SCIENTIFIC
) {
2016 switch (event
->keyval
) {
2050 /* Connect home and end keys to move into the display entry */
2051 if (!gtk_widget_is_focus(X
->display_item
)) {
2052 if (event
->keyval
== GDK_Home
) { /* || event->keyval == GDK_Left) { */
2053 select_display_entry(0);
2055 } else if (event
->keyval
== GDK_End
) { /* || event->keyval == GDK_Right) { */
2056 select_display_entry(-1);
2061 for (i
= 0; i
< NBUTTONS
; i
++) {
2062 button
= X
->buttons
[i
];
2064 /* Check any parent widgets are visible */
2065 if (!GTK_WIDGET_VISIBLE(gtk_widget_get_parent(button
)) ||
2066 !GTK_WIDGET_VISIBLE(button
) || !GTK_WIDGET_IS_SENSITIVE(button
)) {
2071 while (button_widgets
[i
].accelerator_keys
[j
] != 0) {
2072 if (button_widgets
[i
].accelerator_keys
[j
] == event
->keyval
&&
2073 (button_widgets
[i
].accelerator_mods
[j
] & ~GDK_SHIFT_MASK
) == state
) {
2074 button_cb(button
, NULL
);
2087 edit_cb(GtkWidget
*widget
)
2089 gboolean can_paste
, can_copy
;
2091 can_copy
= gtk_text_buffer_get_has_selection(X
->display_buffer
);
2092 can_paste
= gtk_clipboard_wait_is_text_available(
2093 gtk_clipboard_get(X
->clipboard_atom
));
2095 gtk_widget_set_sensitive(GET_WIDGET("copy_menu"), can_copy
);
2096 gtk_widget_set_sensitive(GET_WIDGET("paste_menu"), can_paste
);
2102 copy_cb(GtkWidget
*widget
)
2110 get_proc(GtkClipboard
*clipboard
, const gchar
*buffer
, gpointer data
)
2113 gchar
*dstp
, *end_buffer
, *srcp
, *text
, c
;
2115 if (buffer
== NULL
) {
2119 end_buffer
= (gchar
*) (buffer
+ strlen(buffer
));
2120 text
= malloc(strlen(buffer
)+1);
2123 for (srcp
= (gchar
*) buffer
; srcp
< end_buffer
; srcp
++) {
2124 /* If the clipboard buffer contains any occurances of the "thousands
2125 * separator", remove them.
2127 if (*srcp
== v
->tsep
[0]) {
2128 if (strstr(srcp
, v
->tsep
) == srcp
) {
2129 srcp
+= strlen(v
->tsep
) - 1;
2134 /* If an "A", "B", "C", "D" or "F" character is encountered, it
2135 * will be converted to its lowercase equivalent. If an "E" is
2136 * found, and the next character is a "-" or a "+", then it
2137 * remains as an upper case "E" (it's assumed to be a possible
2138 * exponential number), otherwise its converted to a lower case
2139 * "e". See bugs #455889 and #469245 for more details.
2142 /* Replace tabs with spaces */
2147 /* Terminate on newlines */
2163 if (srcp
< (end_buffer
-1)) {
2164 if (*(srcp
+1) != '-' &&
2180 switch (v
->syntax
) {
2182 ret
= lr_parse((char *) text
, v
->MPdisp_val
);
2184 show_display(v
->MPdisp_val
);
2186 ui_set_statusbar(_("Clipboard contained malformed calculation"),
2187 "gtk-dialog-error");
2192 exp_insert((char *) text
, get_cursor()); // FIXME: Move out of gtk.c
2193 refresh_display(-1);
2205 mouse_button_cb(GtkWidget
*widget
, GdkEventButton
*event
)
2207 if (event
->button
== 2) {
2208 gtk_clipboard_request_text(gtk_clipboard_get(X
->primary_atom
),
2218 paste_cb(GtkWidget
*widget
)
2220 gtk_clipboard_request_text(gtk_clipboard_get(X
->clipboard_atom
),
2227 popup_paste_cb(GtkWidget
*menu
)
2235 undo_cb(GtkWidget
*widget
)
2243 redo_cb(GtkWidget
*widget
)
2246 refresh_display(-1);
2252 for_each_menu(GtkWidget
*widget
, gpointer data
)
2254 /* Find the "Paste" entry and activate it (see bug #317786). */
2255 if (strcmp(G_OBJECT_TYPE_NAME(widget
), "GtkImageMenuItem") == 0) {
2256 GtkWidget
*label
= gtk_bin_get_child(GTK_BIN(widget
));
2258 if (strcmp(gtk_label_get_text(GTK_LABEL(label
)), _("Paste")) == 0) {
2259 if (gtk_clipboard_wait_is_text_available(
2260 gtk_clipboard_get(X
->clipboard_atom
))) {
2261 gtk_widget_set_sensitive(GTK_WIDGET(widget
), TRUE
);
2262 g_signal_connect(GTK_OBJECT(widget
), "activate",
2263 G_CALLBACK(popup_paste_cb
), NULL
);
2272 buffer_populate_popup_cb(GtkTextView
*textview
, GtkMenu
*menu
)
2274 gtk_container_foreach(GTK_CONTAINER(menu
), for_each_menu
, NULL
);
2280 insert_ascii_cb(GtkWidget
*widget
)
2282 if (!GTK_WIDGET_VISIBLE(X
->aframe
)) {
2283 ds_position_popup(X
->kframe
, X
->aframe
, DS_POPUP_LEFT
);
2285 gtk_window_set_focus(GTK_WINDOW(X
->kframe
), GTK_WIDGET(X
->aframe_ch
));
2286 gtk_widget_show(X
->aframe
);
2291 shift_cb(GtkWidget
*widget
)
2293 int count
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
),
2295 do_button(KEY_SHIFT
, count
);
2301 show_bitcalculating_cb(GtkWidget
*widget
)
2304 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2305 ui_set_show_bitcalculating(visible
);
2311 show_registers_cb(GtkWidget
*widget
)
2314 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2315 ui_set_registers_visible(visible
);
2320 arithmetic_mode_cb(GtkWidget
*widget
)
2323 mode
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
)) ? EXPRS
: NPA
;
2324 ui_set_syntax_mode(mode
);
2330 mode_radio_cb(GtkWidget
*menu
)
2332 int mode
; /* The new mode. */
2334 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu
))) {
2338 mode
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "calcmode"));
2340 /* If the user has completed a calculation and we are going to a
2341 * new mode that is "compatible" with this one, then just change
2342 * modes. Otherwise display a dialog warning the user that the
2343 * current calculation will be cleared.
2345 * Incompatible modes are:
2347 * Scientific -> Basic
2348 * Scientific -> Advanced
2349 * Scientific -> Financial
2351 * (unless we are in Scientific mode with Decimal numeric base and Fixed).
2353 if (display_is_result() &&
2354 ((v
->modetype
!= SCIENTIFIC
) ||
2355 (v
->dtype
== FIX
&& v
->base
== DEC
))) {
2357 ui_set_mode(v
->modetype
);
2359 if (request_change_mode()) {
2368 accuracy_radio_cb(GtkWidget
*widget
)
2371 count
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
), "accuracy"));
2372 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
))) {
2380 accuracy_other_cb(GtkWidget
*widget
)
2382 if (!GTK_WIDGET_VISIBLE(X
->spframe
)) {
2383 ds_position_popup(X
->kframe
, X
->spframe
, DS_POPUP_LEFT
);
2385 gtk_window_set_focus(GTK_WINDOW(X
->spframe
), GTK_WIDGET(X
->precision_spin
));
2386 gtk_widget_show(X
->spframe
);
2392 show_trailing_zeroes_cb(GtkWidget
*widget
)
2395 visible
= gtk_check_menu_item_get_active(
2396 GTK_CHECK_MENU_ITEM(widget
));
2397 ui_set_show_trailing_zeroes(visible
);
2403 quit_cb(GtkWidget
*widget
)
2405 save_win_position();
2411 spframe_response_cb(GtkWidget
*dialog
, gint response_id
)
2414 if (response_id
== GTK_RESPONSE_OK
) {
2415 val
= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(X
->precision_spin
));
2416 ui_set_accuracy(val
);
2419 gtk_widget_hide(dialog
);
2424 spframe_delete_cb(GtkWidget
*dialog
)
2426 spframe_response_cb(dialog
, GTK_RESPONSE_CANCEL
);
2433 spframe_activate_cb(GtkWidget
*spin
)
2435 spframe_response_cb(X
->spframe
, GTK_RESPONSE_OK
);
2441 trig_cb(GtkWidget
*widget
)
2443 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
)))
2444 do_trigtype((enum trig_type
) g_object_get_data(G_OBJECT(widget
),
2451 show_thousands_separator_cb(GtkWidget
*widget
)
2455 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2456 ui_set_show_thousands_seperator(visible
);
2462 edit_constants_cb(GtkMenuItem
*item
)
2464 gtk_widget_show(X
->con_dialog
);
2470 edit_functions_cb(GtkMenuItem
*item
)
2472 gtk_widget_show(X
->fun_dialog
);
2479 int intval
, screen_height
, screen_width
;
2482 screen_width
= gdk_screen_get_width(gdk_screen_get_default());
2483 screen_height
= gdk_screen_get_height(gdk_screen_get_default());
2485 if (get_int_resource(R_XPOS
, &intval
)) {
2487 if (x
< 0 || x
> screen_width
) {
2492 if (get_int_resource(R_YPOS
, &intval
)) {
2494 if (y
< 0 || y
> screen_height
) {
2499 gtk_window_move(GTK_WINDOW(X
->kframe
), x
, y
);
2509 PangoFontDescription
*font_desc
;
2510 GtkSizeGroup
*size_group
;
2511 GtkAccelGroup
*accel_group
;
2512 GtkWidget
*treeview
;
2514 X
->ui
= glade_xml_new(UI_FILE
, NULL
, NULL
);
2515 if (X
->ui
== NULL
) {
2518 dialog
= gtk_message_dialog_new(NULL
, 0,
2521 N_("Error loading user interface"));
2522 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog
),
2523 N_("The user interace file %s is missing or unable to be loaded. Please check your installation."), UI_FILE
);
2524 gtk_dialog_add_buttons(GTK_DIALOG(dialog
), GTK_STOCK_QUIT
, GTK_RESPONSE_ACCEPT
, NULL
);
2526 gtk_dialog_run(GTK_DIALOG(dialog
));
2530 /* When connecting up signals, would ideally use autoconnect but not
2531 * sure how to get the build process working.
2532 * See http://library.gnome.org/devel/libglade/unstable and
2533 * http://www.jamesh.id.au/software/libglade/
2534 * for some information on how to get this to work
2535 * glade_xml_signal_autoconnect(X->ui);
2537 CONNECT_SIGNAL(kframe_key_press_cb
);
2538 CONNECT_SIGNAL(button_cb
);
2539 CONNECT_SIGNAL(menu_item_select_cb
);
2540 CONNECT_SIGNAL(menu_item_deselect_cb
);
2541 CONNECT_SIGNAL(mode_radio_cb
);
2542 CONNECT_SIGNAL(inv_cb
);
2543 CONNECT_SIGNAL(hyp_cb
);
2544 CONNECT_SIGNAL(trig_cb
);
2545 CONNECT_SIGNAL(base_cb
);
2546 CONNECT_SIGNAL(disp_cb
);
2547 CONNECT_SIGNAL(quit_cb
);
2548 CONNECT_SIGNAL(edit_cb
);
2549 CONNECT_SIGNAL(copy_cb
);
2550 CONNECT_SIGNAL(paste_cb
);
2551 CONNECT_SIGNAL(insert_ascii_cb
);
2552 CONNECT_SIGNAL(undo_cb
);
2553 CONNECT_SIGNAL(redo_cb
);
2554 CONNECT_SIGNAL(help_cb
);
2555 CONNECT_SIGNAL(about_cb
);
2556 CONNECT_SIGNAL(show_trailing_zeroes_cb
);
2557 CONNECT_SIGNAL(show_thousands_separator_cb
);
2558 CONNECT_SIGNAL(show_bitcalculating_cb
);
2559 CONNECT_SIGNAL(show_registers_cb
);
2560 CONNECT_SIGNAL(accuracy_radio_cb
);
2561 CONNECT_SIGNAL(accuracy_other_cb
);
2562 CONNECT_SIGNAL(constant_menu_cb
);
2563 CONNECT_SIGNAL(function_menu_cb
);
2564 CONNECT_SIGNAL(store_menu_cb
);
2565 CONNECT_SIGNAL(recall_menu_cb
);
2566 CONNECT_SIGNAL(exchange_menu_cb
);
2567 CONNECT_SIGNAL(arithmetic_mode_cb
);
2568 CONNECT_SIGNAL(mouse_button_cb
);
2569 CONNECT_SIGNAL(display_focus_in_cb
);
2570 CONNECT_SIGNAL(display_focus_out_cb
);
2571 /* Detect when populating the right-click menu to enable pasting */
2572 CONNECT_SIGNAL(buffer_populate_popup_cb
);
2573 CONNECT_SIGNAL(shift_cb
);
2574 CONNECT_SIGNAL(bit_toggle_cb
);
2575 CONNECT_SIGNAL(aframe_delete_cb
);
2576 CONNECT_SIGNAL(aframe_activate_cb
);
2577 CONNECT_SIGNAL(aframe_response_cb
);
2578 CONNECT_SIGNAL(spframe_delete_cb
);
2579 CONNECT_SIGNAL(spframe_activate_cb
);
2580 CONNECT_SIGNAL(spframe_response_cb
);
2581 CONNECT_SIGNAL(rframe_delete_cb
);
2582 CONNECT_SIGNAL(rframe_response_cb
);
2583 CONNECT_SIGNAL(edit_constants_cb
);
2584 CONNECT_SIGNAL(edit_functions_cb
);
2585 CONNECT_SIGNAL(edit_constants_delete_cb
);
2586 CONNECT_SIGNAL(edit_constants_response_cb
);
2587 CONNECT_SIGNAL(edit_constants_delete_cb
);
2588 CONNECT_SIGNAL(edit_functions_response_cb
);
2589 CONNECT_SIGNAL(edit_functions_delete_cb
);
2591 X
->clipboard_atom
= gdk_atom_intern("CLIPBOARD", FALSE
);
2592 X
->primary_atom
= gdk_atom_intern("PRIMARY", FALSE
);
2593 X
->kframe
= GET_WIDGET("calc_window");
2594 X
->aframe
= GET_WIDGET("ascii_dialog");
2595 X
->aframe_ch
= GET_WIDGET("ascii_entry");
2596 X
->spframe
= GET_WIDGET("precision_dialog");
2597 X
->precision_spin
= GET_WIDGET("spframe_spin");
2598 X
->rframe
= GET_WIDGET("register_dialog");
2599 X
->con_dialog
= GET_WIDGET("edit_constants_dialog");
2600 X
->fun_dialog
= GET_WIDGET("edit_functions_dialog");
2601 X
->menubar
= GET_WIDGET("menubar");
2602 X
->scrolledwindow
= GET_WIDGET("display_scroll"),
2603 X
->display_item
= GET_WIDGET("displayitem"),
2604 X
->bas_panel
= GET_WIDGET("basic_panel");
2605 X
->sci_panel
= GET_WIDGET("scientific_panel");
2606 X
->adv_panel
= GET_WIDGET("advanced_panel");
2607 X
->fin_panel
= GET_WIDGET("financial_panel");
2608 X
->bit_panel
= GET_WIDGET("bit_panel");
2609 X
->clear_buttons
[0] = GET_WIDGET("calc_clear_simple_button");
2610 X
->clear_buttons
[1] = GET_WIDGET("calc_clear_advanced_button");
2611 X
->mode_panel
= GET_WIDGET("mode_panel");
2612 X
->trig
[0] = GET_WIDGET("degrees_radio");
2613 X
->trig
[1] = GET_WIDGET("gradians_radio");
2614 X
->trig
[2] = GET_WIDGET("radians_radio");
2615 X
->base
[0] = GET_WIDGET("binary_radio");
2616 X
->base
[1] = GET_WIDGET("octal_radio");
2617 X
->base
[2] = GET_WIDGET("decimal_radio");
2618 X
->base
[3] = GET_WIDGET("hexadecimal_radio");
2619 X
->disp
[0] = GET_WIDGET("engineering_radio");
2620 X
->disp
[1] = GET_WIDGET("fixed_point_radio");
2621 X
->disp
[2] = GET_WIDGET("scientific_radio");
2622 X
->inverse_toggle
= GET_WIDGET("inverse_check");
2623 X
->hyperbolic_toggle
= GET_WIDGET("hyperbolic_check");
2624 X
->statusbar
= GET_WIDGET("statusbar");
2625 for (i
= 0; i
< 16; i
++) {
2626 SNPRINTF(name
, MAXLINE
, "calc_%x_button", i
);
2627 X
->digit_buttons
[i
] = GET_WIDGET(name
);
2629 for (i
= 0; i
< MAX_REGISTERS
; i
++) {
2630 SNPRINTF(name
, MAXLINE
, "register_entry_%d", i
);
2631 X
->regs
[i
] = GET_WIDGET(name
);
2634 /* Load buttons and set them all to be the same size */
2635 size_group
= gtk_size_group_new(GTK_SIZE_GROUP_BOTH
);
2636 for (i
= 0; i
< NBUTTONS
; i
++) {
2637 SNPRINTF(name
, MAXLINE
, "calc_%s_button",
2638 button_widgets
[i
].widget_name
);
2639 X
->buttons
[i
] = GET_WIDGET(name
);
2640 assert(X
->buttons
[i
] != NULL
);
2642 gtk_size_group_add_widget(size_group
, X
->buttons
[i
]);
2644 g_object_set_data(G_OBJECT(X
->buttons
[i
]), "calc_function",
2645 GINT_TO_POINTER(button_widgets
[i
].key
));
2648 /* Make popup buttons */
2649 g_object_set_data(G_OBJECT(GET_WIDGET("calc_accuracy_button")),
2650 "calc_menu", GET_WIDGET("accuracy_popup"));
2651 g_object_set_data(G_OBJECT(GET_WIDGET("calc_shift_left_button")),
2652 "calc_menu", GET_WIDGET("left_shift_popup"));
2653 g_object_set_data(G_OBJECT(GET_WIDGET("calc_shift_right_button")),
2654 "calc_menu", GET_WIDGET("right_shift_popup"));
2656 g_object_set_data(G_OBJECT(GET_WIDGET("calc_constants_button")),
2657 "calc_menu", GET_WIDGET("constants_popup"));
2658 for (i
= 0; i
< MAX_CONSTANTS
; i
++) {
2659 SNPRINTF(name
, MAXLINE
, "constant_menu_item%d", i
);
2660 widget
= GET_WIDGET(name
);
2661 g_object_set_data(G_OBJECT(widget
), "constant_id", GINT_TO_POINTER(i
));
2662 X
->constant_menu_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2665 g_object_set_data(G_OBJECT(GET_WIDGET("calc_functions_button")),
2666 "calc_menu", GET_WIDGET("functions_popup"));
2667 for (i
= 0; i
< MAX_FUNCTIONS
; i
++) {
2668 SNPRINTF(name
, MAXLINE
, "function_menu_item%d", i
);
2669 widget
= GET_WIDGET(name
);
2670 g_object_set_data(G_OBJECT(widget
), "function_id", GINT_TO_POINTER(i
));
2671 X
->function_menu_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2674 g_object_set_data(G_OBJECT(GET_WIDGET("calc_store_button")),
2675 "calc_menu", GET_WIDGET("memory_store_popup"));
2676 g_object_set_data(G_OBJECT(GET_WIDGET("calc_recall_button")),
2677 "calc_menu", GET_WIDGET("memory_recall_popup"));
2678 g_object_set_data(G_OBJECT(GET_WIDGET("calc_exchange_button")),
2679 "calc_menu", GET_WIDGET("memory_exchange_popup"));
2680 for (i
= 0; i
< MAX_REGISTERS
; i
++) {
2681 SNPRINTF(name
, MAXLINE
, "store_menu_item%d", i
);
2682 widget
= GET_WIDGET(name
);
2683 g_object_set_data(G_OBJECT(widget
), "register_id", GINT_TO_POINTER(i
));
2684 X
->memory_store_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2686 SNPRINTF(name
, MAXLINE
, "recall_menu_item%d", i
);
2687 widget
= GET_WIDGET(name
);
2688 g_object_set_data(G_OBJECT(widget
), "register_id", GINT_TO_POINTER(i
));
2689 X
->memory_recall_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2691 SNPRINTF(name
, MAXLINE
, "exchange_menu_item%d", i
);
2692 widget
= GET_WIDGET(name
);
2693 g_object_set_data(G_OBJECT(widget
), "register_id", GINT_TO_POINTER(i
));
2694 X
->memory_exchange_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2697 /* Load bit panel */
2698 for (i
= 0; i
< MAXBITS
; i
++)
2700 SNPRINTF(name
, MAXLINE
, "bit_label_%d", i
);
2701 X
->bits
[i
] = GET_WIDGET(name
);
2702 SNPRINTF(name
, MAXLINE
, "bit_eventbox_%d", i
);
2703 g_object_set_data(G_OBJECT(GET_WIDGET(name
)),
2704 "bit_index", GINT_TO_POINTER(i
));
2707 /* Make menu tooltips displayed in the status bar */
2708 set_menubar_tooltip("quit_menu");
2709 set_menubar_tooltip("copy_menu");
2710 set_menubar_tooltip("paste_menu");
2711 set_menubar_tooltip("insert_ascii_menu");
2712 set_menubar_tooltip("undo_menu");
2713 set_menubar_tooltip("redo_menu");
2714 set_menubar_tooltip("view_basic_menu");
2715 set_menubar_tooltip("view_advanced_menu");
2716 set_menubar_tooltip("view_financial_menu");
2717 set_menubar_tooltip("view_scientific_menu");
2718 set_menubar_tooltip("show_trailing_zeroes_menu");
2719 set_menubar_tooltip("show_thousands_separator_menu");
2720 set_menubar_tooltip("show_bitcalculating_menu");
2721 set_menubar_tooltip("show_registers_menu");
2722 set_menubar_tooltip("ltr_precedence_menu");
2723 set_menubar_tooltip("arithmetic_precedence_menu");
2724 set_menubar_tooltip("help_menu");
2725 set_menubar_tooltip("about_menu");
2728 widget
= GET_WIDGET("kvbox");
2729 gtk_widget_set_direction(widget
, GTK_TEXT_DIR_LTR
);
2730 gtk_widget_set_direction(X
->fin_panel
, GTK_TEXT_DIR_LTR
);
2732 /* Make dialogs transient of the main window */
2733 gtk_window_set_transient_for(GTK_WINDOW(X
->aframe
), GTK_WINDOW(X
->kframe
));
2734 gtk_window_set_transient_for(GTK_WINDOW(X
->spframe
), GTK_WINDOW(X
->kframe
));
2735 gtk_window_set_transient_for(GTK_WINDOW(X
->rframe
), GTK_WINDOW(X
->kframe
));
2736 gtk_window_set_transient_for(GTK_WINDOW(X
->con_dialog
),
2737 GTK_WINDOW(X
->kframe
));
2739 /* Can't set max length for spin buttons in Glade 2 */
2740 gtk_entry_set_max_length(GTK_ENTRY(X
->precision_spin
), 2);
2742 gtk_dialog_set_default_response(GTK_DIALOG(X
->con_dialog
),
2743 GTK_RESPONSE_ACCEPT
);
2745 /* Make constant tree model */
2746 X
->constants_model
= create_constants_model();
2747 treeview
= GET_WIDGET("edit_constants_treeview");
2748 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview
), X
->constants_model
);
2749 gtk_tree_selection_set_mode(
2750 gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
)),
2751 GTK_SELECTION_SINGLE
);
2752 add_cf_column(GTK_TREE_VIEW(treeview
), _("No."),
2753 COLUMN_NUMBER
, FALSE
);
2754 add_cf_column(GTK_TREE_VIEW(treeview
), _("Value"),
2755 COLUMN_VALUE
, TRUE
);
2756 add_cf_column(GTK_TREE_VIEW(treeview
), _("Description"),
2757 COLUMN_DESCRIPTION
, TRUE
);
2759 /* Make function tree model */
2760 X
->functions_model
= create_functions_model();
2761 treeview
= GET_WIDGET("edit_functions_treeview");
2762 gtk_dialog_set_default_response(GTK_DIALOG(X
->fun_dialog
),
2763 GTK_RESPONSE_ACCEPT
);
2764 gtk_window_set_transient_for(GTK_WINDOW(X
->fun_dialog
),
2765 GTK_WINDOW(X
->kframe
));
2766 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview
), X
->functions_model
);
2767 gtk_tree_selection_set_mode(
2768 gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
)),
2769 GTK_SELECTION_SINGLE
);
2770 add_cf_column(GTK_TREE_VIEW(treeview
), _("No."),
2771 COLUMN_NUMBER
, FALSE
);
2772 add_cf_column(GTK_TREE_VIEW(treeview
), _("Value"),
2773 COLUMN_VALUE
, TRUE
);
2774 add_cf_column(GTK_TREE_VIEW(treeview
), _("Description"),
2775 COLUMN_DESCRIPTION
, TRUE
);
2778 X
->display_buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(X
->display_item
));
2779 gtk_widget_ensure_style(X
->display_item
);
2780 font_desc
= pango_font_description_copy(X
->display_item
->style
->font_desc
);
2781 pango_font_description_set_size(font_desc
, 16 * PANGO_SCALE
);
2782 gtk_widget_modify_font(X
->display_item
, font_desc
);
2783 pango_font_description_free(font_desc
);
2784 gtk_widget_set_name(X
->display_item
, "displayitem");
2785 atk_object_set_role(gtk_widget_get_accessible(X
->display_item
),
2788 gtk_widget_realize(X
->kframe
);
2791 for (i
= 0; i
< 3; i
++)
2792 g_object_set_data(G_OBJECT(X
->trig
[i
]),
2793 "trig_mode", GINT_TO_POINTER(i
));
2794 for (i
= 0; i
< 4; i
++)
2795 g_object_set_data(G_OBJECT(X
->base
[i
]),
2796 "base_mode", GINT_TO_POINTER(i
));
2797 for (i
= 0; i
< 3; i
++)
2798 g_object_set_data(G_OBJECT(X
->disp
[i
]),
2799 "numeric_mode", GINT_TO_POINTER(i
));
2801 /* Put status image into statusbar (glade doesn't support child widgets
2803 X
->status_image
= gtk_image_new_from_stock("", GTK_ICON_SIZE_BUTTON
);
2804 gtk_widget_show(X
->status_image
);
2805 gtk_box_pack_start(GTK_BOX(X
->statusbar
), X
->status_image
, FALSE
, TRUE
, 0);
2807 /* Set modes for menu items */
2808 for (i
= 1; i
< 16; i
++) {
2809 SNPRINTF(name
, MAXLINE
, "shift_left%d_menu", i
);
2810 g_object_set_data(G_OBJECT(GET_WIDGET(name
)),
2811 "shiftcount", GINT_TO_POINTER(i
));
2812 SNPRINTF(name
, MAXLINE
, "shift_right%d_menu", i
);
2813 g_object_set_data(G_OBJECT(GET_WIDGET(name
)),
2814 "shiftcount", GINT_TO_POINTER(-i
));
2816 g_object_set_data(G_OBJECT(GET_WIDGET("view_basic_menu")),
2817 "calcmode", GINT_TO_POINTER(BASIC
));
2818 g_object_set_data(G_OBJECT(GET_WIDGET("view_advanced_menu")),
2819 "calcmode", GINT_TO_POINTER(ADVANCED
));
2820 g_object_set_data(G_OBJECT(GET_WIDGET("view_financial_menu")),
2821 "calcmode", GINT_TO_POINTER(FINANCIAL
));
2822 g_object_set_data(G_OBJECT(GET_WIDGET("view_scientific_menu")),
2823 "calcmode", GINT_TO_POINTER(SCIENTIFIC
));
2825 /* Make shortcuts for accuracy menus */
2826 accel_group
= gtk_accel_group_new();
2827 gtk_window_add_accel_group(GTK_WINDOW(X
->kframe
), accel_group
);
2828 for (i
= 0; i
< 10; i
++) {
2829 SNPRINTF(name
, MAXLINE
, "acc_item%d", i
);
2830 widget
= GET_WIDGET(name
);
2831 g_object_set_data(G_OBJECT(widget
), "accuracy", GINT_TO_POINTER(i
));
2837 read_cfdefs() /* Read constant/function definitions. */
2841 for (n
= 0; n
< MAX_CONSTANTS
; n
++) {
2844 for (n
= 0; n
< MAX_FUNCTIONS
; n
++) {
2845 STRCPY(v
->fun_vals
[n
], ""); /* Initially empty function strings. */
2852 ui_init(int *argc
, char ***argv
)
2854 X
= (XVars
) LINT_CAST(calloc(1, sizeof(struct Xobject
)));
2856 gtk_init(argc
, argv
);
2858 X
->lnp
= ui_get_localized_numeric_point();
2860 gtk_rc_get_default_files();
2862 v
->home
= (char *) g_get_home_dir();
2863 gtk_rc_parse(g_build_path(v
->home
, RCNAME
, NULL
));
2865 gtk_window_set_default_icon_name("gnome-calculator");
2878 /* Create main gcalctool window. */
2881 /* Load configuration */
2882 resource
= get_resource(R_BITCALC
);
2883 show_bit
= resource
!= NULL
&& strcmp(resource
, Rcstr
[0]) != 0;
2885 ui_set_show_thousands_seperator(v
->show_tsep
);
2886 ui_set_show_trailing_zeroes(v
->show_zeroes
);
2887 ui_set_show_bitcalculating(show_bit
);
2889 ui_set_syntax_mode(v
->syntax
);
2890 ui_set_mode(v
->modetype
);
2891 ui_set_numeric_mode(FIX
);
2892 ui_set_base(v
->base
);
2893 ui_set_accuracy(v
->accuracy
);
2894 ui_set_undo_enabled(FALSE
, FALSE
);
2895 ui_update_trig_mode();
2897 /* Show the memory register window? */
2898 ui_make_registers();
2899 if (get_boolean_resource(R_REGS
, &boolval
))
2900 ui_set_registers_visible(boolval
);
2902 /* Focus on the clear button */
2903 if (v
->modetype
== BASIC
) {
2904 gtk_window_set_focus(GTK_WINDOW(X
->kframe
),
2905 GTK_WIDGET(X
->clear_buttons
[0]));
2907 gtk_window_set_focus(GTK_WINDOW(X
->kframe
),
2908 GTK_WIDGET(X
->clear_buttons
[1]));
2915 X
->warn_change_mode
= TRUE
; // FIXME: Load from GConf
2917 ui_set_base(v
->base
);
2918 ui_set_trigonometric_mode(v
->ttype
);
2919 ui_set_numeric_mode(v
->dtype
);
2921 gtk_widget_show(X
->kframe
);
2923 /* Init expression mode.
2924 * This must be executed after do_base is called at init.