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 /* 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
[] = {
79 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
80 { GDK_0
, GDK_0
, GDK_KP_0
, GDK_KP_Insert
, 0 }},
83 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
84 { GDK_1
, GDK_1
, GDK_KP_1
, GDK_KP_End
, GDK_R13
, 0 }},
87 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
88 { GDK_2
, GDK_2
, GDK_KP_2
, GDK_KP_Down
, 0 }},
91 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
92 { GDK_3
, GDK_3
, GDK_KP_3
, GDK_KP_Page_Down
, GDK_R15
, 0 }},
95 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
96 { GDK_4
, GDK_4
, GDK_KP_4
, GDK_KP_Left
, 0 }},
99 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
100 { GDK_5
, GDK_5
, GDK_KP_5
, GDK_KP_Begin
, GDK_R11
, 0 }},
103 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
104 { GDK_6
, GDK_6
, GDK_KP_6
, GDK_KP_Right
, 0 }},
107 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
108 { GDK_7
, GDK_7
, GDK_KP_7
, GDK_KP_Home
, GDK_R7
, 0 }},
111 { 0, GDK_SHIFT_MASK
, 0, 0, 0 },
112 { GDK_8
, GDK_8
, GDK_KP_8
, GDK_KP_Up
, 0 }},
115 { 0, GDK_SHIFT_MASK
, 0, 0, 0, 0 },
116 { GDK_9
, GDK_9
, GDK_KP_9
, GDK_KP_Page_Up
, GDK_R9
, 0 }},
142 {KEY_CLEAR
, "clear_simple",
146 {KEY_CLEAR
, "clear_advanced",
150 {KEY_SHIFT
, "shift_left",
151 { GDK_SHIFT_MASK
, 0 },
154 {KEY_SHIFT
, "shift_right",
155 { GDK_SHIFT_MASK
, 0 },
158 {KEY_SET_ACCURACY
, "accuracy",
159 { GDK_SHIFT_MASK
, 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 },
171 { GDK_SHIFT_MASK
, 0 },
174 {KEY_RECALL
, "recall",
175 { GDK_SHIFT_MASK
, 0 },
178 {KEY_EXCHANGE
, "exchange",
179 { GDK_SHIFT_MASK
, 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",
192 { GDK_BackSpace
, 0 }},
194 {KEY_BACKSPACE
, "backspace_advanced",
196 { GDK_BackSpace
, 0 }},
198 {KEY_NUMERIC_POINT
, "numeric_point",
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 }},
215 { GDK_SHIFT_MASK
, 0, 0, 0 },
216 { GDK_plus
, GDK_plus
, GDK_KP_Add
, 0 }},
218 {KEY_SUBTRACT
, "subtract",
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 },
234 {KEY_CHANGE_SIGN
, "change_sign_advanced",
235 { GDK_SHIFT_MASK
, 0 },
238 {KEY_INTEGER
, "integer_portion",
242 {KEY_FRACTION
, "fractional_portion",
243 { GDK_SHIFT_MASK
, 0 },
246 {KEY_PERCENTAGE
, "percentage",
247 { GDK_SHIFT_MASK
, 0 },
250 {KEY_SQUARE
, "square",
251 { GDK_SHIFT_MASK
, 0 },
254 {KEY_SQUARE_ROOT
, "sqrt",
258 {KEY_RECIPROCAL
, "reciprocal",
262 {KEY_ABSOLUTE_VALUE
, "abs",
266 {KEY_MASK_16
, "mask_16",
268 { GDK_bracketright
, 0 }},
270 {KEY_MASK_32
, "mask_32",
272 { GDK_bracketleft
, 0 }},
274 {KEY_MODULUS_DIVIDE
, "modulus_divide",
275 { GDK_SHIFT_MASK
, 0 },
278 {KEY_EXPONENTIAL
, "exponential",
279 { GDK_SHIFT_MASK
, 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 },
298 {KEY_LOGARITHM
, "logarithm",
299 { GDK_SHIFT_MASK
, 0 },
302 {KEY_FACTORIAL
, "factorial",
303 { GDK_SHIFT_MASK
, 0 },
306 {KEY_RANDOM
, "random",
307 { GDK_SHIFT_MASK
, 0 },
308 { GDK_question
, 0 }},
311 { GDK_SHIFT_MASK
, 0 },
315 { GDK_SHIFT_MASK
, 0 },
319 { GDK_SHIFT_MASK
, 0 },
323 { GDK_SHIFT_MASK
, 0 },
324 { GDK_asciitilde
, 0 }},
327 { GDK_SHIFT_MASK
, 0 },
331 { GDK_SHIFT_MASK
, 0 },
332 { GDK_ampersand
, 0 }},
342 {KEY_FINC_CTRM
, "finc_compounding_term",
346 {KEY_FINC_DDB
, "finc_double_declining_depreciation",
347 { GDK_SHIFT_MASK
, 0 },
350 {KEY_FINC_FV
, "finc_future_value",
354 {KEY_FINC_PMT
, "finc_periodic_payment",
355 { GDK_SHIFT_MASK
, 0 },
358 {KEY_FINC_PV
, "finc_present_value",
362 {KEY_FINC_RATE
, "finc_periodic_interest_rate",
363 { GDK_SHIFT_MASK
, 0 },
366 {KEY_FINC_SLN
, "finc_straight_line_depreciation",
370 {KEY_FINC_SYD
, "finc_sum_of_the_years_digits_depreciation",
374 {KEY_FINC_TERM
, "finc_term",
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, \
394 struct Xobject
{ /* Gtk+/Xlib graphics object. */
395 GdkAtom clipboard_atom
;
396 GdkAtom primary_atom
;
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
;
470 ui_set_syntax_mode(enum syntax mode
)
472 struct exprm_state
*e
;
475 /* TODO: Always do clear things when mode is changed. */
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();
488 MPstr_to_num("0", DEC
, e
->ans
);
490 show_display(e
->ans
);
492 _("Activated expression mode with operator precedence"), "");
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
);
510 widget
= GET_WIDGET("ltr_precedence_menu");
511 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget
), TRUE
);
517 ui_set_accuracy(int accuracy
)
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.",
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.",
539 tooltip
= g_strdup_printf ("%s %s [A]", desc
, current
);
540 gtk_widget_set_tooltip_text (GET_WIDGET("calc_accuracy_button"), 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
),
554 set_int_resource(R_ACCURACY
, accuracy
);
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
};
578 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X
->hyperbolic_toggle
))) {
581 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X
->inverse_toggle
))) {
585 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("sine_label")),
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
]));
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();
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();
619 ui_set_trigonometric_mode(enum trig_type mode
)
621 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->trig
[mode
]), 1);
626 ui_set_numeric_mode(enum base_type mode
)
628 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->disp
[mode
]), 1);
633 ui_set_show_thousands_seperator(gboolean visible
)
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();
649 ui_set_show_bitcalculating(gboolean visible
)
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
);
663 ui_set_show_trailing_zeroes(gboolean visible
)
667 v
->show_zeroes
= visible
;
668 set_boolean_resource(R_ZEROES
, visible
);
670 syntaxdep_show_display();
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
);
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
);
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
);
703 while (*scanner
!= ':') {
709 if (strcmp(display
, hostname
) &&
710 strcmp(display
, "localhost") &&
711 strcmp(display
, "unix") &&
712 strcmp(display
, "")) {
713 SPRINTF(client_hostname
, " [%s] ", hostname
);
715 STRCPY(client_hostname
, "");
720 if (client_hostname
[0] == '\0')
723 return(strdup(client_hostname
));
728 ui_set_mode(enum mode_type mode
)
732 char *hostname
, title
[MAXLINE
];
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");
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");
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");
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
);
774 gtk_widget_hide(X
->bit_panel
);
776 gtk_widget_show(X
->sci_panel
);
777 menu
= GET_WIDGET("view_scientific_menu");
786 r
= g_new0(GtkRequisition
, 1);
787 gtk_widget_size_request(X
->menubar
, r
);
790 gtk_widget_size_request(X
->display_item
, r
);
791 w
= MAX(w
, r
->width
);
794 if (GTK_WIDGET_VISIBLE(X
->fin_panel
)) {
795 gtk_widget_size_request(X
->fin_panel
, r
);
796 w
= MAX(w
, r
->width
);
800 if (GTK_WIDGET_VISIBLE(X
->mode_panel
)) {
801 gtk_widget_size_request(X
->mode_panel
, r
);
802 w
= MAX(w
, r
->width
);
806 if (GTK_WIDGET_VISIBLE(X
->sci_panel
)) {
807 gtk_widget_size_request(X
->sci_panel
, r
);
808 w
= MAX(w
, r
->width
);
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
);
818 if((hostname
= make_hostname())) {
819 SNPRINTF(title
, MAXLINE
, hostname_titles
[mode
], hostname
);
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
);
831 ui_set_statusbar(gchar
*text
, const gchar
*imagename
)
833 GtkImage
*image
= GTK_IMAGE(X
->status_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
);
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
];
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
);
860 mpcmim(MP_value
, MP0
);
863 for (i
= 0; i
< maxbits
; i
++) {
864 double lsb
; /* Least significant bit. */
865 calc_and(MP3
, MP0
, MP1
);
869 str
[maxbits
- i
-1] = (neg
) ? '1' : '0';
871 str
[maxbits
- i
-1] = (neg
) ? '0' : '1';
874 mpdiv(MP0
, MP2
, MP3
);
885 int bit_str_len
, i
, MP1
[MP_SIZE
], MP2
[MP_SIZE
];
887 char str
[64], label
[3];
888 int ret
= usable_num(MP
);
892 MPstr_to_num(v
->display
, v
->base
, MP1
);
894 if (mpeq(MP1
, MP2
)) {
895 char *bit_str
, label
[3], tmp
[MAXLINE
];
896 int toclear
= (v
->current
== KEY_CLEAR_ENTRY
)
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
);
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
);
913 gtk_widget_set_sensitive(X
->bit_panel
, FALSE
);
917 if (ret
|| !is_integer(MP
)) {
918 gtk_widget_set_sensitive(X
->bit_panel
, FALSE
);
921 bin_str(MP
, str
, 64);
922 gtk_widget_set_sensitive(X
->bit_panel
, TRUE
);
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
);
940 if (GTK_WIDGET_VISIBLE(
941 GTK_SCROLLED_WINDOW(X
->scrolledwindow
)->hscrollbar
)) {
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
);
954 ui_set_display(char *str
)
956 char localized
[MAX_LOCALIZED
];
958 if (str
== NULL
|| str
[0] == '\0') {
961 if (v
->noparens
== 0) {
962 localize_number(localized
, str
);
966 gtk_text_buffer_set_text(X
->display_buffer
, str
, -1);
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:
979 * When the error condition is cleared, resensitise everything, setting
980 * the numeric base buttons correctly.
984 ui_set_error_state(gboolean 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
);
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
);
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
));
1039 ui_set_base(enum base_type base
)
1041 int i
, baseval
= basevals
[(int) 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);
1053 ui_set_registers_visible(gboolean visible
)
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
);
1064 if (gdk_window_is_visible(X
->rframe
->window
)) {
1065 gdk_window_raise(X
->rframe
->window
);
1068 ds_position_popup(X
->kframe
, X
->rframe
, DS_POPUP_ABOVE
);
1069 gtk_widget_show(X
->rframe
);
1071 gtk_widget_hide(X
->rframe
);
1074 set_boolean_resource(R_REGS
, visible
);
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
,
1094 g_object_get(G_OBJECT(X
->display_buffer
), "cursor-position", &pos
, NULL
);
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>",
1109 const gchar
*documenters
[] = {
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",
1134 gtk_show_about_dialog(GTK_WINDOW(X
->kframe
),
1135 "name",_("Gcalctool"),
1137 "copyright", _("\xc2\xa9 1986-2007 The Gcalctool authors"),
1138 "license", license_trans
,
1139 "comments", _("Calculator with financial and scientific modes."),
1141 "documenters", documenters
,
1142 "translator_credits", translator_credits
,
1143 "logo-icon-name", "gnome-calculator",
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
);
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
)) {
1164 gtk_tree_model_get(model
, &iter
, column
, &old_text
, -1);
1166 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, column
,
1167 g_strdup(new_text
), -1);
1170 case COLUMN_DESCRIPTION
:
1171 gtk_tree_model_get(model
, &iter
, column
, &old_text
, -1);
1173 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, column
,
1174 g_strdup(new_text
), -1);
1178 gtk_tree_path_free(path
);
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();
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
));
1196 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview
),
1199 "editable", COLUMN_EDITABLE
,
1202 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview
),
1212 aframe_response_cb(GtkWidget
*dialog
, gint response_id
)
1217 if (response_id
== GTK_RESPONSE_OK
) {
1218 ch
= (char *) gtk_entry_get_text(GTK_ENTRY(X
->aframe_ch
));
1220 mpcim(&val
, v
->MPdisp_val
);
1221 show_display(v
->MPdisp_val
);
1224 gtk_widget_hide(dialog
);
1229 aframe_delete_cb(GtkWidget
*dialog
)
1231 aframe_response_cb(dialog
, GTK_RESPONSE_CANCEL
);
1238 aframe_activate_cb(GtkWidget
*entry
)
1240 aframe_response_cb(X
->aframe
, GTK_RESPONSE_OK
);
1246 rframe_response_cb(GtkWidget
*dialog
, int response_id
)
1248 ui_set_registers_visible(FALSE
);
1253 rframe_delete_cb(GtkWidget
*dialog
)
1255 rframe_response_cb(dialog
, GTK_RESPONSE_OK
);
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"));
1271 base_cb(GtkWidget
*widget
)
1273 enum base_type base
;
1275 base
= (enum base_type
) g_object_get_data(G_OBJECT(widget
),
1277 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
))) {
1283 static void do_button(int function
, int arg
)
1285 struct exprm_state
*e
;
1287 switch (v
->syntax
) {
1289 process_item(&buttons
[function
], arg
);
1291 if (v
->new_input
&& v
->dtype
== FIX
) {
1292 STRNCPY(v
->fnum
, v
->display
, MAX_DIGITS
- 1);
1293 ui_set_display(v
->fnum
);
1300 MEMCPY(&(e
->button
), &buttons
[function
], sizeof(struct button
));
1315 GError
*error
= NULL
;
1323 const char * const * langs
= g_get_language_names ();
1325 for (i
= 0; langs
[i
]; i
++) {
1327 if (strchr (lang
, '.')) {
1331 uri
= g_build_filename(PACKAGE_DATA_DIR
,
1332 "/gnome/help/gcalctool/",
1337 if (g_file_test (uri
, G_FILE_TEST_EXISTS
)) {
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
);
1348 d
= gtk_message_dialog_new(NULL
,
1349 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1350 GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
,
1352 gtk_dialog_run(GTK_DIALOG(d
));
1353 gtk_widget_destroy(d
);
1354 g_error_free(error
);
1364 put_constant(int n
, char *con_value
, char *con_name
)
1367 char *cstr
= g_strdup(con_value
);
1369 /* Constants are written out with no thousands seaparator and with a radix
1373 SNPRINTF(key
, MAXLINE
, "constant%1dvalue", n
);
1374 set_resource(key
, cstr
);
1377 SNPRINTF(key
, MAXLINE
, "constant%1dname", n
);
1378 set_resource(key
, con_name
);
1383 put_function(int n
, char *fun_value
, char *fun_name
)
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
);
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
);
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
);
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
);
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
);
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
);
1441 update_constants_menu(void)
1443 char mline
[MAXLINE
];
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
),
1451 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->constant_menu_labels
[i
]), mline
);
1457 update_functions_menu(void)
1459 char mline
[MAXLINE
];
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
);
1471 gtk_widget_hide(gtk_widget_get_parent(X
->function_menu_labels
[i
]));
1477 edit_constants_response_cb(GtkDialog
*dialog
, gint id
)
1484 if (id
== GTK_RESPONSE_HELP
) {
1488 if (id
== GTK_RESPONSE_ACCEPT
) {
1489 if (gtk_tree_model_get_iter_first(X
->constants_model
, &iter
)) {
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
));
1507 edit_functions_response_cb(GtkDialog
*dialog
, gint id
)
1514 if (id
== GTK_RESPONSE_HELP
) {
1518 if (id
== GTK_RESPONSE_ACCEPT
) {
1519 if (gtk_tree_model_get_iter_first(X
->functions_model
, &iter
)) {
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
));
1537 static GtkTreeModel
*
1538 create_constants_model()
1541 GtkListStore
*model
;
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
,
1551 COLUMN_EDITABLE
, TRUE
,
1555 return(GTK_TREE_MODEL(model
));
1560 static GtkTreeModel
*
1561 create_functions_model()
1564 GtkListStore
*model
;
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
,
1574 COLUMN_EDITABLE
, TRUE
,
1578 return(GTK_TREE_MODEL(model
));
1583 ui_make_registers() /* Calculate memory register frame values. */
1585 char *mval
, key
[MAXLINE
];
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
);
1599 reset_mode_display(void)
1601 switch (v
->syntax
) {
1603 show_display(v
->MPdisp_val
);
1613 ui_make_registers();
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
);
1629 change_mode(int mode
)
1634 ui_set_numeric_mode(FIX
);
1636 ui_set_show_thousands_seperator(FALSE
);
1637 ui_set_show_trailing_zeroes(FALSE
);
1639 reset_mode_display();
1645 request_change_mode()
1647 GtkWidget
*dialog
, *request_check
, *button
;
1650 if (!v
->warn_change_mode
)
1653 dialog
= gtk_message_dialog_new(GTK_WINDOW(X
->kframe
),
1654 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1655 GTK_MESSAGE_WARNING
,
1658 _("Changing Modes Clears Calculation"));
1659 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog
),
1661 _("When you change modes, the current calculation "
1662 "will be cleared, and the base will be reset to "
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
,
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
;
1700 bit_toggle_cb(GtkWidget
*event_box
, GdkEventButton
*event
)
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
),
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");
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
);
1731 menu_item_select_cb(GtkWidget
*widget
)
1733 GtkStatusbar
*statusbar
= GTK_STATUSBAR(X
->statusbar
);
1737 context_id
= gtk_statusbar_get_context_id(statusbar
, "menuhelp");
1739 tooltip
= (gchar
*)g_object_get_data(G_OBJECT(widget
), "tooltip");
1741 gtk_statusbar_push(statusbar
, context_id
, tooltip
);
1748 menu_item_deselect_cb(GtkWidget
*widget
)
1750 GtkStatusbar
*statusbar
= GTK_STATUSBAR(X
->statusbar
);
1753 context_id
= gtk_statusbar_get_context_id(statusbar
, "menuhelp");
1754 gtk_statusbar_pop(statusbar
, context_id
);
1759 set_menubar_tooltip(gchar
*menu_name
)
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
);
1772 update_memory_menus()
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
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
);
1792 char nkey
[MAXLINE
], *nline
;
1793 char vkey
[MAXLINE
], *vline
;
1795 SNPRINTF(nkey
, MAXLINE
, "constant%1dname", n
);
1796 if ((nline
= get_resource(nkey
)) == NULL
) {
1800 SNPRINTF(vkey
, MAXLINE
, "constant%1dvalue", n
);
1801 if ((vline
= get_resource(vkey
)) == NULL
) {
1805 MPstr_to_num(vline
, DEC
, v
->MPcon_vals
[n
]);
1806 STRNCPY(v
->con_names
[n
], nline
, MAXLINE
- 1);
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
);
1819 string
= ui_get_display();
1822 if (v
->shelf
!= NULL
) {
1825 v
->shelf
= g_locale_from_utf8(string
, strlen(string
), NULL
, NULL
, NULL
);
1828 gtk_clipboard_set_text(gtk_clipboard_get(X
->clipboard_atom
), v
->shelf
, -1);
1835 char nkey
[MAXLINE
], *nline
;
1836 char vkey
[MAXLINE
], *vline
;
1838 SNPRINTF(nkey
, MAXLINE
, "function%1dname", n
);
1839 if ((nline
= get_resource(nkey
)) == NULL
) {
1843 SNPRINTF(vkey
, MAXLINE
, "function%1dvalue", n
);
1844 if ((vline
= get_resource(vkey
)) == NULL
) {
1848 STRNCPY(v
->fun_vals
[n
], convert(vline
), MAXLINE
- 1);
1849 STRNCPY(v
->fun_names
[n
], nline
, MAXLINE
- 1);
1854 check_for_localized_numeric_point(int keyval
)
1856 gchar outbuf
[10]; /* Minumum size 6. */
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);
1870 help_cb(GtkWidget
*widget
)
1878 hyp_cb(GtkWidget
*widget
)
1880 ui_update_trig_mode();
1886 inv_cb(GtkWidget
*widget
)
1888 ui_update_trig_mode();
1894 display_focus_out_cb(GtkWidget
*widget
, GdkEventKey
*event
)
1896 if (v
->syntax
== EXPRS
) {
1897 exp_replace(ui_get_display());
1905 display_focus_in_cb(GtkWidget
*widget
, GdkEventKey
*event
)
1914 menu_pos_func(GtkMenu
*menu
, gint
*x
, gint
*y
,
1915 gboolean
*push_in
, gpointer user_data
)
1917 GdkPoint
*loc
= (GdkPoint
*) user_data
;
1926 button_cb(GtkWidget
*widget
, GdkEventButton
*event
)
1932 function
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
),
1934 menu
= (GtkWidget
*)g_object_get_data(G_OBJECT(widget
), "calc_menu");
1937 do_button(function
, 0);
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
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
);
1966 select_display_entry(int offset
)
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
);
1978 kframe_key_press_cb(GtkWidget
*widget
, GdkEventKey
*event
)
1983 if (check_for_localized_numeric_point(event
->keyval
) == TRUE
) {
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
) {
2026 /* Connect home and end keys to move into the display entry */
2027 if (event
->keyval
== GDK_Home
) {
2028 select_display_entry(0);
2030 } else if (event
->keyval
== GDK_End
) {
2031 select_display_entry(-1);
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
)) {
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
);
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
);
2076 copy_cb(GtkWidget
*widget
)
2084 get_proc(GtkClipboard
*clipboard
, const gchar
*buffer
, gpointer data
)
2087 gchar
*dstp
, *end_buffer
, *srcp
, *text
;
2089 if (buffer
== NULL
) {
2093 end_buffer
= (gchar
*) (buffer
+ strlen(buffer
));
2094 text
= malloc(strlen(buffer
)+1);
2096 srcp
= (gchar
*) buffer
;
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
);
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.
2123 case 'F': *dstp
++ = tolower(*srcp
);
2127 case 'E': if (srcp
< (end_buffer
-1)) {
2128 if (*(srcp
+1) != '-' &&
2130 *dstp
++ = tolower(*srcp
);
2137 default: *dstp
++ = *srcp
++;
2143 switch (v
->syntax
) {
2145 ret
= lr_parse((char *) text
, v
->MPdisp_val
);
2147 show_display(v
->MPdisp_val
);
2149 ui_set_statusbar(_("Clipboard contained malformed calculation"),
2150 "gtk-dialog-error");
2155 exp_append((char *) text
);
2168 mouse_button_cb(GtkWidget
*widget
, GdkEventButton
*event
)
2170 if (event
->button
== 2) {
2171 gtk_clipboard_request_text(gtk_clipboard_get(X
->primary_atom
),
2181 paste_cb(GtkWidget
*widget
)
2183 gtk_clipboard_request_text(gtk_clipboard_get(X
->clipboard_atom
),
2190 popup_paste_cb(GtkWidget
*menu
)
2198 undo_cb(GtkWidget
*widget
)
2207 redo_cb(GtkWidget
*widget
)
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
);
2237 buffer_populate_popup_cb(GtkTextView
*textview
, GtkMenu
*menu
)
2239 gtk_container_foreach(GTK_CONTAINER(menu
), for_each_menu
, NULL
);
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
);
2256 shift_cb(GtkWidget
*widget
)
2258 int count
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
),
2260 do_button(KEY_SHIFT
, count
);
2266 show_bitcalculating_cb(GtkWidget
*widget
)
2269 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2270 ui_set_show_bitcalculating(visible
);
2276 show_registers_cb(GtkWidget
*widget
)
2279 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2280 ui_set_registers_visible(visible
);
2285 arithmetic_mode_cb(GtkWidget
*widget
)
2288 mode
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
)) ? EXPRS
: NPA
;
2289 ui_set_syntax_mode(mode
);
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
))) {
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
) {
2324 if (v
->old_cal_value
< 0 ||
2325 v
->old_cal_value
== KEY_CALCULATE
) {
2326 complete
= 1; /* Calculation is complete. */
2332 if (!e
->expression
|| !strcmp(e
->expression
, "Ans")) {
2333 complete
= 1; /* Calculation is complete. */
2342 if ((v
->modetype
!= SCIENTIFIC
) ||
2343 (v
->dtype
== FIX
&& v
->base
== DEC
)) {
2350 reset_mode_display();
2352 } else if (request_change_mode()) {
2360 accuracy_radio_cb(GtkWidget
*widget
)
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
))) {
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
);
2384 show_trailing_zeroes_cb(GtkWidget
*widget
)
2387 visible
= gtk_check_menu_item_get_active(
2388 GTK_CHECK_MENU_ITEM(widget
));
2389 ui_set_show_trailing_zeroes(visible
);
2395 quit_cb(GtkWidget
*widget
)
2397 save_win_position();
2403 spframe_response_cb(GtkWidget
*dialog
, gint response_id
)
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
);
2416 spframe_delete_cb(GtkWidget
*dialog
)
2418 spframe_response_cb(dialog
, GTK_RESPONSE_CANCEL
);
2425 spframe_activate_cb(GtkWidget
*spin
)
2427 spframe_response_cb(X
->spframe
, GTK_RESPONSE_OK
);
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
),
2443 show_thousands_separator_cb(GtkWidget
*widget
)
2447 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2448 ui_set_show_thousands_seperator(visible
);
2454 edit_constants_cb(GtkMenuItem
*item
)
2456 gtk_widget_show(X
->con_dialog
);
2462 edit_functions_cb(GtkMenuItem
*item
)
2464 gtk_widget_show(X
->fun_dialog
);
2471 int intval
, screen_height
, screen_width
;
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
)) {
2479 if (x
< 0 || x
> screen_width
) {
2484 if (get_int_resource(R_YPOS
, &intval
)) {
2486 if (y
< 0 || y
> screen_height
) {
2491 gtk_window_move(GTK_WINDOW(X
->kframe
), x
, y
);
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
) {
2510 dialog
= gtk_message_dialog_new(NULL
, 0,
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
));
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");
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
),
2780 gtk_widget_realize(X
->kframe
);
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
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
));
2829 read_cfdefs() /* Read constant/function definitions. */
2833 for (n
= 0; n
< MAX_CONSTANTS
; n
++) {
2836 for (n
= 0; n
< MAX_FUNCTIONS
; n
++) {
2837 STRCPY(v
->fun_vals
[n
], ""); /* Initially empty function strings. */
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");
2868 /* Create main gcalctool window. */
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]));
2894 gtk_window_set_focus(GTK_WINDOW(X
->kframe
),
2895 GTK_WIDGET(X
->clear_buttons
[1]));
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
) {
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.
2920 MPstr_to_num("0", DEC
, e
->ans
);
2922 show_display(e
->ans
);