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
*spframe_val
;
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
);
554 ui_update_trig_mode()
556 static char *sine_labels
[] = {N_("Sin"), N_("Sinh"),
557 N_("Sin<sup>-1</sup>"),
558 N_("Sinh<sup>-1</sup>")};
559 static int sine_functions
[] = {KEY_SIN
, KEY_SINH
, KEY_ASIN
, KEY_ASINH
};
560 static char *cosine_labels
[] = {N_("Cos"), N_("Cosh"),
561 N_("Cos<sup>-1</sup>"),
562 N_("Cosh<sup>-1</sup>")};
563 static int cosine_functions
[] = {KEY_COS
, KEY_COSH
, KEY_ACOS
, KEY_ACOSH
};
564 static char *tangent_labels
[] = {N_("Tan"), N_("Tanh"),
565 N_("Tan<sup>-1</sup>"),
566 N_("Tanh<sup>-1</sup>")};
567 static int tangent_functions
[] = {KEY_TAN
, KEY_TANH
, KEY_ATAN
, KEY_ATANH
};
570 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X
->hyperbolic_toggle
))) {
573 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(X
->inverse_toggle
))) {
577 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("sine_label")),
579 g_object_set_data(G_OBJECT(GET_WIDGET("calc_sine_button")), "calc_function",
580 GINT_TO_POINTER(sine_functions
[index
]));
582 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("cosine_label")),
583 cosine_labels
[index
]);
584 g_object_set_data(G_OBJECT(GET_WIDGET("calc_cosine_button")), "calc_function",
585 GINT_TO_POINTER(cosine_functions
[index
]));
587 gtk_label_set_markup(GTK_LABEL(GET_WIDGET("tangent_label")),
588 tangent_labels
[index
]);
589 g_object_set_data(G_OBJECT(GET_WIDGET("calc_tangent_button")), "calc_function",
590 GINT_TO_POINTER(tangent_functions
[index
]));
595 ui_set_hyperbolic_state(gboolean state
)
597 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->hyperbolic_toggle
), state
);
598 ui_update_trig_mode();
603 ui_set_inverse_state(gboolean state
)
605 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->inverse_toggle
), state
);
606 ui_update_trig_mode();
611 ui_set_trigonometric_mode(enum trig_type mode
)
613 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->trig
[mode
]), 1);
618 ui_set_numeric_mode(enum base_type mode
)
620 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->disp
[mode
]), 1);
625 ui_set_show_thousands_seperator(gboolean visible
)
629 v
->show_tsep
= visible
;
630 set_boolean_resource(R_TSEP
, v
->show_tsep
);
632 menu
= GET_WIDGET("show_thousands_separator_menu");
633 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
635 syntaxdep_show_display();
641 ui_set_show_bitcalculating(gboolean visible
)
645 v
->bitcalculating_mode
= visible
;
646 ui_set_mode(v
->modetype
);
647 set_resource(R_BITCALC
, Rcstr
[v
->bitcalculating_mode
]);
649 menu
= GET_WIDGET("show_bitcalculating_menu");
650 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
655 ui_set_show_trailing_zeroes(gboolean visible
)
659 v
->show_zeroes
= visible
;
660 set_boolean_resource(R_ZEROES
, visible
);
662 syntaxdep_show_display();
665 menu
= GET_WIDGET("show_trailing_zeroes_menu");
666 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
667 menu
= GET_WIDGET("acc_trailing_zeroes_item");
668 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
673 ui_set_undo_enabled(gboolean undo
, gboolean redo
)
675 gtk_widget_set_sensitive(GET_WIDGET("undo_menu"), undo
);
676 gtk_widget_set_sensitive(GET_WIDGET("redo_menu"), redo
);
683 Display
*dpy
= GDK_DISPLAY();
684 char client_hostname
[MAXHOSTNAMELEN
+ 4];
685 char hostname
[MAXHOSTNAMELEN
];
686 char *display
= DisplayString(dpy
);
687 char *scanner
= display
;
689 GETHOSTNAME(hostname
, MAXHOSTNAMELEN
);
695 while (*scanner
!= ':') {
701 if (strcmp(display
, hostname
) &&
702 strcmp(display
, "localhost") &&
703 strcmp(display
, "unix") &&
704 strcmp(display
, "")) {
705 SPRINTF(client_hostname
, " [%s] ", hostname
);
707 STRCPY(client_hostname
, "");
712 if (client_hostname
[0] == '\0')
715 return(strdup(client_hostname
));
720 ui_set_mode(enum mode_type mode
)
724 char *hostname
, title
[MAXLINE
];
729 gtk_widget_show(X
->bas_panel
);
730 gtk_widget_hide(X
->adv_panel
);
731 gtk_widget_hide(X
->fin_panel
);
732 gtk_widget_hide(X
->mode_panel
);
733 gtk_widget_hide(X
->bit_panel
);
734 gtk_widget_hide(X
->sci_panel
);
735 menu
= GET_WIDGET("view_basic_menu");
739 gtk_widget_hide(X
->bas_panel
);
740 gtk_widget_show(X
->adv_panel
);
741 gtk_widget_hide(X
->fin_panel
);
742 gtk_widget_hide(X
->mode_panel
);
743 gtk_widget_hide(X
->bit_panel
);
744 gtk_widget_hide(X
->sci_panel
);
745 menu
= GET_WIDGET("view_advanced_menu");
749 gtk_widget_hide(X
->bas_panel
);
750 gtk_widget_show(X
->adv_panel
);
751 gtk_widget_show(X
->fin_panel
);
752 gtk_widget_hide(X
->mode_panel
);
753 gtk_widget_hide(X
->bit_panel
);
754 gtk_widget_hide(X
->sci_panel
);
755 menu
= GET_WIDGET("view_financial_menu");
759 gtk_widget_hide(X
->bas_panel
);
760 gtk_widget_show(X
->adv_panel
);
761 gtk_widget_hide(X
->fin_panel
);
762 gtk_widget_show_all(X
->mode_panel
);
763 if (v
->bitcalculating_mode
) {
764 gtk_widget_show_all(X
->bit_panel
);
766 gtk_widget_hide(X
->bit_panel
);
768 gtk_widget_show(X
->sci_panel
);
769 menu
= GET_WIDGET("view_scientific_menu");
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
);
804 /* For initial display. */
805 gtk_window_set_default_size(GTK_WINDOW(X
->kframe
), w
, h
);
806 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 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), TRUE
);
823 ui_set_statusbar(gchar
*text
, const gchar
*imagename
)
825 GtkImage
*image
= GTK_IMAGE(X
->status_image
);
831 gtk_image_set_from_stock(image
, imagename
, GTK_ICON_SIZE_BUTTON
);
832 gtk_statusbar_pop(GTK_STATUSBAR(X
->statusbar
), 0);
833 gtk_statusbar_push(GTK_STATUSBAR(X
->statusbar
), 0, text
);
838 bin_str(int MP_value
[MP_SIZE
], char *str
, int maxbits
)
840 int i
, MP0
[MP_SIZE
], MP1
[MP_SIZE
], MP2
[MP_SIZE
], MP3
[MP_SIZE
];
843 MPstr_to_num("0", DEC
, MP0
);
844 MPstr_to_num("1", DEC
, MP1
);
845 MPstr_to_num("2", DEC
, MP2
);
847 if (mplt(MP_value
, MP0
)) {
848 mpcmim(MP_value
, MP0
);
849 mpadd(MP0
, MP1
, MP0
);
852 mpcmim(MP_value
, MP0
);
855 for (i
= 0; i
< maxbits
; i
++) {
856 double lsb
; /* Least significant bit. */
857 calc_and(MP3
, MP0
, MP1
);
861 str
[maxbits
- i
-1] = (neg
) ? '1' : '0';
863 str
[maxbits
- i
-1] = (neg
) ? '0' : '1';
866 mpdiv(MP0
, MP2
, MP3
);
877 int bit_str_len
, i
, MP1
[MP_SIZE
], MP2
[MP_SIZE
];
879 char str
[64], label
[3];
880 int ret
= usable_num(MP
);
884 MPstr_to_num(v
->display
, v
->base
, MP1
);
886 if (mpeq(MP1
, MP2
)) {
887 char *bit_str
, label
[3], tmp
[MAXLINE
];
888 int toclear
= (v
->current
== KEY_CLEAR_ENTRY
)
891 bit_str
= make_fixed(MP1
, tmp
, BIN
, MAXLINE
, toclear
);
892 bit_str_len
= strlen(bit_str
);
893 if (bit_str_len
<= MAXBITS
) {
894 gtk_widget_set_sensitive(X
->bit_panel
, TRUE
);
897 for (i
= 0; i
< MAXBITS
; i
++) {
898 label
[1] = (i
< bit_str_len
) ? bit_str
[bit_str_len
-i
-1] : '0';
899 gtk_label_set_text(GTK_LABEL(X
->bits
[MAXBITS
- i
- 1]), label
);
905 gtk_widget_set_sensitive(X
->bit_panel
, FALSE
);
909 if (ret
|| !is_integer(MP
)) {
910 gtk_widget_set_sensitive(X
->bit_panel
, FALSE
);
913 bin_str(MP
, str
, 64);
914 gtk_widget_set_sensitive(X
->bit_panel
, TRUE
);
917 for (i
= 0; i
< 64; i
++) {
918 label
[1] = str
[64 - i
- 1];
919 gtk_label_set_text(GTK_LABEL(X
->bits
[64 - i
- 1]), label
);
936 if (GTK_WIDGET_VISIBLE(
937 GTK_SCROLLED_WINDOW(X
->scrolledwindow
)->hscrollbar
)) {
940 set
= gtk_scrolled_window_get_hadjustment(
941 GTK_SCROLLED_WINDOW(X
->scrolledwindow
));
942 gtk_adjustment_set_value(set
, set
->upper
);
943 gtk_scrolled_window_set_hadjustment(
944 GTK_SCROLLED_WINDOW(X
->scrolledwindow
), set
);
950 ui_set_display(char *str
, gboolean minimize_changes
)
952 char localized
[MAX_LOCALIZED
];
953 GtkTextIter start
, end
;
959 if (str
== NULL
|| str
[0] == '\0') {
962 if (v
->noparens
== 0) {
963 localize_number(localized
, str
);
967 gtk_text_buffer_get_bounds(X
->display_buffer
, &start
, &end
);
968 text
= gtk_text_buffer_get_text(X
->display_buffer
, &start
, &end
, TRUE
);
969 diff
= strcmp (text
, str
);
975 if (minimize_changes
) {
976 if (len1
< len2
&& strncmp(text
, str
, len1
) == 0) {
978 gtk_text_buffer_insert(X
->display_buffer
, &end
, str
+ len1
, -1);
980 } else if (len1
> len2
&& strncmp(text
, str
, len2
) == 0) {
982 gtk_text_buffer_get_iter_at_offset (X
->display_buffer
, &start
, len2
);
983 gtk_text_buffer_delete(X
->display_buffer
, &start
, &end
);
989 gtk_text_buffer_delete(X
->display_buffer
, &start
, &end
);
990 gtk_text_buffer_insert(X
->display_buffer
, &end
, str
, -1);
998 /* When an error condition occurs:
1000 * - make insensitive all buttons except Clr.
1001 * - make all Scientific mode toggles and checkboxes insensitive.
1002 * - make all menubar items insensitive except:
1006 * When the error condition is cleared, resensitise everything, setting
1007 * the numeric base buttons correctly.
1011 ui_set_error_state(gboolean error
)
1017 for (i
= 0; i
< NBUTTONS
; i
++) {
1018 gtk_widget_set_sensitive(X
->buttons
[i
], !v
->error
);
1020 /* Clr button always sensitive. */
1021 gtk_widget_set_sensitive(X
->clear_buttons
[0], TRUE
);
1022 gtk_widget_set_sensitive(X
->clear_buttons
[1], TRUE
);
1025 ui_set_base(v
->base
);
1028 gtk_widget_set_sensitive(X
->mode_panel
, !v
->error
);
1030 // FIXME: Isn't this missing a whole lot of widgets?
1031 SET_MENUBAR_ITEM_STATE("copy_menu", !v
->error
);
1032 SET_MENUBAR_ITEM_STATE("paste_menu", !v
->error
);
1033 SET_MENUBAR_ITEM_STATE("insert_ascii_menu", !v
->error
);
1034 SET_MENUBAR_ITEM_STATE("view_basic_menu", !v
->error
);
1035 SET_MENUBAR_ITEM_STATE("view_advanced_menu", !v
->error
);
1036 SET_MENUBAR_ITEM_STATE("view_financial_menu", !v
->error
);
1037 SET_MENUBAR_ITEM_STATE("view_scientific_menu", !v
->error
);
1038 SET_MENUBAR_ITEM_STATE("show_trailing_zeroes_menu",
1039 !v
->error
&& (v
->modetype
== SCIENTIFIC
));
1040 SET_MENUBAR_ITEM_STATE("show_thousands_separator_menu", !v
->error
);
1041 SET_MENUBAR_ITEM_STATE("show_registers_menu", !v
->error
);
1042 SET_MENUBAR_ITEM_STATE("arithmetic_precedence_menu", !v
->error
);
1043 SET_MENUBAR_ITEM_STATE("about_menu", !v
->error
);
1049 about_cb(GtkWidget
*widget
)
1051 const gchar
*authors
[] = {
1052 "Rich Burridge <rich.burridge@sun.com>",
1053 "Sami Pietila <sampie@ariana-dsl.utu.fi>",
1054 "Robert Ancell <robert.ancell@gmail.com>",
1057 const gchar
*documenters
[] = {
1061 const gchar
*translator_credits
= _("translator-credits");
1063 const char *license
[] = {
1064 N_("Gcalctool is free software; you can redistribute it and/or modify\n"
1065 "it under the terms of the GNU General Public License as published by\n"
1066 "the Free Software Foundation; either version 2 of the License, or\n"
1067 "(at your option) any later version.\n"),
1068 N_("Gcalctool is distributed in the hope that it will be useful,\n"
1069 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1070 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1071 "GNU General Public License for more details.\n"),
1072 N_("You should have received a copy of the GNU General Public License\n"
1073 "along with Gcalctool; if not, write to the Free Software Foundation, Inc.,\n"
1074 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n")
1077 char *license_trans
= g_strconcat(_(license
[0]), "\n",
1078 _(license
[1]), "\n",
1079 _(license
[2]), "\n",
1082 gtk_show_about_dialog(GTK_WINDOW(X
->kframe
),
1083 "name",_("Gcalctool"),
1085 "copyright", _("\xc2\xa9 1986-2007 The Gcalctool authors"),
1086 "license", license_trans
,
1087 "comments", _("Calculator with financial and scientific modes."),
1089 "documenters", documenters
,
1090 "translator_credits", translator_credits
,
1091 "logo-icon-name", "gnome-calculator",
1097 cell_edited_cb(GtkCellRendererText
*cell
, const gchar
*path_string
,
1098 const gchar
*new_text
, gpointer data
)
1100 GtkTreeModel
*model
= (GtkTreeModel
*) data
;
1101 GtkTreePath
*path
= gtk_tree_path_new_from_string(path_string
);
1106 column
= g_object_get_data(G_OBJECT(cell
), "column");
1108 gtk_tree_model_get_iter(model
, &iter
, path
);
1110 switch (GPOINTER_TO_INT(column
)) {
1112 gtk_tree_model_get(model
, &iter
, column
, &old_text
, -1);
1114 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, column
,
1115 g_strdup(new_text
), -1);
1118 case COLUMN_DESCRIPTION
:
1119 gtk_tree_model_get(model
, &iter
, column
, &old_text
, -1);
1121 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, column
,
1122 g_strdup(new_text
), -1);
1126 gtk_tree_path_free(path
);
1131 add_cf_column(GtkTreeView
*treeview
, gchar
*name
, gint colno
, gboolean editable
)
1133 GtkCellRenderer
*renderer
;
1134 GtkTreeModel
*model
= gtk_tree_view_get_model(treeview
);
1136 renderer
= gtk_cell_renderer_text_new();
1138 g_signal_connect(G_OBJECT(renderer
), "edited",
1139 G_CALLBACK(cell_edited_cb
), model
);
1141 g_object_set_data(G_OBJECT(renderer
), "column", GINT_TO_POINTER(colno
));
1144 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview
),
1147 "editable", COLUMN_EDITABLE
,
1150 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview
),
1160 aframe_cancel_cb(GtkButton
*button
, gpointer user_data
)
1162 gtk_widget_hide(X
->aframe
);
1168 aframe_key_cb(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
1170 g_return_val_if_fail(GTK_IS_WIDGET(widget
), FALSE
);
1172 if (event
->keyval
== GDK_Escape
) {
1173 gtk_widget_hide(X
->aframe
);
1182 aframe_ok_cb(GtkButton
*button
, gpointer user_data
)
1187 ch
= (char *) gtk_entry_get_text(GTK_ENTRY(X
->aframe_ch
));
1189 mpcim(&val
, v
->MPdisp_val
);
1190 show_display(v
->MPdisp_val
);
1191 gtk_widget_hide(X
->aframe
);
1197 base_cb(GtkWidget
*widget
)
1199 enum base_type base
;
1201 base
= (enum base_type
) g_object_get_data(G_OBJECT(widget
),
1203 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
))) {
1215 static void do_button(int function
, int arg
)
1217 struct exprm_state
*e
;
1219 switch (v
->syntax
) {
1221 process_item(&buttons
[function
], arg
);
1223 if (v
->new_input
&& v
->dtype
== FIX
) {
1224 STRNCPY(v
->fnum
, v
->display
, MAX_DIGITS
- 1);
1225 ui_set_display(v
->fnum
, TRUE
);
1232 MEMCPY(&(e
->button
), &buttons
[function
], sizeof(struct button
));
1247 GError
*error
= NULL
;
1255 const char * const * langs
= g_get_language_names ();
1257 for (i
= 0; langs
[i
]; i
++) {
1259 if (strchr (lang
, '.')) {
1263 uri
= g_build_filename(PACKAGE_DATA_DIR
,
1264 "/gnome/help/gcalctool/",
1269 if (g_file_test (uri
, G_FILE_TEST_EXISTS
)) {
1274 command
= g_strconcat ("gnome-open ghelp://", uri
, NULL
);
1275 gscreen
= gdk_screen_get_default();
1276 gdk_spawn_command_line_on_screen (gscreen
, command
, &error
);
1280 d
= gtk_message_dialog_new(NULL
,
1281 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1282 GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
,
1284 gtk_dialog_run(GTK_DIALOG(d
));
1285 gtk_widget_destroy(d
);
1286 g_error_free(error
);
1296 put_constant(int n
, char *con_value
, char *con_name
)
1299 char *cstr
= g_strdup(con_value
);
1301 /* Constants are written out with no thousands seaparator and with a radix
1305 SNPRINTF(key
, MAXLINE
, "constant%1dvalue", n
);
1306 set_resource(key
, cstr
);
1309 SNPRINTF(key
, MAXLINE
, "constant%1dname", n
);
1310 set_resource(key
, con_name
);
1315 put_function(int n
, char *fun_value
, char *fun_name
)
1319 SNPRINTF(key
, MAXLINE
, "function%1dvalue", n
);
1320 set_resource(key
, fun_value
);
1322 SNPRINTF(key
, MAXLINE
, "function%1dname", n
);
1323 set_resource(key
, fun_name
);
1329 constant_menu_cb(GtkMenuItem
*menu
)
1331 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "constant_id"));
1332 do_button(KEY_CONSTANT
, arg
);
1338 function_menu_cb(GtkMenuItem
*menu
)
1340 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "function_id"));
1341 do_button(KEY_FUNCTION
, arg
);
1347 store_menu_cb(GtkMenuItem
*menu
)
1349 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "register_id"));
1350 do_button(KEY_STORE
, arg
);
1356 recall_menu_cb(GtkMenuItem
*menu
)
1358 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "register_id"));
1359 do_button(KEY_RECALL
, arg
);
1365 exchange_menu_cb(GtkMenuItem
*menu
)
1367 int arg
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "register_id"));
1368 do_button(KEY_EXCHANGE
, arg
);
1373 update_constants_menu(void)
1375 char mline
[MAXLINE
];
1378 for (i
= 0; i
< MAX_CONSTANTS
; i
++) {
1379 SNPRINTF(mline
, MAXLINE
,
1380 "<span weight=\"bold\">%s_%1d:</span> %s [%s]", _("C"), i
,
1381 make_number(v
->MPcon_vals
[i
], DEC
, TRUE
),
1383 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->constant_menu_labels
[i
]), mline
);
1389 update_functions_menu(void)
1391 char mline
[MAXLINE
];
1394 for (i
= 0; i
< MAX_FUNCTIONS
; i
++) {
1395 if (strlen(v
->fun_vals
[i
]) != 0) {
1396 SNPRINTF(mline
, MAXLINE
,
1397 "<span weight=\"bold\">%s_%1d:</span> %s [%s]",
1398 _("F"), i
, v
->fun_vals
[i
], v
->fun_names
[i
]);
1399 gtk_widget_show(gtk_widget_get_parent(X
->function_menu_labels
[i
]));
1400 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->function_menu_labels
[i
]), mline
);
1403 gtk_widget_hide(gtk_widget_get_parent(X
->function_menu_labels
[i
]));
1409 edit_constants_response_cb(GtkDialog
*dialog
, gint id
)
1416 if (id
== GTK_RESPONSE_HELP
) {
1420 if (id
== GTK_RESPONSE_ACCEPT
) {
1421 if (gtk_tree_model_get_iter_first(X
->constants_model
, &iter
)) {
1423 gtk_tree_model_get(X
->constants_model
, &iter
,
1424 COLUMN_NUMBER
, &number
,
1425 COLUMN_VALUE
, &value
,
1426 COLUMN_DESCRIPTION
, &description
, -1);
1427 MPstr_to_num(value
, DEC
, v
->MPcon_vals
[number
]);
1428 STRNCPY(v
->con_names
[number
], description
, MAXLINE
- 1);
1429 put_constant(number
, value
, description
);
1430 } while (gtk_tree_model_iter_next(X
->constants_model
, &iter
));
1434 gtk_widget_hide(GTK_WIDGET(dialog
));
1439 edit_functions_response_cb(GtkDialog
*dialog
, gint id
)
1446 if (id
== GTK_RESPONSE_HELP
) {
1450 if (id
== GTK_RESPONSE_ACCEPT
) {
1451 if (gtk_tree_model_get_iter_first(X
->functions_model
, &iter
)) {
1453 gtk_tree_model_get(X
->functions_model
, &iter
,
1454 COLUMN_NUMBER
, &number
,
1455 COLUMN_VALUE
, &value
,
1456 COLUMN_DESCRIPTION
, &description
, -1);
1457 STRNCPY(v
->fun_vals
[number
], convert(value
), MAXLINE
- 1);
1458 STRNCPY(v
->fun_names
[number
], description
, MAXLINE
- 1);
1459 put_function(number
, value
, description
);
1460 } while (gtk_tree_model_iter_next(X
->functions_model
, &iter
));
1464 gtk_widget_hide(GTK_WIDGET(dialog
));
1469 static GtkTreeModel
*
1470 create_constants_model()
1473 GtkListStore
*model
;
1476 model
= gtk_list_store_new(NUM_COLUMNS
, G_TYPE_INT
, G_TYPE_STRING
,
1477 G_TYPE_STRING
, G_TYPE_BOOLEAN
);
1478 for (i
= 0; i
< MAX_CONSTANTS
; i
++) {
1479 gtk_list_store_append(model
, &iter
);
1481 gtk_list_store_set(model
, &iter
,
1483 COLUMN_EDITABLE
, TRUE
,
1487 return(GTK_TREE_MODEL(model
));
1492 static GtkTreeModel
*
1493 create_functions_model()
1496 GtkListStore
*model
;
1499 model
= gtk_list_store_new(NUM_COLUMNS
, G_TYPE_INT
, G_TYPE_STRING
,
1500 G_TYPE_STRING
, G_TYPE_BOOLEAN
);
1501 for (i
= 0; i
< MAX_FUNCTIONS
; i
++) {
1502 gtk_list_store_append(model
, &iter
);
1504 gtk_list_store_set(model
, &iter
,
1506 COLUMN_EDITABLE
, TRUE
,
1510 return(GTK_TREE_MODEL(model
));
1515 ui_make_registers() /* Calculate memory register frame values. */
1517 char *mval
, key
[MAXLINE
];
1520 for (n
= 0; n
< MAX_REGISTERS
; n
++) {
1521 mval
= make_number(v
->MPmvals
[n
], v
->base
, TRUE
);
1522 gtk_entry_set_width_chars(GTK_ENTRY(X
->regs
[n
]), strlen(mval
));
1523 gtk_entry_set_text(GTK_ENTRY(X
->regs
[n
]), mval
);
1524 SNPRINTF(key
, MAXLINE
, "register%d", n
);
1525 set_resource(key
, mval
);
1531 reset_mode_display(void)
1533 switch (v
->syntax
) {
1535 show_display(v
->MPdisp_val
);
1545 ui_make_registers();
1554 (void) gdk_window_get_origin(X
->kframe
->window
, &x
, &y
);
1555 set_int_resource(R_XPOS
, x
);
1556 set_int_resource(R_YPOS
, y
);
1561 change_mode(int mode
)
1566 ui_set_numeric_mode(FIX
);
1568 ui_set_show_thousands_seperator(FALSE
);
1569 ui_set_show_trailing_zeroes(FALSE
);
1571 reset_mode_display();
1577 request_change_mode()
1579 GtkWidget
*dialog
, *request_check
, *button
;
1582 if (!v
->warn_change_mode
)
1585 dialog
= gtk_message_dialog_new(GTK_WINDOW(X
->kframe
),
1586 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1587 GTK_MESSAGE_WARNING
,
1590 _("Changing Modes Clears Calculation"));
1591 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog
),
1593 _("When you change modes, the current calculation "
1594 "will be cleared, and the base will be reset to "
1597 request_check
= gtk_check_button_new_with_mnemonic(_("_Do not warn me again"));
1598 gtk_box_pack_end(GTK_BOX(GTK_DIALOG(dialog
)->vbox
),
1599 request_check
, FALSE
, FALSE
, 0);
1601 button
= gtk_dialog_add_button(GTK_DIALOG(dialog
),
1602 _("C_hange Mode"), GTK_RESPONSE_ACCEPT
);
1603 gtk_button_set_image(GTK_BUTTON(button
),
1604 gtk_image_new_from_stock(GTK_STOCK_REFRESH
,
1605 GTK_ICON_SIZE_BUTTON
));
1606 /* Set default focus on affirmative button */
1607 gtk_widget_grab_focus(button
);
1609 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog
),
1610 GTK_RESPONSE_ACCEPT
,
1611 GTK_RESPONSE_CANCEL
,
1614 gtk_window_set_position(GTK_WINDOW(dialog
),
1615 GTK_WIN_POS_CENTER_ON_PARENT
);
1617 gtk_widget_show_all(dialog
);
1618 response
= gtk_dialog_run(GTK_DIALOG(dialog
));
1620 // FIXME: Save this in GConf
1621 v
->warn_change_mode
= !gtk_toggle_button_get_active(
1622 GTK_TOGGLE_BUTTON(request_check
));
1624 gtk_widget_destroy(dialog
);
1626 return response
== GTK_RESPONSE_ACCEPT
;
1632 bit_toggle_cb(GtkWidget
*event_box
, GdkEventButton
*event
)
1635 unsigned long long lval
;
1636 int n
, MP1
[MP_SIZE
], index
;
1638 index
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box
),
1640 n
= MAXBITS
- index
- 1;
1641 MPstr_to_num(v
->display
, v
->base
, MP1
);
1642 mpcmd(MP1
, &number
);
1643 lval
= (long long) number
;
1645 if (lval
& (1LL << n
)) {
1646 lval
&= ~(1LL << n
);
1647 gtk_label_set_text(GTK_LABEL(X
->bits
[index
]), " 0");
1650 gtk_label_set_text(GTK_LABEL(X
->bits
[index
]), " 1");
1653 number
= (double) lval
;
1654 mpcdm(&number
, v
->MPdisp_val
);
1655 show_display(v
->MPdisp_val
);
1663 menu_item_select_cb(GtkWidget
*widget
)
1665 GtkStatusbar
*statusbar
= GTK_STATUSBAR(X
->statusbar
);
1669 context_id
= gtk_statusbar_get_context_id(statusbar
, "menuhelp");
1671 tooltip
= (gchar
*)g_object_get_data(G_OBJECT(widget
), "tooltip");
1673 gtk_statusbar_push(statusbar
, context_id
, tooltip
);
1680 menu_item_deselect_cb(GtkWidget
*widget
)
1682 GtkStatusbar
*statusbar
= GTK_STATUSBAR(X
->statusbar
);
1685 context_id
= gtk_statusbar_get_context_id(statusbar
, "menuhelp");
1686 gtk_statusbar_pop(statusbar
, context_id
);
1691 set_menubar_tooltip(gchar
*menu_name
)
1696 menu
= GET_WIDGET(menu_name
);
1697 tooltip
= gtk_widget_get_tooltip_text(menu
);
1698 g_object_set_data(G_OBJECT(menu
), "tooltip", tooltip
);
1699 gtk_widget_set_tooltip_text(menu
, NULL
);
1704 update_memory_menus()
1709 for (i
= 0; i
< MAX_REGISTERS
; i
++) {
1710 SNPRINTF(mstr
, MAXLINE
, "<span weight=\"bold\">%s_%d:</span> %s",
1711 /* translators: R is the short form of register used inter alia
1713 _("R"), i
, make_number(v
->MPmvals
[i
], v
->base
, TRUE
));
1714 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->memory_store_labels
[i
]), mstr
);
1715 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->memory_recall_labels
[i
]), mstr
);
1716 gtk_label_set_markup_with_mnemonic(GTK_LABEL(X
->memory_exchange_labels
[i
]), mstr
);
1723 rframe_response_cb(GtkDialog
*dialog
, int response
)
1725 ui_set_registers_visible(FALSE
);
1731 aframe_delete_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1733 gtk_widget_hide(widget
);
1741 rframe_delete_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1743 gtk_dialog_response(GTK_DIALOG(widget
), GTK_RESPONSE_DELETE_EVENT
);
1751 spframe_delete_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1753 gtk_widget_hide(X
->spframe
);
1761 disp_cb(GtkWidget
*widget
)
1763 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
)))
1764 do_numtype((enum num_type
) g_object_get_data(G_OBJECT(widget
), "numeric_mode"));
1771 char nkey
[MAXLINE
], *nline
;
1772 char vkey
[MAXLINE
], *vline
;
1774 SNPRINTF(nkey
, MAXLINE
, "constant%1dname", n
);
1775 if ((nline
= get_resource(nkey
)) == NULL
) {
1779 SNPRINTF(vkey
, MAXLINE
, "constant%1dvalue", n
);
1780 if ((vline
= get_resource(vkey
)) == NULL
) {
1784 MPstr_to_num(vline
, DEC
, v
->MPcon_vals
[n
]);
1785 STRNCPY(v
->con_names
[n
], nline
, MAXLINE
- 1);
1790 get_display() /* The Copy function key has been pressed. */
1792 gchar
*string
= NULL
;
1793 GtkTextIter start
, end
;
1795 if (gtk_text_buffer_get_selection_bounds(X
->display_buffer
, &start
, &end
) == TRUE
) {
1796 string
= gtk_text_buffer_get_text(X
->display_buffer
, &start
, &end
, FALSE
);
1798 gtk_text_buffer_get_bounds(X
->display_buffer
, &start
, &end
);
1799 string
= gtk_text_buffer_get_text(X
->display_buffer
, &start
, &end
, FALSE
);
1802 if (v
->shelf
!= NULL
) {
1805 v
->shelf
= g_locale_from_utf8(string
, strlen(string
), NULL
, NULL
, NULL
);
1808 gtk_clipboard_set_text(gtk_clipboard_get(X
->clipboard_atom
), v
->shelf
, -1);
1815 char nkey
[MAXLINE
], *nline
;
1816 char vkey
[MAXLINE
], *vline
;
1818 SNPRINTF(nkey
, MAXLINE
, "function%1dname", n
);
1819 if ((nline
= get_resource(nkey
)) == NULL
) {
1823 SNPRINTF(vkey
, MAXLINE
, "function%1dvalue", n
);
1824 if ((vline
= get_resource(vkey
)) == NULL
) {
1828 STRNCPY(v
->fun_vals
[n
], convert(vline
), MAXLINE
- 1);
1829 STRNCPY(v
->fun_names
[n
], nline
, MAXLINE
- 1);
1834 ui_get_localized_numeric_point(void)
1836 const char *decimal_point
;
1838 decimal_point
= localeconv()->decimal_point
;
1840 return(g_locale_to_utf8(decimal_point
, -1, NULL
, NULL
, NULL
));
1846 get_proc(GtkClipboard
*clipboard
, const gchar
*buffer
, gpointer data
)
1849 gchar
*dstp
, *end_buffer
, *srcp
, *text
;
1851 if (buffer
== NULL
) {
1855 end_buffer
= (gchar
*) (buffer
+ strlen(buffer
));
1856 text
= malloc(strlen(buffer
)+1);
1858 srcp
= (gchar
*) buffer
;
1860 while (srcp
< end_buffer
) {
1862 /* If the clipboard buffer contains any occurances of the "thousands
1863 * separator", remove them.
1865 if (*srcp
== v
->tsep
[0]) {
1866 if (strstr(srcp
, v
->tsep
) == srcp
) {
1867 srcp
+= strlen(v
->tsep
);
1873 /* If an "A", "B", "C", "D" or "F" character is encountered, it
1874 * will be converted to its lowercase equivalent. If an "E" is
1875 * found, and the next character is a "-" or a "+", then it
1876 * remains as an upper case "E" (it's assumed to be a possible
1877 * exponential number), otherwise its converted to a lower case
1878 * "e". See bugs #455889 and #469245 for more details.
1885 case 'F': *dstp
++ = tolower(*srcp
);
1889 case 'E': if (srcp
< (end_buffer
-1)) {
1890 if (*(srcp
+1) != '-' &&
1892 *dstp
++ = tolower(*srcp
);
1899 default: *dstp
++ = *srcp
++;
1905 switch (v
->syntax
) {
1907 ret
= lr_parse((char *) text
, v
->MPdisp_val
);
1909 show_display(v
->MPdisp_val
);
1911 ui_set_statusbar(_("Clipboard contained malformed calculation"),
1912 "gtk-dialog-error");
1917 exp_append((char *) text
);
1929 ui_set_base(enum base_type base
)
1931 int i
, baseval
= basevals
[(int) base
];
1935 for (i
= 0; i
< 16; i
++) {
1936 gtk_widget_set_sensitive(X
->digit_buttons
[i
], i
< baseval
);
1938 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X
->base
[base
]), 1);
1943 ui_set_registers_visible(gboolean visible
)
1946 ui_make_registers();
1948 menu
= GET_WIDGET("show_registers_menu");
1949 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), visible
);
1951 gtk_widget_realize(X
->rframe
);
1954 if (gdk_window_is_visible(X
->rframe
->window
)) {
1955 gdk_window_raise(X
->rframe
->window
);
1958 ds_position_popup(X
->kframe
, X
->rframe
, DS_POPUP_ABOVE
);
1959 gtk_widget_show(X
->rframe
);
1961 gtk_widget_hide(X
->rframe
);
1964 set_boolean_resource(R_REGS
, visible
);
1970 help_cb(GtkWidget
*widget
)
1979 hyp_cb(GtkWidget
*widget
)
1981 ui_update_trig_mode();
1987 inv_cb(GtkWidget
*widget
)
1989 ui_update_trig_mode();
1994 check_for_localized_numeric_point(int keyval
)
1996 gchar outbuf
[10]; /* Minumum size 6. */
1999 ch
= gdk_keyval_to_unicode(keyval
);
2000 g_return_val_if_fail(g_unichar_validate(ch
), FALSE
);
2002 outbuf
[g_unichar_to_utf8(ch
, outbuf
)] = '\0';
2004 return(strcmp(outbuf
, X
->lnp
) == 0);
2012 GtkTextIter start
, end
;
2014 gtk_text_buffer_get_bounds(X
->display_buffer
, &start
, &end
);
2016 text
= gtk_text_buffer_get_text(X
->display_buffer
,
2028 g_object_get(G_OBJECT(X
->display_buffer
), "cursor-position", &pos
, NULL
);
2035 display_focus_out_cb(GtkWidget
*widget
, GdkEventKey
*event
)
2037 if (v
->syntax
== EXPRS
) {
2047 display_focus_in_cb(GtkWidget
*widget
, GdkEventKey
*event
)
2057 menu_pos_func(GtkMenu
*menu
, gint
*x
, gint
*y
,
2058 gboolean
*push_in
, gpointer user_data
)
2060 GdkPoint
*loc
= (GdkPoint
*) user_data
;
2069 button_cb(GtkWidget
*widget
, GdkEventButton
*event
)
2075 function
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
),
2077 menu
= (GtkWidget
*)g_object_get_data(G_OBJECT(widget
), "calc_menu");
2080 do_button(function
, 0);
2082 /* If gcalctool is being driven by gok, the on-screen keyboard
2083 * assistive technology, it's possible that the event returned by
2084 * gtk_get_current_event() is NULL. If this is the case, we need
2085 * to fudge the popping up on the menu associated with this menu
2089 update_constants_menu();
2090 update_functions_menu();
2091 update_memory_menus();
2093 if (event
== NULL
) {
2094 gdk_window_get_origin(widget
->window
, &loc
.x
, &loc
.y
);
2095 loc
.x
+= widget
->allocation
.x
;
2096 loc
.y
+= widget
->allocation
.y
;
2097 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, menu_pos_func
,
2098 (gpointer
) &loc
, 0, gtk_get_current_event_time());
2099 } else if (event
->button
== 1) {
2100 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
,
2101 event
->button
, event
->time
);
2109 select_display_entry(int offset
)
2113 gtk_text_buffer_get_iter_at_offset(X
->display_buffer
, &iter
, offset
);
2114 gtk_text_buffer_place_cursor(X
->display_buffer
, &iter
);
2115 gtk_widget_grab_focus(X
->display_item
);
2121 kframe_key_press_cb(GtkWidget
*widget
, GdkEventKey
*event
)
2126 if (check_for_localized_numeric_point(event
->keyval
) == TRUE
) {
2128 event
->keyval
= GDK_KP_Decimal
;
2131 state
= event
->state
& (GDK_CONTROL_MASK
| GDK_MOD1_MASK
);
2133 /* Accuracy shortcuts */
2134 if (state
== GDK_CONTROL_MASK
&& v
->modetype
== SCIENTIFIC
)
2136 switch (event
->keyval
) {
2170 /* Connect home and end keys to move into the display entry */
2171 if (event
->keyval
== GDK_Home
)
2173 select_display_entry(0);
2175 } else if (event
->keyval
== GDK_End
)
2177 select_display_entry(-1);
2181 for (i
= 0; i
< NBUTTONS
; i
++) {
2182 button
= X
->buttons
[i
];
2184 /* Check any parent widgets are visible */
2185 if (!GTK_WIDGET_VISIBLE(gtk_widget_get_parent(button
)) ||
2186 !GTK_WIDGET_VISIBLE(button
) || !GTK_WIDGET_IS_SENSITIVE(button
)) {
2191 while (button_widgets
[i
].accelerator_keys
[j
] != 0) {
2192 if (button_widgets
[i
].accelerator_keys
[j
] == event
->keyval
&&
2193 (button_widgets
[i
].accelerator_mods
[j
] & ~GDK_SHIFT_MASK
) == state
) {
2194 button_cb(button
, NULL
);
2207 mouse_button_cb(GtkWidget
*widget
, GdkEventButton
*event
)
2209 if (event
->button
== 2) {
2210 gtk_clipboard_request_text(gtk_clipboard_get(X
->primary_atom
),
2221 int intval
, screen_height
, screen_width
;
2224 screen_width
= gdk_screen_get_width(gdk_screen_get_default());
2225 screen_height
= gdk_screen_get_height(gdk_screen_get_default());
2227 if (get_int_resource(R_XPOS
, &intval
)) {
2229 if (x
< 0 || x
> screen_width
) {
2234 if (get_int_resource(R_YPOS
, &intval
)) {
2236 if (y
< 0 || y
> screen_height
) {
2241 gtk_window_move(GTK_WINDOW(X
->kframe
), x
, y
);
2245 show_ascii_frame() /* Display ASCII popup. */
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 show_precision_frame() /* Display Set Precision popup. */
2258 if (!GTK_WIDGET_VISIBLE(X
->spframe
)) {
2259 ds_position_popup(X
->kframe
, X
->spframe
, DS_POPUP_LEFT
);
2261 gtk_window_set_focus(GTK_WINDOW(X
->spframe
), GTK_WIDGET(X
->spframe_val
));
2262 gtk_widget_show(X
->spframe
);
2266 /* Handle menu bar menu selection. */
2270 edit_cb(GtkWidget
*widget
)
2279 can_copy
= gtk_text_buffer_get_has_selection(X
->display_buffer
);
2280 can_paste
= gtk_clipboard_wait_is_text_available(
2281 gtk_clipboard_get(X
->clipboard_atom
));
2283 gtk_widget_set_sensitive(GET_WIDGET("copy_menu"), can_copy
);
2284 gtk_widget_set_sensitive(GET_WIDGET("paste_menu"), can_paste
);
2289 handle_selection() /* Handle the GET function key being pressed. */
2291 gtk_clipboard_request_text(gtk_clipboard_get(X
->clipboard_atom
),
2298 popup_paste_cb(GtkMenuItem
*menuitem
)
2306 copy_cb(GtkWidget
*widget
)
2316 paste_cb(GtkWidget
*widget
)
2326 undo_cb(GtkWidget
*widget
)
2337 redo_cb(GtkWidget
*widget
)
2348 for_each_menu(GtkWidget
*widget
, gpointer data
)
2350 /* Find the "Paste" entry and activate it (see bug #317786). */
2351 if (strcmp(G_OBJECT_TYPE_NAME(widget
), "GtkImageMenuItem") == 0) {
2352 GtkWidget
*label
= gtk_bin_get_child(GTK_BIN(widget
));
2354 if (strcmp(gtk_label_get_text(GTK_LABEL(label
)), _("Paste")) == 0) {
2355 if (gtk_clipboard_wait_is_text_available(
2356 gtk_clipboard_get(X
->clipboard_atom
))) {
2357 gtk_widget_set_sensitive(GTK_WIDGET(widget
), TRUE
);
2358 g_signal_connect(GTK_OBJECT(widget
), "activate",
2359 G_CALLBACK(popup_paste_cb
), NULL
);
2368 buffer_populate_popup_cb(GtkTextView
*textview
, GtkMenu
*menu
)
2370 gtk_container_foreach(GTK_CONTAINER(menu
), for_each_menu
, NULL
);
2376 insert_ascii_cb(GtkWidget
*widget
)
2385 shift_cb(GtkWidget
*widget
)
2387 int count
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
),
2390 do_button(KEY_SHIFT
, count
);
2397 show_bitcalculating_cb(GtkWidget
*widget
)
2401 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2403 ui_set_show_bitcalculating(visible
);
2410 show_registers_cb(GtkWidget
*widget
)
2414 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2416 ui_set_registers_visible(visible
);
2422 arithmetic_mode_cb(GtkWidget
*widget
)
2426 mode
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
)) ? EXPRS
: NPA
;
2428 ui_set_syntax_mode(mode
);
2435 mode_radio_cb(GtkWidget
*menu
)
2437 struct exprm_state
*e
;
2438 int mode
; /* The new mode. */
2439 int immediate
= 0; /* Set if we can change mode without warning user. */
2440 int complete
= 0; /* Set if the user has completed a calculation. */
2442 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu
))) {
2450 mode
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "calcmode"));
2452 /* If the user has completed a calculation and we are going to a
2453 * new mode that is "compatible" with this one, then just change
2454 * modes. Otherwise display a dialog warning the user that the
2455 * current calculation will be cleared.
2457 * Incompatible modes are:
2459 * Scientific -> Basic
2460 * Scientific -> Advanced
2461 * Scientific -> Financial
2463 * (unless we are in Scientific mode with Decimal numeric base and Fixed).
2466 switch (v
->syntax
) {
2468 if (v
->old_cal_value
< 0 ||
2469 v
->old_cal_value
== KEY_CALCULATE
) {
2470 complete
= 1; /* Calculation is complete. */
2476 if (!e
->expression
|| !strcmp(e
->expression
, "Ans")) {
2477 complete
= 1; /* Calculation is complete. */
2486 if ((v
->modetype
!= SCIENTIFIC
) ||
2487 (v
->dtype
== FIX
&& v
->base
== DEC
)) {
2494 reset_mode_display();
2496 } else if (request_change_mode()) {
2504 accuracy_radio_cb(GtkWidget
*widget
)
2508 count
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
), "accuracy"));
2511 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
))) {
2519 accuracy_other_cb(GtkWidget
*widget
)
2522 show_precision_frame();
2529 show_trailing_zeroes_cb(GtkWidget
*widget
)
2533 visible
= gtk_check_menu_item_get_active(
2534 GTK_CHECK_MENU_ITEM(widget
));
2536 ui_set_show_trailing_zeroes(visible
);
2543 quit_cb(GtkWidget
*widget
)
2545 save_win_position();
2552 spframe_cancel_cb(GtkButton
*button
)
2554 gtk_widget_hide(X
->spframe
);
2560 spframe_key_cb(GtkWidget
*widget
, GdkEventKey
*event
)
2562 if (event
->keyval
== GDK_minus
) {
2563 ui_set_statusbar(_("Accuracy value out of range"),
2564 "gtk-dialog-error");
2566 } else if (event
->keyval
== GDK_Escape
) {
2567 gtk_widget_hide(X
->spframe
);
2576 spframe_ok_cb(GtkButton
*button
)
2578 int val
= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(X
->spframe_val
));
2582 set_int_resource(R_ACCURACY
, v
->accuracy
);
2584 ui_set_accuracy(v
->accuracy
);
2586 ui_make_registers();
2589 gtk_widget_hide(X
->spframe
);
2595 trig_cb(GtkWidget
*widget
)
2597 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
)))
2598 do_trigtype((enum trig_type
) g_object_get_data(G_OBJECT(widget
),
2606 struct exprm_state
*e
;
2609 ui_set_base(v
->base
);
2610 ui_set_trigonometric_mode(v
->ttype
);
2611 ui_set_numeric_mode(v
->dtype
);
2613 gtk_widget_show(X
->kframe
);
2615 switch (v
->syntax
) {
2620 /* Init expression mode.
2621 * This must be executed after do_base is called at init.
2622 * FIXME: The init code here is duplicated elsewhere.
2625 MPstr_to_num("0", DEC
, e
->ans
);
2627 show_display(e
->ans
);
2640 show_thousands_separator_cb(GtkWidget
*widget
)
2644 visible
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget
));
2646 ui_set_show_thousands_seperator(visible
);
2653 edit_constants_cb(GtkMenuItem
*item
)
2655 gtk_widget_show(X
->con_dialog
);
2661 edit_functions_cb(GtkMenuItem
*item
)
2663 gtk_widget_show(X
->fun_dialog
);
2673 PangoFontDescription
*font_desc
;
2674 GtkSizeGroup
*size_group
;
2675 GtkAccelGroup
*accel_group
;
2676 GtkWidget
*treeview
;
2678 X
->ui
= glade_xml_new(UI_FILE
, NULL
, NULL
);
2679 if (X
->ui
== NULL
) {
2682 dialog
= gtk_message_dialog_new(NULL
, 0,
2685 N_("Error loading user interface"));
2686 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog
),
2687 N_("The user interace file %s is missing or unable to be loaded. Please check your installation."), UI_FILE
);
2688 gtk_dialog_add_buttons(GTK_DIALOG(dialog
), GTK_STOCK_QUIT
, GTK_RESPONSE_ACCEPT
, NULL
);
2690 gtk_dialog_run(GTK_DIALOG(dialog
));
2694 /* When connecting up signals, would ideally use autoconnect but not
2695 * sure how to get the build process working.
2696 * See http://library.gnome.org/devel/libglade/unstable and
2697 * http://www.jamesh.id.au/software/libglade/
2698 * for some information on how to get this to work
2699 * glade_xml_signal_autoconnect(X->ui);
2701 CONNECT_SIGNAL(kframe_key_press_cb
);
2702 CONNECT_SIGNAL(button_cb
);
2703 CONNECT_SIGNAL(menu_item_select_cb
);
2704 CONNECT_SIGNAL(menu_item_deselect_cb
);
2705 CONNECT_SIGNAL(mode_radio_cb
);
2706 CONNECT_SIGNAL(inv_cb
);
2707 CONNECT_SIGNAL(hyp_cb
);
2708 CONNECT_SIGNAL(trig_cb
);
2709 CONNECT_SIGNAL(base_cb
);
2710 CONNECT_SIGNAL(disp_cb
);
2711 CONNECT_SIGNAL(quit_cb
);
2712 CONNECT_SIGNAL(edit_cb
);
2713 CONNECT_SIGNAL(copy_cb
);
2714 CONNECT_SIGNAL(paste_cb
);
2715 CONNECT_SIGNAL(insert_ascii_cb
);
2716 CONNECT_SIGNAL(undo_cb
);
2717 CONNECT_SIGNAL(redo_cb
);
2718 CONNECT_SIGNAL(help_cb
);
2719 CONNECT_SIGNAL(about_cb
);
2720 CONNECT_SIGNAL(show_trailing_zeroes_cb
);
2721 CONNECT_SIGNAL(show_thousands_separator_cb
);
2722 CONNECT_SIGNAL(show_bitcalculating_cb
);
2723 CONNECT_SIGNAL(show_registers_cb
);
2724 CONNECT_SIGNAL(accuracy_radio_cb
);
2725 CONNECT_SIGNAL(accuracy_other_cb
);
2726 CONNECT_SIGNAL(constant_menu_cb
);
2727 CONNECT_SIGNAL(function_menu_cb
);
2728 CONNECT_SIGNAL(store_menu_cb
);
2729 CONNECT_SIGNAL(recall_menu_cb
);
2730 CONNECT_SIGNAL(exchange_menu_cb
);
2731 CONNECT_SIGNAL(arithmetic_mode_cb
);
2732 CONNECT_SIGNAL(mouse_button_cb
);
2733 CONNECT_SIGNAL(display_focus_in_cb
);
2734 CONNECT_SIGNAL(display_focus_out_cb
);
2735 /* Detect when populating the right-click menu to enable pasting */
2736 CONNECT_SIGNAL(buffer_populate_popup_cb
);
2737 CONNECT_SIGNAL(shift_cb
);
2738 CONNECT_SIGNAL(bit_toggle_cb
);
2739 CONNECT_SIGNAL(aframe_delete_cb
);
2740 CONNECT_SIGNAL(aframe_ok_cb
);
2741 CONNECT_SIGNAL(aframe_cancel_cb
);
2742 CONNECT_SIGNAL(aframe_key_cb
);
2743 CONNECT_SIGNAL(spframe_delete_cb
);
2744 CONNECT_SIGNAL(spframe_ok_cb
);
2745 CONNECT_SIGNAL(spframe_cancel_cb
);
2746 CONNECT_SIGNAL(spframe_key_cb
);
2747 CONNECT_SIGNAL(rframe_delete_cb
);
2748 CONNECT_SIGNAL(rframe_response_cb
);
2749 CONNECT_SIGNAL(edit_constants_cb
);
2750 CONNECT_SIGNAL(edit_functions_cb
);
2751 CONNECT_SIGNAL(edit_constants_response_cb
);
2752 CONNECT_SIGNAL(edit_functions_response_cb
);
2754 X
->clipboard_atom
= gdk_atom_intern("CLIPBOARD", FALSE
);
2755 X
->primary_atom
= gdk_atom_intern("PRIMARY", FALSE
);
2756 X
->kframe
= GET_WIDGET("calc_window");
2757 X
->aframe
= GET_WIDGET("ascii_window");
2758 X
->aframe_ch
= GET_WIDGET("ascii_entry");
2759 X
->spframe
= GET_WIDGET("precision_dialog");
2760 X
->spframe_val
= GET_WIDGET("spframe_spin");
2761 X
->rframe
= GET_WIDGET("register_dialog");
2762 X
->con_dialog
= GET_WIDGET("edit_constants_dialog");
2763 X
->fun_dialog
= GET_WIDGET("edit_functions_dialog");
2764 X
->menubar
= GET_WIDGET("menubar");
2765 X
->scrolledwindow
= GET_WIDGET("display_scroll"),
2766 X
->display_item
= GET_WIDGET("displayitem"),
2767 X
->bas_panel
= GET_WIDGET("basic_panel");
2768 X
->sci_panel
= GET_WIDGET("scientific_panel");
2769 X
->adv_panel
= GET_WIDGET("advanced_panel");
2770 X
->fin_panel
= GET_WIDGET("financial_panel");
2771 X
->bit_panel
= GET_WIDGET("bit_panel");
2772 X
->clear_buttons
[0] = GET_WIDGET("calc_clear_simple_button");
2773 X
->clear_buttons
[1] = GET_WIDGET("calc_clear_advanced_button");
2774 X
->mode_panel
= GET_WIDGET("mode_panel");
2775 X
->trig
[0] = GET_WIDGET("degrees_radio");
2776 X
->trig
[1] = GET_WIDGET("gradians_radio");
2777 X
->trig
[2] = GET_WIDGET("radians_radio");
2778 X
->base
[0] = GET_WIDGET("binary_radio");
2779 X
->base
[1] = GET_WIDGET("octal_radio");
2780 X
->base
[2] = GET_WIDGET("decimal_radio");
2781 X
->base
[3] = GET_WIDGET("hexadecimal_radio");
2782 X
->disp
[0] = GET_WIDGET("engineering_radio");
2783 X
->disp
[1] = GET_WIDGET("fixed_point_radio");
2784 X
->disp
[2] = GET_WIDGET("scientific_radio");
2785 X
->inverse_toggle
= GET_WIDGET("inverse_check");
2786 X
->hyperbolic_toggle
= GET_WIDGET("hyperbolic_check");
2787 X
->statusbar
= GET_WIDGET("statusbar");
2788 for (i
= 0; i
< 16; i
++) {
2789 SNPRINTF(name
, MAXLINE
, "calc_%x_button", i
);
2790 X
->digit_buttons
[i
] = GET_WIDGET(name
);
2792 for (i
= 0; i
< MAX_REGISTERS
; i
++) {
2793 SNPRINTF(name
, MAXLINE
, "register_entry_%d", i
);
2794 X
->regs
[i
] = GET_WIDGET(name
);
2797 /* Load buttons and set them all to be the same size */
2798 size_group
= gtk_size_group_new(GTK_SIZE_GROUP_BOTH
);
2799 for (i
= 0; i
< NBUTTONS
; i
++) {
2800 SNPRINTF(name
, MAXLINE
, "calc_%s_button",
2801 button_widgets
[i
].widget_name
);
2802 X
->buttons
[i
] = GET_WIDGET(name
);
2803 assert(X
->buttons
[i
] != NULL
);
2805 gtk_size_group_add_widget(size_group
, X
->buttons
[i
]);
2807 g_object_set_data(G_OBJECT(X
->buttons
[i
]), "calc_function",
2808 GINT_TO_POINTER(button_widgets
[i
].key
));
2811 /* Make popup buttons */
2812 g_object_set_data(G_OBJECT(GET_WIDGET("calc_accuracy_button")),
2813 "calc_menu", GET_WIDGET("accuracy_popup"));
2814 g_object_set_data(G_OBJECT(GET_WIDGET("calc_shift_left_button")),
2815 "calc_menu", GET_WIDGET("left_shift_popup"));
2816 g_object_set_data(G_OBJECT(GET_WIDGET("calc_shift_right_button")),
2817 "calc_menu", GET_WIDGET("right_shift_popup"));
2819 g_object_set_data(G_OBJECT(GET_WIDGET("calc_constants_button")),
2820 "calc_menu", GET_WIDGET("constants_popup"));
2821 for (i
= 0; i
< MAX_CONSTANTS
; i
++) {
2822 SNPRINTF(name
, MAXLINE
, "constant_menu_item%d", i
);
2823 widget
= GET_WIDGET(name
);
2824 g_object_set_data(G_OBJECT(widget
), "constant_id", GINT_TO_POINTER(i
));
2825 X
->constant_menu_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2828 g_object_set_data(G_OBJECT(GET_WIDGET("calc_functions_button")),
2829 "calc_menu", GET_WIDGET("functions_popup"));
2830 for (i
= 0; i
< MAX_FUNCTIONS
; i
++) {
2831 SNPRINTF(name
, MAXLINE
, "function_menu_item%d", i
);
2832 widget
= GET_WIDGET(name
);
2833 g_object_set_data(G_OBJECT(widget
), "function_id", GINT_TO_POINTER(i
));
2834 X
->function_menu_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2837 g_object_set_data(G_OBJECT(GET_WIDGET("calc_store_button")),
2838 "calc_menu", GET_WIDGET("memory_store_popup"));
2839 g_object_set_data(G_OBJECT(GET_WIDGET("calc_recall_button")),
2840 "calc_menu", GET_WIDGET("memory_recall_popup"));
2841 g_object_set_data(G_OBJECT(GET_WIDGET("calc_exchange_button")),
2842 "calc_menu", GET_WIDGET("memory_exchange_popup"));
2843 for (i
= 0; i
< MAX_REGISTERS
; i
++) {
2844 SNPRINTF(name
, MAXLINE
, "store_menu_item%d", i
);
2845 widget
= GET_WIDGET(name
);
2846 g_object_set_data(G_OBJECT(widget
), "register_id", GINT_TO_POINTER(i
));
2847 X
->memory_store_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2849 SNPRINTF(name
, MAXLINE
, "recall_menu_item%d", i
);
2850 widget
= GET_WIDGET(name
);
2851 g_object_set_data(G_OBJECT(widget
), "register_id", GINT_TO_POINTER(i
));
2852 X
->memory_recall_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2854 SNPRINTF(name
, MAXLINE
, "exchange_menu_item%d", i
);
2855 widget
= GET_WIDGET(name
);
2856 g_object_set_data(G_OBJECT(widget
), "register_id", GINT_TO_POINTER(i
));
2857 X
->memory_exchange_labels
[i
] = gtk_bin_get_child(GTK_BIN(widget
));
2860 /* Load bit panel */
2861 for (i
= 0; i
< MAXBITS
; i
++)
2863 SNPRINTF(name
, MAXLINE
, "bit_label_%d", i
);
2864 X
->bits
[i
] = GET_WIDGET(name
);
2865 SNPRINTF(name
, MAXLINE
, "bit_eventbox_%d", i
);
2866 g_object_set_data(G_OBJECT(GET_WIDGET(name
)),
2867 "bit_index", GINT_TO_POINTER(i
));
2870 /* Make menu tooltips displayed in the status bar */
2871 set_menubar_tooltip("quit_menu");
2872 set_menubar_tooltip("copy_menu");
2873 set_menubar_tooltip("paste_menu");
2874 set_menubar_tooltip("insert_ascii_menu");
2875 set_menubar_tooltip("undo_menu");
2876 set_menubar_tooltip("redo_menu");
2877 set_menubar_tooltip("view_basic_menu");
2878 set_menubar_tooltip("view_advanced_menu");
2879 set_menubar_tooltip("view_financial_menu");
2880 set_menubar_tooltip("view_scientific_menu");
2881 set_menubar_tooltip("show_trailing_zeroes_menu");
2882 set_menubar_tooltip("show_thousands_separator_menu");
2883 set_menubar_tooltip("show_bitcalculating_menu");
2884 set_menubar_tooltip("show_registers_menu");
2885 set_menubar_tooltip("ltr_precedence_menu");
2886 set_menubar_tooltip("arithmetic_precedence_menu");
2887 set_menubar_tooltip("help_menu");
2888 set_menubar_tooltip("about_menu");
2891 widget
= GET_WIDGET("kvbox");
2892 gtk_widget_set_direction(widget
, GTK_TEXT_DIR_LTR
);
2893 gtk_widget_set_direction(X
->fin_panel
, GTK_TEXT_DIR_LTR
);
2895 /* Make dialogs transient of the main window */
2896 gtk_window_set_transient_for(GTK_WINDOW(X
->aframe
), GTK_WINDOW(X
->kframe
));
2897 gtk_window_set_transient_for(GTK_WINDOW(X
->spframe
), GTK_WINDOW(X
->kframe
));
2898 gtk_window_set_transient_for(GTK_WINDOW(X
->rframe
), GTK_WINDOW(X
->kframe
));
2899 gtk_window_set_transient_for(GTK_WINDOW(X
->con_dialog
),
2900 GTK_WINDOW(X
->kframe
));
2902 gtk_spin_button_set_value(GTK_SPIN_BUTTON(X
->spframe_val
),
2903 (double) v
->accuracy
); // FIXME
2904 gtk_entry_set_max_length(GTK_ENTRY(X
->spframe_val
), 2);
2906 gtk_dialog_set_default_response(GTK_DIALOG(X
->con_dialog
),
2907 GTK_RESPONSE_ACCEPT
);
2909 /* Make constant tree model */
2910 X
->constants_model
= create_constants_model();
2911 treeview
= GET_WIDGET("edit_constants_treeview");
2912 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview
), X
->constants_model
);
2913 gtk_tree_selection_set_mode(
2914 gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
)),
2915 GTK_SELECTION_SINGLE
);
2916 add_cf_column(GTK_TREE_VIEW(treeview
), _("No."),
2917 COLUMN_NUMBER
, FALSE
);
2918 add_cf_column(GTK_TREE_VIEW(treeview
), _("Value"),
2919 COLUMN_VALUE
, TRUE
);
2920 add_cf_column(GTK_TREE_VIEW(treeview
), _("Description"),
2921 COLUMN_DESCRIPTION
, TRUE
);
2923 /* Make function tree model */
2924 X
->functions_model
= create_functions_model();
2925 treeview
= GET_WIDGET("edit_functions_treeview");
2926 gtk_dialog_set_default_response(GTK_DIALOG(X
->fun_dialog
),
2927 GTK_RESPONSE_ACCEPT
);
2928 gtk_window_set_transient_for(GTK_WINDOW(X
->fun_dialog
),
2929 GTK_WINDOW(X
->kframe
));
2930 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview
), X
->functions_model
);
2931 gtk_tree_selection_set_mode(
2932 gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
)),
2933 GTK_SELECTION_SINGLE
);
2934 add_cf_column(GTK_TREE_VIEW(treeview
), _("No."),
2935 COLUMN_NUMBER
, FALSE
);
2936 add_cf_column(GTK_TREE_VIEW(treeview
), _("Value"),
2937 COLUMN_VALUE
, TRUE
);
2938 add_cf_column(GTK_TREE_VIEW(treeview
), _("Description"),
2939 COLUMN_DESCRIPTION
, TRUE
);
2942 X
->display_buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(X
->display_item
));
2943 gtk_widget_ensure_style(X
->display_item
);
2944 font_desc
= pango_font_description_copy(X
->display_item
->style
->font_desc
);
2945 pango_font_description_set_size(font_desc
, 16 * PANGO_SCALE
);
2946 gtk_widget_modify_font(X
->display_item
, font_desc
);
2947 pango_font_description_free(font_desc
);
2948 gtk_widget_set_name(X
->display_item
, "displayitem");
2949 // FIXME: We can't allow the display to be editable. See bug #326938
2950 gtk_text_view_set_editable(GTK_TEXT_VIEW(X
->display_item
),
2951 (v
->syntax
== EXPRS
));
2952 atk_object_set_role(gtk_widget_get_accessible(X
->display_item
),
2955 gtk_widget_realize(X
->kframe
);
2958 for (i
= 0; i
< 3; i
++)
2959 g_object_set_data(G_OBJECT(X
->trig
[i
]),
2960 "trig_mode", GINT_TO_POINTER(i
));
2961 for (i
= 0; i
< 4; i
++)
2962 g_object_set_data(G_OBJECT(X
->base
[i
]),
2963 "base_mode", GINT_TO_POINTER(i
));
2964 for (i
= 0; i
< 3; i
++)
2965 g_object_set_data(G_OBJECT(X
->disp
[i
]),
2966 "numeric_mode", GINT_TO_POINTER(i
));
2968 /* Put status image into statusbar (glade doesn't support child widgets
2970 X
->status_image
= gtk_image_new_from_stock("", GTK_ICON_SIZE_BUTTON
);
2971 gtk_widget_show(X
->status_image
);
2972 gtk_box_pack_start(GTK_BOX(X
->statusbar
), X
->status_image
, FALSE
, TRUE
, 0);
2974 /* Set modes for menu items */
2975 for (i
= 1; i
< 16; i
++) {
2976 SNPRINTF(name
, MAXLINE
, "shift_left%d_menu", i
);
2977 g_object_set_data(G_OBJECT(GET_WIDGET(name
)),
2978 "shiftcount", GINT_TO_POINTER(i
));
2979 SNPRINTF(name
, MAXLINE
, "shift_right%d_menu", i
);
2980 g_object_set_data(G_OBJECT(GET_WIDGET(name
)),
2981 "shiftcount", GINT_TO_POINTER(-i
));
2983 g_object_set_data(G_OBJECT(GET_WIDGET("view_basic_menu")),
2984 "calcmode", GINT_TO_POINTER(BASIC
));
2985 g_object_set_data(G_OBJECT(GET_WIDGET("view_advanced_menu")),
2986 "calcmode", GINT_TO_POINTER(ADVANCED
));
2987 g_object_set_data(G_OBJECT(GET_WIDGET("view_financial_menu")),
2988 "calcmode", GINT_TO_POINTER(FINANCIAL
));
2989 g_object_set_data(G_OBJECT(GET_WIDGET("view_scientific_menu")),
2990 "calcmode", GINT_TO_POINTER(SCIENTIFIC
));
2992 /* Make shortcuts for accuracy menus */
2993 accel_group
= gtk_accel_group_new();
2994 gtk_window_add_accel_group(GTK_WINDOW(X
->kframe
), accel_group
);
2995 for (i
= 0; i
< 10; i
++) {
2996 SNPRINTF(name
, MAXLINE
, "acc_item%d", i
);
2997 widget
= GET_WIDGET(name
);
2998 g_object_set_data(G_OBJECT(widget
), "accuracy", GINT_TO_POINTER(i
));
3004 read_cfdefs() /* Read constant/function definitions. */
3008 for (n
= 0; n
< MAX_CONSTANTS
; n
++) {
3011 for (n
= 0; n
< MAX_FUNCTIONS
; n
++) {
3012 STRCPY(v
->fun_vals
[n
], ""); /* Initially empty function strings. */
3019 ui_init(int *argc
, char ***argv
)
3021 X
= (XVars
) LINT_CAST(calloc(1, sizeof(struct Xobject
)));
3023 gtk_init(argc
, argv
);
3025 X
->lnp
= ui_get_localized_numeric_point();
3027 gtk_rc_get_default_files();
3029 v
->home
= (char *) g_get_home_dir();
3030 gtk_rc_parse(g_build_path(v
->home
, RCNAME
, NULL
));
3032 gtk_window_set_default_icon_name("gnome-calculator");
3042 /* Create main gcalctool window. */
3045 ui_set_show_thousands_seperator(v
->show_tsep
);
3046 ui_set_show_trailing_zeroes(v
->show_zeroes
);
3047 ui_set_show_bitcalculating(v
->bitcalculating_mode
);
3049 ui_set_syntax_mode(v
->syntax
);
3050 ui_set_display("0.00", FALSE
);
3051 ui_set_mode(v
->modetype
);
3052 ui_set_numeric_mode(FIX
);
3053 ui_set_base(v
->base
);
3054 ui_set_accuracy(v
->accuracy
);
3055 ui_set_undo_enabled(FALSE
, FALSE
);
3056 ui_update_trig_mode();
3058 /* Show the memory register window? */
3059 ui_make_registers();
3060 if (get_boolean_resource(R_REGS
, &boolval
))
3061 ui_set_registers_visible(boolval
);
3063 /* Focus on the clear button */
3064 if (v
->modetype
== BASIC
) {
3065 gtk_window_set_focus(GTK_WINDOW(X
->kframe
),
3066 GTK_WIDGET(X
->clear_buttons
[0]));
3068 gtk_window_set_focus(GTK_WINDOW(X
->kframe
),
3069 GTK_WIDGET(X
->clear_buttons
[1]));