Changes for v5.5.15; see the ChangeLog and NEWS files for more details.
[gcalctool.git] / gcalctool / gtk.c
blob2c2a769d3ac89f3ea4bac7addf4088835895913f
2 /* $Header$
4 * Copyright (c) 1987-2004 Sun Microsystems, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
21 #include "config.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <limits.h>
27 #include <sys/param.h>
28 #include <sys/stat.h>
29 #include <netdb.h>
30 #include <pwd.h>
31 #include "calctool.h"
32 #include "extern.h"
33 #include "dsdefs.h"
34 #include "functions.h"
35 #include "lr_parser.h"
36 #include <gtk/gtk.h>
37 #include <gdk/gdkx.h>
38 #include <gdk/gdkkeysyms.h>
39 #include <gconf/gconf-client.h>
40 #include "ce_parser.h"
42 #define BUT_0_BAS X->bas_buttons[24] /* 0 - in "Basic" mode */
43 #define BUT_1_BAS X->bas_buttons[16] /* 1 - in "Basic" mode */
44 #define BUT_2_BAS X->bas_buttons[17] /* 2 - in "Basic" mode */
45 #define BUT_3_BAS X->bas_buttons[18] /* 3 - in "Basic" mode */
46 #define BUT_4_BAS X->bas_buttons[8] /* 4 - in "Basic" mode */
47 #define BUT_5_BAS X->bas_buttons[9] /* 5 - in "Basic" mode */
48 #define BUT_6_BAS X->bas_buttons[10] /* 6 - in "Basic" mode */
49 #define BUT_7_BAS X->bas_buttons[0] /* 7 - in "Basic" mode */
50 #define BUT_8_BAS X->bas_buttons[1] /* 8 - in "Basic" mode */
51 #define BUT_9_BAS X->bas_buttons[2] /* 9 - in "Basic" mode */
53 #define BUT_0_ADV X->adv_buttons[24] /* 0 - in "Advanced" mode */
54 #define BUT_1_ADV X->adv_buttons[16] /* 1 - in "Advanced" mode */
55 #define BUT_2_ADV X->adv_buttons[17] /* 2 - in "Advanced" mode */
56 #define BUT_3_ADV X->adv_buttons[18] /* 3 - in "Advanced" mode */
57 #define BUT_4_ADV X->adv_buttons[8] /* 4 - in "Advanced" mode */
58 #define BUT_5_ADV X->adv_buttons[9] /* 5 - in "Advanced" mode */
59 #define BUT_6_ADV X->adv_buttons[10] /* 6 - in "Advanced" mode */
60 #define BUT_7_ADV X->adv_buttons[0] /* 7 - in "Advanced" mode */
61 #define BUT_8_ADV X->adv_buttons[1] /* 8 - in "Advanced" mode */
62 #define BUT_9_ADV X->adv_buttons[2] /* 9 - in "Advanced" mode */
64 #define BUT_CLR_BAS X->bas_buttons[2] /* Clr - in "Basic" mode */
65 #define BUT_CLR_ADV X->adv_buttons[7] /* Clr - in "Advanced" mode */
67 #define BUT_ACC X->sci_buttons[7] /* a */
68 #define BUT_A X->sci_buttons[24] /* A */
69 #define BUT_B X->sci_buttons[25] /* B */
70 #define BUT_C X->sci_buttons[26] /* C */
71 #define BUT_D X->sci_buttons[16] /* D */
72 #define BUT_E X->sci_buttons[17] /* E */
73 #define BUT_F X->sci_buttons[18] /* F */
75 struct Xobject { /* Gtk+/Xlib graphics object. */
76 GtkAccelGroup *kbd_accel;
77 GdkAtom clipboard_atom;
78 GConfClient *client;
79 GtkUIManager *ui;
80 GtkActionGroup *actions;
81 GtkTooltips *tips;
82 GtkWidget *aframe; /* ASCII window. */
83 GtkWidget *aframe_ch;
84 GtkWidget *base[MAXBASES]; /* Numeric base radio buttons. */
85 GtkWidget *con_dialog; /* Edit constants dialog. */
86 GtkWidget *disp[MAXDISPMODES]; /* Numeric display mode. */
87 GtkWidget *fun_dialog; /* Edit functions dialog. */
88 GtkWidget *hyp; /* Hyperbolic mode. */
89 GtkWidget *inv; /* Inverse mode. */
90 GtkWidget *kframe; /* Main window. */
91 GtkWidget *kvbox;
92 GtkWidget *ktable;
93 GdkPixbuf *icon; /* Main window icon. */
94 GtkWidget *menubar;
95 GtkWidget *mode_panel;
97 GtkWidget *khbox; /* Box containing statusbar and image */
98 GtkWidget *status_image; /* Statusbar image */
99 GtkWidget *statusbar;
101 GtkWidget *display_item; /* Calculator display. */
102 GtkWidget *rframe; /* Register window. */
103 GtkWidget *spframe; /* Set Precision window. */
104 GtkWidget *spframe_val;
105 GtkWidget *scrolledwindow; /* Scrolled window for display_item. */
106 GtkWidget *regs[MAXREGS]; /* Memory registers. */
107 GtkWidget *menus[MAXMENUS];
108 GtkWidget *trig[MAXTRIGMODES]; /* Trigonometric mode. */
110 GtkWidget *bas_buttons[BROWS * BCOLS];
111 GtkWidget *adv_buttons[AROWS * ACOLS];
112 GtkWidget *fin_buttons[FROWS * FCOLS];
113 GtkWidget *sci_buttons[SROWS * SCOLS];
115 GtkWidget *bas_panel;
116 GtkWidget *adv_panel;
117 GtkWidget *fin_panel;
118 GtkWidget *sci_panel;
120 Display *dpy;
122 int menuval; /* Index to button array at menu time. */
123 char *lnp; /* Localized numerical point (UTF8 format) */
124 struct button *mrec[MAXMENUS];
127 typedef struct Xobject *XVars;
129 enum
131 COLUMN_NUMBER,
132 COLUMN_VALUE,
133 COLUMN_DESCRIPTION,
134 COLUMN_EDITABLE,
135 NUM_COLUMNS
138 typedef struct {
139 gint number;
140 gchar *value;
141 gchar *description;
142 gboolean editable;
143 } CF_Item;
145 static GtkWidget *create_menu(enum menu_type, struct button *);
146 static GtkWidget *create_mode_panel(GtkWidget *);
147 static GtkWidget *make_menu_button(gchar *, int);
148 static GtkWidget *make_but_panel(GtkWidget *, GtkWidget **,
149 struct button *, int, int, char *);
151 static char *get_localized_numeric_point(void);
152 static char *make_hostname(Display *);
154 static gboolean aframe_key_cb(GtkWidget *, GdkEventKey *, gpointer);
155 static gboolean dismiss_aframe(GtkWidget *, GdkEvent *, gpointer);
156 static gboolean dismiss_rframe(GtkWidget *, GdkEvent *, gpointer);
157 static gboolean dismiss_spframe(GtkWidget *, GdkEvent *, gpointer);
158 static gboolean kframe_key_press_cb(GtkWidget *, GdkEventKey *, gpointer);
159 static gboolean spframe_key_cb(GtkWidget *, GdkEventKey *, gpointer);
161 static void about_cb(GtkAction *action);
162 static void add_cf_column(GtkTreeView *, gchar *, gint, gboolean);
163 static void aframe_cancel_cb(GtkButton *, gpointer);
164 static void aframe_ok_cb(GtkButton *, gpointer);
165 static void astz_proc(GtkAction *action);
166 static void base_cb(GtkToggleButton *, gpointer);
167 static void cell_edited(GtkCellRendererText *,
168 const gchar *, const gchar *, gpointer);
169 static void create_con_fun_menu(enum menu_type);
170 static void create_menu_item_with_markup(char *, int, int);
171 static void die_cb(GnomeClient *client, gpointer data);
172 static void disp_cb(GtkToggleButton *, gpointer);
173 static void hyp_cb(GtkToggleButton *, gpointer);
174 static void inv_cb(GtkToggleButton *, gpointer);
175 static void mb_proc(GtkAction *action);
176 static void mb_acc_radio_proc(GtkAction *action, GtkRadioAction *current);
177 static void mb_base_radio_proc(GtkAction *action, GtkRadioAction *current);
178 static void menu_pos_func(GtkMenu *, gint *, gint *, gboolean *, gpointer);
179 static void menu_proc_cb(GtkMenuItem *, gpointer);
180 static void mstz_proc(GtkAction *action);
181 static void new_cf_value(GtkMenuItem *, gpointer);
182 static void put_constant(int, char *, char *);
183 static void put_function(int, char *, char *);
184 static void quit_cb(GtkWidget *, gpointer);
185 static void reset_mode_values(enum mode_type);
186 static void set_button_state(GtkWidget *, int);
187 static void set_gcalctool_icon(void);
188 static void set_memory_toggle(int);
189 static void set_show_tsep_toggle(int);
190 static void set_show_zeroes_toggle(int);
191 static void show_precision_frame();
192 static void spframe_cancel_cb(GtkButton *, gpointer);
193 static void spframe_ok_cb(GtkButton *, gpointer);
194 static void trig_cb(GtkToggleButton *, gpointer);
195 static void ts_proc(GtkAction *action);
196 static void gcalc_window_have_icons_notify(GConfClient *, guint,
197 GConfEntry *, gpointer);
198 static void gcalc_window_get_menu_items(XVars);
199 static void gcalc_window_set_unset_image(gboolean);
201 #define MENU_KEY_DIR "/desktop/gnome/interface"
203 static GSList *list;
204 static XVars X;
206 /* Menubar menus. */
208 static GtkActionEntry entries[] = {
209 { "CalculatorMenu", NULL, N_("_Calculator") },
210 { "EditMenu", NULL, N_("_Edit") },
211 { "ViewMenu", NULL, N_("_View") },
212 { "HelpMenu", NULL, N_("_Help") },
214 { "Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q",
215 N_("Quit the calculator"), G_CALLBACK(mb_proc) },
217 { "Copy", GTK_STOCK_COPY, N_("_Copy"), NULL,
218 N_("Copy selection"), G_CALLBACK(mb_proc) },
219 { "Paste", GTK_STOCK_PASTE, N_("_Paste"), NULL,
220 N_("Paste selection"), G_CALLBACK(mb_proc) },
221 { "Insert", NULL, N_("_Insert ASCII Value..."), "<control>I",
222 N_("Insert ASCII value"), G_CALLBACK(mb_proc) },
224 { "Contents", GTK_STOCK_HELP, N_("_Contents"), "F1",
225 N_("Show help contents"), G_CALLBACK(mb_proc) },
226 { "About", GNOME_STOCK_ABOUT, N_("_About"), NULL,
227 N_("Show the About Gcalctool dialog"), G_CALLBACK(about_cb) },
229 { "LSPlaces1", NULL, N_("1 place"), NULL,
230 N_("1 place"), G_CALLBACK(mb_proc) },
231 { "LSPlaces2", NULL, N_("2 places"), NULL,
232 N_("2 places"), G_CALLBACK(mb_proc) },
233 { "LSPlaces3", NULL, N_("3 places"), NULL,
234 N_("3 places"), G_CALLBACK(mb_proc) },
235 { "LSPlaces4", NULL, N_("4 places"), NULL,
236 N_("4 places"), G_CALLBACK(mb_proc) },
237 { "LSPlaces5", NULL, N_("5 places"), NULL,
238 N_("5 places"), G_CALLBACK(mb_proc) },
239 { "LSPlaces6", NULL, N_("6 places"), NULL,
240 N_("6 places"), G_CALLBACK(mb_proc) },
241 { "LSPlaces7", NULL, N_("7 places"), NULL,
242 N_("7 places"), G_CALLBACK(mb_proc) },
243 { "LSPlaces8", NULL, N_("8 places"), NULL,
244 N_("8 places"), G_CALLBACK(mb_proc) },
245 { "LSPlaces9", NULL, N_("9 places"), NULL,
246 N_("9 places"), G_CALLBACK(mb_proc) },
247 { "LSPlaces10", NULL, N_("10 places"), NULL,
248 N_("10 places"), G_CALLBACK(mb_proc) },
249 { "LSPlaces11", NULL, N_("11 places"), NULL,
250 N_("11 places"), G_CALLBACK(mb_proc) },
251 { "LSPlaces12", NULL, N_("12 places"), NULL,
252 N_("12 places"), G_CALLBACK(mb_proc) },
253 { "LSPlaces13", NULL, N_("13 places"), NULL,
254 N_("13 places"), G_CALLBACK(mb_proc) },
255 { "LSPlaces14", NULL, N_("14 places"), NULL,
256 N_("14 places"), G_CALLBACK(mb_proc) },
257 { "LSPlaces15", NULL, N_("15 places"), NULL,
258 N_("15 places"), G_CALLBACK(mb_proc) },
260 { "RSPlaces1", NULL, N_("1 place"), NULL,
261 N_("1 place"), G_CALLBACK(mb_proc) },
262 { "RSPlaces2", NULL, N_("2 places"), NULL,
263 N_("2 places"), G_CALLBACK(mb_proc) },
264 { "RSPlaces3", NULL, N_("3 places"), NULL,
265 N_("3 places"), G_CALLBACK(mb_proc) },
266 { "RSPlaces4", NULL, N_("4 places"), NULL,
267 N_("4 places"), G_CALLBACK(mb_proc) },
268 { "RSPlaces5", NULL, N_("5 places"), NULL,
269 N_("5 places"), G_CALLBACK(mb_proc) },
270 { "RSPlaces6", NULL, N_("6 places"), NULL,
271 N_("6 places"), G_CALLBACK(mb_proc) },
272 { "RSPlaces7", NULL, N_("7 places"), NULL,
273 N_("7 places"), G_CALLBACK(mb_proc) },
274 { "RSPlaces8", NULL, N_("8 places"), NULL,
275 N_("8 places"), G_CALLBACK(mb_proc) },
276 { "RSPlaces9", NULL, N_("9 places"), NULL,
277 N_("9 places"), G_CALLBACK(mb_proc) },
278 { "RSPlaces10", NULL, N_("10 places"), NULL,
279 N_("10 places"), G_CALLBACK(mb_proc) },
280 { "RSPlaces11", NULL, N_("11 places"), NULL,
281 N_("11 places"), G_CALLBACK(mb_proc) },
282 { "RSPlaces12", NULL, N_("12 places"), NULL,
283 N_("12 places"), G_CALLBACK(mb_proc) },
284 { "RSPlaces13", NULL, N_("13 places"), NULL,
285 N_("13 places"), G_CALLBACK(mb_proc) },
286 { "RSPlaces14", NULL, N_("14 places"), NULL,
287 N_("14 places"), G_CALLBACK(mb_proc) },
288 { "RSPlaces15", NULL, N_("15 places"), NULL,
289 N_("15 places"), G_CALLBACK(mb_proc) },
291 static guint n_entries = G_N_ELEMENTS(entries);
293 static GtkToggleActionEntry toggle_entries[] = {
294 { "Trailing", NULL, N_("Show _Trailing Zeroes"), "<control>T",
295 N_("Show trailing zeroes"), G_CALLBACK(mstz_proc), FALSE },
296 { "Thousands", NULL, N_("Show T_housands Separator"), "<control>K",
297 N_("Show thousands separator"), G_CALLBACK(ts_proc), FALSE },
298 { "Memory", NULL, N_("_Memory Registers"), "<control>M",
299 N_("Show memory registers"), G_CALLBACK(mb_proc), FALSE },
300 { "Show", NULL, N_("Show _Trailing Zeroes"), "<control>T",
301 N_("Show trailing zeroes"), G_CALLBACK(astz_proc), FALSE },
302 { "ArithmeticPrecedence", NULL, N_("_Use Arithmetic Precedence"), "<control>U",
303 N_("Use Arithmetic Precedence"), G_CALLBACK(mb_proc), FALSE },
305 static guint n_toggle_entries = G_N_ELEMENTS(toggle_entries);
307 static GtkRadioActionEntry acc_radio_entries[] = {
308 { "SP0", NULL, N_("_0 significant places"), "<control>0",
309 N_("0 significant places"), '0' },
310 { "SP1", NULL, N_("_1 significant place"), "<control>1",
311 N_("1 significant place"), '1' },
312 { "SP2", NULL, N_("_2 significant places"), "<control>2",
313 N_("2 significant places"), '2' },
314 { "SP3", NULL, N_("_3 significant places"), "<control>3",
315 N_("3 significant places"), '3' },
316 { "SP4", NULL, N_("_4 significant places"), "<control>4",
317 N_("4 significant places"), '4' },
318 { "SP5", NULL, N_("_5 significant places"), "<control>5",
319 N_("5 significant places"), '5' },
320 { "SP6", NULL, N_("_6 significant places"), "<control>6",
321 N_("6 significant places"), '6' },
322 { "SP7", NULL, N_("_7 significant places"), "<control>7",
323 N_("7 significant places"), '7' },
324 { "SP8", NULL, N_("_8 significant places"), "<control>8",
325 N_("8 significant places"), '8' },
326 { "SP9", NULL, N_("_9 significant places"), "<control>9",
327 N_("9 significant places"), '9' },
328 { "SPOther", NULL, N_("_Other (10) ..."), "<control>O",
329 N_("Set other precision"), 'O' },
331 static guint n_acc_radio_entries = G_N_ELEMENTS(acc_radio_entries);
333 static GtkRadioActionEntry base_radio_entries[] = {
334 { "Basic", NULL, N_("_Basic mode"), "<control>B",
335 N_("Basic mode"), M_BASIC },
336 { "Advanced", NULL, N_("_Advanced mode"), "<control>A",
337 N_("Advanced mode"), M_ADV },
338 { "Financial", NULL, N_("_Financial mode"), "<control>F",
339 N_("Financial mode"), M_FIN },
340 { "Scientific", NULL, N_("_Scientific mode"), "<control>S",
341 N_("Scientific mode"), M_SCI },
344 static guint n_base_radio_entries = G_N_ELEMENTS(base_radio_entries);
346 static const gchar *ui_info =
347 "<ui>"
348 " <menubar name='MenuBar'>"
349 " <menu action='CalculatorMenu'>"
350 " <menuitem action='Quit'/>"
351 " </menu>"
352 " <menu action='EditMenu'>"
353 " <menuitem action='Copy'/>"
354 " <menuitem action='Paste'/>"
355 " <separator/>"
356 " <menuitem action='Insert'/>"
357 " </menu>"
358 " <menu action='ViewMenu'>"
359 " <menuitem action='Basic'/>"
360 " <menuitem action='Advanced'/>"
361 " <menuitem action='Financial'/>"
362 " <menuitem action='Scientific'/>"
363 " <separator/>"
364 " <menuitem action='Trailing'/>"
365 " <menuitem action='Thousands'/>"
366 " <separator/>"
367 " <menuitem action='Memory'/>"
368 " <separator/>"
369 " <menuitem action='ArithmeticPrecedence'/>"
370 " </menu>"
371 " <menu action='HelpMenu'>"
372 " <menuitem action='Contents'/>"
373 " <menuitem action='About'/>"
374 " </menu>"
375 " </menubar>"
376 " <popup name='AccMenu'>"
377 " <menuitem action='SP0'/>"
378 " <menuitem action='SP1'/>"
379 " <menuitem action='SP2'/>"
380 " <menuitem action='SP3'/>"
381 " <menuitem action='SP4'/>"
382 " <menuitem action='SP5'/>"
383 " <menuitem action='SP6'/>"
384 " <menuitem action='SP7'/>"
385 " <menuitem action='SP8'/>"
386 " <menuitem action='SP9'/>"
387 " <menuitem action='SPOther'/>"
388 " <separator/>"
389 " <menuitem action='Show'/>"
390 " </popup>"
391 " <popup name='LeftShiftMenu'>"
392 " <menuitem action='LSPlaces1'/>"
393 " <menuitem action='LSPlaces2'/>"
394 " <menuitem action='LSPlaces3'/>"
395 " <menuitem action='LSPlaces4'/>"
396 " <menuitem action='LSPlaces5'/>"
397 " <menuitem action='LSPlaces6'/>"
398 " <menuitem action='LSPlaces7'/>"
399 " <menuitem action='LSPlaces8'/>"
400 " <menuitem action='LSPlaces9'/>"
401 " <menuitem action='LSPlaces10'/>"
402 " <menuitem action='LSPlaces11'/>"
403 " <menuitem action='LSPlaces12'/>"
404 " <menuitem action='LSPlaces13'/>"
405 " <menuitem action='LSPlaces14'/>"
406 " <menuitem action='LSPlaces15'/>"
407 " </popup>"
408 " <popup name='RightShiftMenu'>"
409 " <menuitem action='RSPlaces1'/>"
410 " <menuitem action='RSPlaces2'/>"
411 " <menuitem action='RSPlaces3'/>"
412 " <menuitem action='RSPlaces4'/>"
413 " <menuitem action='RSPlaces5'/>"
414 " <menuitem action='RSPlaces6'/>"
415 " <menuitem action='RSPlaces7'/>"
416 " <menuitem action='RSPlaces8'/>"
417 " <menuitem action='RSPlaces9'/>"
418 " <menuitem action='RSPlaces10'/>"
419 " <menuitem action='RSPlaces11'/>"
420 " <menuitem action='RSPlaces12'/>"
421 " <menuitem action='RSPlaces13'/>"
422 " <menuitem action='RSPlaces14'/>"
423 " <menuitem action='RSPlaces15'/>"
424 " </popup>"
425 "</ui>";
429 main(int argc, char **argv)
431 char name[MAXLINE]; /* Full name of users .gcalctoolrc file. */
432 struct passwd *entry;
433 GnomeClient *client;
435 v = (Vars) LINT_CAST(calloc(1, sizeof(struct calcVars)));
436 X = (XVars) LINT_CAST(calloc(1, sizeof(struct Xobject)));
438 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
439 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
440 textdomain(GETTEXT_PACKAGE);
442 gnome_program_init("gcalctool", VERSION, LIBGNOMEUI_MODULE, argc, argv,
443 NULL, NULL, NULL);
445 X->lnp = get_localized_numeric_point();
447 /* Connect to the die signal. */
448 client = gnome_master_client();
449 g_signal_connect(client, "die", G_CALLBACK(die_cb), NULL);
451 gtk_rc_get_default_files();
452 if ((v->home = getenv("HOME")) == NULL) {
453 if ((entry = getpwuid(getuid())) != NULL) {
454 v->home = entry->pw_dir;
457 SPRINTF(name, "%s/%s", v->home, RCNAME);
458 gtk_rc_parse(name);
460 X->kbd_accel = gtk_accel_group_new();
461 X->tips = gtk_tooltips_new();
462 X->dpy = GDK_DISPLAY();
463 set_gcalctool_icon();
465 do_calctool(argc, argv);
467 return(0);
471 void
472 update_statusbar(gchar *text, const gchar *imagename)
474 GtkImage *image = GTK_IMAGE(X->status_image);
476 assert(text);
477 assert(imagename);
478 assert(image);
480 gtk_image_set_from_stock(image, imagename, GTK_ICON_SIZE_BUTTON);
481 gtk_statusbar_pop(GTK_STATUSBAR(X->statusbar), 0);
482 gtk_statusbar_push(GTK_STATUSBAR(X->statusbar), 0, text);
486 /*ARGSUSED*/
487 static void
488 about_cb(GtkAction *action)
490 static GtkWidget *about = NULL;
492 if (about == NULL) {
493 const gchar *authors[] = {
494 "Rich Burridge <rich.burridge@sun.com>",
495 "Sami Pietila <sampie@ariana-dsl.utu.fi>",
496 NULL
498 const gchar *documenters[] = {
499 "Sun Microsystems",
500 NULL
502 const gchar *translator_credits = _("translator_credits");
504 about = gnome_about_new(_("Gcalctool"),
505 VERSION,
506 "(C) 2004 the Free Software Foundation",
507 _("Calculator with financial and scientific modes."),
508 authors,
509 documenters,
510 strcmp(translator_credits, "translator_credits") != 0 ?
511 translator_credits : NULL,
512 X->icon);
514 g_signal_connect(G_OBJECT(about), "destroy",
515 G_CALLBACK(gtk_widget_destroyed), &about);
516 gtk_window_set_icon(GTK_WINDOW(about), X->icon);
518 gtk_window_present(GTK_WINDOW(about));
522 static void
523 add_cf_column(GtkTreeView *treeview, gchar *name, gint colno, gboolean editable)
525 GtkCellRenderer *renderer;
526 GtkTreeModel *model = gtk_tree_view_get_model(treeview);
528 renderer = gtk_cell_renderer_text_new();
529 if (editable) {
530 g_signal_connect(G_OBJECT(renderer), "edited",
531 G_CALLBACK(cell_edited), model);
533 g_object_set_data(G_OBJECT(renderer), "column", (gint *) colno);
535 if (editable) {
536 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
537 -1, name, renderer,
538 "text", colno,
539 "editable", COLUMN_EDITABLE,
540 NULL);
541 } else {
542 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
543 -1, name, renderer,
544 "text", colno,
545 NULL);
549 /*ARGSUSED*/
550 static void
551 aframe_cancel_cb(GtkButton *button, gpointer user_data)
553 gtk_widget_hide(X->aframe);
557 /*ARGSUSED*/
558 static gboolean
559 aframe_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
561 g_return_val_if_fail(GTK_IS_WIDGET(widget), FALSE);
563 if (event->keyval == GDK_Escape) {
564 gtk_widget_hide(X->aframe);
567 return(FALSE);
571 /*ARGSUSED*/
572 static void
573 aframe_ok_cb(GtkButton *button, gpointer user_data)
575 char *ch;
576 int val;
578 ch = (char *) gtk_entry_get_text(GTK_ENTRY(X->aframe_ch));
579 val = ch[0];
580 mpcim(&val, v->MPdisp_val);
581 show_display(v->MPdisp_val);
582 gtk_widget_hide(X->aframe);
586 /*ARGSUSED*/
587 static void
588 astz_proc(GtkAction *action)
590 GtkWidget *mi;
592 if (!v->doing_mi) {
593 v->show_zeroes = !v->show_zeroes;
594 v->doing_mi = 1;
595 mi = gtk_ui_manager_get_widget(X->ui, "/MenuBar/ViewMenu/Trailing");
596 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi), v->show_zeroes);
597 v->doing_mi = 0;
599 syntaxdep_show_display(); //show_display(v->MPdisp_val);
600 put_resource(R_ZEROES, set_bool(v->show_zeroes == TRUE));
601 make_registers();
606 /*ARGSUSED*/
607 static void
608 base_cb(GtkToggleButton *button, gpointer user_data)
610 do_base((enum base_type) g_object_get_data(G_OBJECT(button), "base"));
614 void
615 beep()
617 gdk_beep();
621 /*ARGSUSED*/
622 static void
623 button_proc(GtkButton *widget, gpointer user_data)
625 struct button *n;
627 n = (struct button *) g_object_get_data(G_OBJECT(widget), "button");
629 switch (v->syntax) {
630 case npa:
631 if (v->pending) {
632 if (v->current != NULL) {
633 free(v->current);
635 v->current = copy_button_info(n);
636 do_pending();
637 } else {
638 process_item(n);
640 if (v->new_input && v->dtype == FIX) {
641 STRCPY(v->fnum, v->display);
642 set_display(v->fnum, FALSE);
644 break;
646 case exprs:
647 v->current = copy_button_info(n);
648 do_expression();
649 break;
651 default:
652 assert(0);
657 static void
658 cell_edited(GtkCellRendererText *cell, const gchar *path_string,
659 const gchar *new_text, gpointer data)
661 GtkTreeModel *model = (GtkTreeModel *) data;
662 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
663 GArray *entries = (GArray *) g_object_get_data(G_OBJECT(model), "entries");
664 GtkTreeIter iter;
665 gchar *old_text;
666 gint *column, i;
668 column = g_object_get_data(G_OBJECT(cell), "column");
670 gtk_tree_model_get_iter(model, &iter, path);
672 switch (GPOINTER_TO_INT(column)) {
673 case COLUMN_VALUE:
674 gtk_tree_model_get(model, &iter, column, &old_text, -1);
675 g_free(old_text);
677 i = gtk_tree_path_get_indices(path)[0];
678 g_free(g_array_index(entries, CF_Item, i).value);
679 g_array_index(entries, CF_Item, i).value = g_strdup(new_text);
680 gtk_list_store_set(GTK_LIST_STORE(model), &iter, column,
681 g_array_index(entries, CF_Item, i).value, -1);
682 break;
684 case COLUMN_DESCRIPTION:
685 gtk_tree_model_get(model, &iter, column, &old_text, -1);
686 g_free(old_text);
688 i = gtk_tree_path_get_indices(path)[0];
689 g_free(g_array_index(entries, CF_Item, i).description);
690 g_array_index(entries, CF_Item, i).description = g_strdup(new_text);
691 gtk_list_store_set(GTK_LIST_STORE(model), &iter, column,
692 g_array_index(entries, CF_Item, i).description, -1);
693 break;
696 gtk_tree_path_free(path);
700 /*ARGSUSED*/
701 static void
702 cfframe_response_cb(GtkDialog *dialog, gint id, gpointer data)
704 CF_Item item;
705 int i;
706 enum menu_type mtype = (enum menu_type)
707 g_object_get_data(G_OBJECT(dialog), "mtype");
708 GArray *entries = (GArray *) g_object_get_data(G_OBJECT(dialog), "entries");
710 if (id == GTK_RESPONSE_HELP) {
711 GError *error = NULL;
713 gnome_help_display_desktop(NULL, "gcalctool", "gcalctool",
714 NULL, &error);
716 if (error) {
717 GtkWidget *d;
719 d = gtk_message_dialog_new(NULL,
720 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
721 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
722 error->message);
723 gtk_dialog_run(GTK_DIALOG(d));
724 gtk_widget_destroy(d);
725 g_error_free(error);
726 error = NULL;
728 return;
731 if (id == GTK_RESPONSE_ACCEPT) {
732 for (i = 0; i < MAXCONFUN; i++) {
733 item = g_array_index(entries, CF_Item, i);
735 if (mtype == M_CON) {
736 MPstr_to_num(item.value, DEC, v->MPcon_vals[i]);
737 STRCPY(v->con_names[i], item.description);
738 put_constant(i, item.value, item.description);
739 } else {
740 STRCPY(v->fun_vals[i], convert(item.value));
741 SPRINTF(v->fun_names[i], item.description);
742 put_function(i, item.value, item.description);
746 create_con_fun_menu(mtype);
749 gtk_widget_destroy(GTK_WIDGET(dialog));
750 if (mtype == M_CON) {
751 X->con_dialog = NULL;
752 } else {
753 X->fun_dialog = NULL;
758 static void
759 create_aframe() /* Create auxiliary frame for ASC key. */
761 GtkWidget *vbox, *hbox, *button_hbox, *label;
762 GtkWidget *insert_button, *cancel_button;
764 X->aframe = gtk_window_new(GTK_WINDOW_TOPLEVEL);
765 gtk_window_set_title(GTK_WINDOW(X->aframe), _("Insert ASCII Value"));
766 gtk_window_set_resizable(GTK_WINDOW(X->aframe), FALSE);
767 gtk_window_set_transient_for(GTK_WINDOW(X->aframe), GTK_WINDOW(X->kframe));
768 gtk_window_set_type_hint(GTK_WINDOW(X->aframe),
769 GDK_WINDOW_TYPE_HINT_DIALOG);
771 vbox = gtk_vbox_new(FALSE, 12);
772 gtk_widget_show(vbox);
773 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
774 gtk_container_add(GTK_CONTAINER(X->aframe), vbox);
776 hbox = gtk_hbox_new(FALSE, 6);
777 gtk_widget_show(hbox);
778 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
780 label = gtk_label_new_with_mnemonic(_("Ch_aracter:"));
781 gtk_widget_show(label);
782 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
783 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
785 X->aframe_ch = gtk_entry_new();
786 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(X->aframe_ch));
787 gtk_entry_set_max_length(GTK_ENTRY(X->aframe_ch), 1);
788 gtk_widget_show(X->aframe_ch);
789 gtk_box_pack_start(GTK_BOX(hbox), X->aframe_ch,
790 FALSE, FALSE, 0);
792 button_hbox = gtk_hbutton_box_new();
793 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
794 gtk_widget_ref(button_hbox);
795 gtk_widget_show(button_hbox);
796 gtk_box_pack_start(GTK_BOX(vbox), button_hbox, TRUE, TRUE, 0);
797 gtk_box_set_spacing(GTK_BOX(button_hbox), 12);
799 cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
800 GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
801 gtk_widget_ref(cancel_button);
802 gtk_widget_show(cancel_button);
803 gtk_box_pack_start(GTK_BOX(button_hbox), cancel_button, FALSE, FALSE, 0);
805 insert_button = gtk_button_new_with_mnemonic(_("_Insert"));
806 g_return_if_fail(insert_button != NULL);
807 gtk_widget_ref(insert_button);
808 gtk_widget_show(insert_button);
809 GTK_WIDGET_SET_FLAGS(insert_button, GTK_CAN_DEFAULT);
810 gtk_window_set_default(GTK_WINDOW(X->aframe), insert_button);
811 gtk_box_pack_start(GTK_BOX(button_hbox), insert_button, FALSE, FALSE, 0);
813 g_signal_connect(G_OBJECT(X->aframe), "delete_event",
814 G_CALLBACK(dismiss_aframe), NULL);
815 g_signal_connect(G_OBJECT(X->aframe_ch), "activate",
816 G_CALLBACK(aframe_ok_cb), NULL);
817 g_signal_connect(G_OBJECT(insert_button), "clicked",
818 G_CALLBACK(aframe_ok_cb), NULL);
819 g_signal_connect(G_OBJECT(cancel_button), "clicked",
820 G_CALLBACK(aframe_cancel_cb), NULL);
821 g_signal_connect(G_OBJECT(X->aframe), "key_press_event",
822 G_CALLBACK(aframe_key_cb), NULL);
823 gtk_widget_realize(X->aframe);
827 static GtkTreeModel *
828 create_cf_model(enum menu_type mtype, GtkWidget *dialog)
830 gint i = 0;
831 CF_Item n;
832 GtkListStore *model;
833 GtkTreeIter iter;
834 GArray *entries = g_array_sized_new(FALSE, FALSE, sizeof(CF_Item), 1);
836 for (i = 0; i < MAXCONFUN; i++) {
837 n.number = i;
838 if (mtype == M_CON) {
839 n.value = g_strdup(make_number(v->MPcon_vals[i], DEC, FALSE, TRUE));
840 n.description = g_strdup(v->con_names[i]);
841 } else {
842 n.value = g_strdup(v->fun_vals[i]);
843 n.description = g_strdup(v->fun_names[i]);
845 n.editable = TRUE;
846 g_array_append_vals(entries, &n, 1);
849 model = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING,
850 G_TYPE_STRING, G_TYPE_BOOLEAN);
852 for (i = 0; i < entries->len; i++) {
853 gtk_list_store_append(model, &iter);
855 gtk_list_store_set(model, &iter,
856 COLUMN_NUMBER,
857 g_array_index(entries, CF_Item, i).number,
858 COLUMN_VALUE,
859 g_array_index(entries, CF_Item, i).value,
860 COLUMN_DESCRIPTION,
861 g_array_index(entries, CF_Item, i).description,
862 COLUMN_EDITABLE,
863 g_array_index(entries, CF_Item, i).editable,
864 -1);
866 g_object_set_data(G_OBJECT(model), "entries", (gpointer) entries);
867 g_object_set_data(G_OBJECT(dialog), "entries", (gpointer) entries);
869 return(GTK_TREE_MODEL(model));
873 /* Create popup window for editing constants/functions. */
875 static GtkWidget *
876 create_cfframe(enum menu_type mtype, GtkWidget *dialog)
878 const gchar *title;
879 GdkGeometry geometry;
880 GtkTreeModel *model;
881 GtkWidget *label, *sw, *treeview, *vbox;
882 gchar *str;
884 title = (mtype == M_CON) ? _("Edit Constants") : _("Edit Functions");
885 geometry.min_width = 380;
886 geometry.min_height = 300;
887 if (dialog == NULL) {
888 dialog = gtk_dialog_new_with_buttons(title, NULL,
889 GTK_DIALOG_DESTROY_WITH_PARENT,
890 GTK_STOCK_HELP, GTK_RESPONSE_HELP,
891 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
892 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
893 NULL);
895 g_object_set_data(G_OBJECT(dialog), "mtype", (gpointer) mtype);
896 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
897 GTK_RESPONSE_ACCEPT);
898 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
899 gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
900 gtk_window_set_resizable(GTK_WINDOW(dialog), TRUE);
901 gtk_window_set_transient_for(GTK_WINDOW(dialog),
902 GTK_WINDOW(X->kframe));
903 gtk_window_set_geometry_hints(GTK_WINDOW(dialog), dialog,
904 &geometry, GDK_HINT_MIN_SIZE);
905 vbox = gtk_vbox_new(FALSE, 6);
906 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
908 str = g_strconcat("<small><i><b>", _("Note:"), "</b> ",
909 _("All constant values are specified in the decimal numeric base."),
910 "</i></small>", NULL);
911 label = gtk_label_new(_(str));
912 g_free(str);
913 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
914 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
915 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
916 gtk_box_pack_end(GTK_BOX(vbox), label, FALSE, FALSE, 0);
918 label = gtk_label_new_with_mnemonic(
919 _("Click a _value or description to edit it:"));
920 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
921 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
922 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
924 sw = gtk_scrolled_window_new(NULL, NULL);
925 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
926 GTK_SHADOW_NONE);
927 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
928 GTK_POLICY_AUTOMATIC,
929 GTK_POLICY_NEVER);
930 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
932 model = create_cf_model(mtype, dialog);
934 treeview = gtk_tree_view_new_with_model(model);
935 gtk_label_set_mnemonic_widget(GTK_LABEL(label), treeview);
936 g_object_unref(model);
937 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
938 gtk_tree_selection_set_mode(
939 gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)),
940 GTK_SELECTION_SINGLE);
942 add_cf_column(GTK_TREE_VIEW(treeview), _("No."),
943 COLUMN_NUMBER, FALSE);
944 add_cf_column(GTK_TREE_VIEW(treeview), _("Value"),
945 COLUMN_VALUE, TRUE);
946 add_cf_column(GTK_TREE_VIEW(treeview), _("Description"),
947 COLUMN_DESCRIPTION, TRUE);
949 gtk_container_add(GTK_CONTAINER(sw), treeview);
951 g_signal_connect(G_OBJECT(dialog), "response",
952 G_CALLBACK(cfframe_response_cb), (gpointer) model);
954 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
956 gtk_widget_show_all(dialog);
958 return(dialog);
962 static void
963 create_spframe() /* Create auxiliary frame for Set Precision value. */
965 GtkWidget *vbox, *hbox, *button_hbox, *label;
966 GtkWidget *set_button, *cancel_button;
968 X->spframe = gtk_window_new(GTK_WINDOW_TOPLEVEL);
969 gtk_window_set_title(GTK_WINDOW(X->spframe), _("Set Precision"));
970 gtk_window_set_resizable(GTK_WINDOW(X->spframe), FALSE);
971 gtk_window_set_transient_for(GTK_WINDOW(X->spframe), GTK_WINDOW(X->kframe));
972 gtk_window_set_type_hint(GTK_WINDOW(X->spframe),
973 GDK_WINDOW_TYPE_HINT_DIALOG);
975 vbox = gtk_vbox_new(FALSE, 12);
976 gtk_widget_show(vbox);
977 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
978 gtk_container_add(GTK_CONTAINER(X->spframe), vbox);
980 hbox = gtk_hbox_new(FALSE, 6);
981 gtk_widget_show(hbox);
982 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
984 label = gtk_label_new_with_mnemonic(_("Significant _places:"));
985 gtk_widget_show(label);
986 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
987 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
989 X->spframe_val = gtk_spin_button_new_with_range(0, MAXACC, 1);
990 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(X->spframe_val),
991 GTK_UPDATE_IF_VALID);
992 gtk_spin_button_set_value(GTK_SPIN_BUTTON(X->spframe_val),
993 (double) v->accuracy);
994 gtk_widget_show(X->spframe_val);
995 gtk_box_pack_start(GTK_BOX(hbox), X->spframe_val, FALSE, FALSE, 0);
997 button_hbox = gtk_hbutton_box_new();
998 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
999 gtk_widget_ref(button_hbox);
1000 gtk_widget_show(button_hbox);
1001 gtk_box_pack_start(GTK_BOX(vbox), button_hbox, TRUE, TRUE, 0);
1002 gtk_box_set_spacing(GTK_BOX(button_hbox), 12);
1004 cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1005 GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
1006 gtk_widget_ref(cancel_button);
1007 gtk_widget_show(cancel_button);
1008 gtk_box_pack_start(GTK_BOX(button_hbox), cancel_button, FALSE, FALSE, 0);
1010 set_button = gtk_button_new_with_mnemonic(_("_Set"));
1011 g_return_if_fail(set_button != NULL);
1012 gtk_widget_ref(set_button);
1013 gtk_widget_show(set_button);
1014 GTK_WIDGET_SET_FLAGS(set_button, GTK_CAN_DEFAULT);
1015 gtk_window_set_default(GTK_WINDOW(X->spframe), set_button);
1016 gtk_box_pack_start(GTK_BOX(button_hbox), set_button, FALSE, FALSE, 0);
1018 g_signal_connect(G_OBJECT(X->spframe), "delete_event",
1019 G_CALLBACK(dismiss_spframe), NULL);
1020 g_signal_connect(G_OBJECT(X->spframe), "key_press_event",
1021 G_CALLBACK(spframe_key_cb), NULL);
1022 g_signal_connect(G_OBJECT(set_button), "clicked",
1023 G_CALLBACK(spframe_ok_cb), NULL);
1024 g_signal_connect(G_OBJECT(cancel_button), "clicked",
1025 G_CALLBACK(spframe_cancel_cb), NULL);
1026 gtk_widget_realize(X->spframe);
1030 /* action_image[] is a list of Actions which are having icons associated.
1031 * We need to set/unset the icons if /desktop/gnome/interface/menus_have_icons
1032 * toggles.
1035 static void
1036 gcalc_window_get_menu_items(XVars X)
1038 GtkAction *act;
1039 GSList *p = NULL;
1040 gint i = 0;
1041 static gchar *action_image[] = { "Quit", "Copy", "Paste",
1042 "Contents", "About", NULL };
1044 while (action_image[i]) {
1045 act = gtk_action_group_get_action (X->actions, action_image[i]);
1046 p = gtk_action_get_proxies (GTK_ACTION (act));
1048 for (; p; p = p->next) {
1049 if (p->data) {
1050 if (GTK_IS_MENU_ITEM (p->data)) {
1051 list = g_slist_append (list, p->data);
1056 i ++;
1061 /*ARGSUSED*/
1062 static void
1063 gcalc_window_have_icons_notify(GConfClient *client, guint cnxn_id,
1064 GConfEntry *entry, gpointer data)
1066 gcalc_window_set_unset_image(gconf_client_get_bool(client,
1067 MENU_KEY_DIR"/menus_have_icons", NULL));
1071 static void
1072 gcalc_window_set_unset_image(gboolean have_icons)
1074 GtkWidget *image;
1075 GSList *temp = list;
1077 while (temp) {
1078 image = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(temp->data));
1080 if (image && ! g_object_get_data(G_OBJECT(temp->data), "saved_image")) {
1081 g_object_set_data_full(G_OBJECT(temp->data), "saved_image",
1082 g_object_ref(image), g_object_unref);
1085 if (!image) {
1086 image = g_object_get_data(G_OBJECT(temp->data), "saved_image");
1089 if (!have_icons) {
1090 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(temp->data),
1091 NULL);
1092 } else {
1093 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(temp->data),
1094 image);
1097 temp = temp->next;
1102 static void
1103 create_kframe()
1105 char *hn;
1106 GError *error;
1107 GtkWidget *event_box, *view_widget;
1108 GtkTextBuffer *buffer;
1110 v->tool_label = NULL;
1111 if (v->titleline == NULL) {
1112 hn = make_hostname(X->dpy);
1113 v->tool_label = malloc(strlen(_("Calculator")) + strlen(hn) + 3);
1115 SPRINTF(v->tool_label, "%s %s", _("Calculator"), hn);
1116 g_free(hn);
1117 } else {
1118 read_str(&v->tool_label, v->titleline);
1121 X->kframe = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1122 g_object_set_data(G_OBJECT(X->kframe), "kframe", X->kframe);
1123 gtk_window_set_resizable(GTK_WINDOW(X->kframe), FALSE);
1125 g_signal_connect(G_OBJECT(X->kframe), "delete_event",
1126 G_CALLBACK(quit_cb), NULL);
1128 X->kvbox = gtk_vbox_new(FALSE, 0);
1129 gtk_widget_ref(X->kvbox);
1130 gtk_container_add(GTK_CONTAINER(X->kframe), X->kvbox);
1131 gtk_widget_show(X->kvbox);
1133 X->actions = gtk_action_group_new("Actions");
1134 gtk_action_group_set_translation_domain (X->actions, NULL);
1135 gtk_action_group_add_actions(X->actions, entries, n_entries, NULL);
1136 gtk_action_group_add_toggle_actions(X->actions,
1137 toggle_entries, n_toggle_entries,
1138 NULL);
1139 gtk_action_group_add_radio_actions(X->actions,
1140 acc_radio_entries, n_acc_radio_entries,
1141 -1, G_CALLBACK(mb_acc_radio_proc),
1142 NULL);
1143 gtk_action_group_add_radio_actions(X->actions,
1144 base_radio_entries, n_base_radio_entries,
1145 M_BASIC, G_CALLBACK(mb_base_radio_proc),
1146 NULL);
1148 X->ui = gtk_ui_manager_new();
1149 gtk_ui_manager_insert_action_group(X->ui, X->actions, 0);
1150 gtk_window_add_accel_group(GTK_WINDOW(X->kframe),
1151 gtk_ui_manager_get_accel_group(X->ui));
1153 if (!gtk_ui_manager_add_ui_from_string(X->ui, ui_info, -1, &error)) {
1154 g_message("Building menus failed: %s", error->message);
1155 g_error_free(error);
1158 X->menubar = gtk_ui_manager_get_widget(X->ui, "/MenuBar"),
1159 gtk_widget_show(X->menubar);
1160 gtk_box_pack_start(GTK_BOX(X->kvbox), X->menubar, FALSE, FALSE, 0);
1163 X->scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
1164 gtk_widget_show(X->scrolledwindow);
1165 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (X->scrolledwindow),
1166 GTK_POLICY_AUTOMATIC,
1167 GTK_POLICY_NEVER);
1170 event_box = gtk_event_box_new();
1171 X->display_item = gtk_text_view_new();
1172 gtk_widget_set_name(X->display_item, "displayitem");
1174 gtk_text_view_set_justification(GTK_TEXT_VIEW(X->display_item),
1175 GTK_JUSTIFY_RIGHT);
1176 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(X->display_item), GTK_WRAP_NONE);
1177 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
1178 gtk_text_buffer_create_tag(buffer, "x-large", "scale", PANGO_SCALE_X_LARGE,
1179 NULL);
1181 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(X->display_item), TRUE);
1182 gtk_text_view_set_editable(GTK_TEXT_VIEW(X->display_item), FALSE);
1183 GTK_WIDGET_SET_FLAGS(X->display_item, GTK_CAN_FOCUS);
1185 gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(X->display_item), 8);
1186 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(X->display_item), 8);
1187 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(X->display_item), 6);
1189 gtk_container_add(GTK_CONTAINER(X->scrolledwindow), X->display_item);
1190 atk_object_set_role(gtk_widget_get_accessible(X->display_item),
1191 ATK_ROLE_EDITBAR);
1192 set_display("0.00", FALSE);
1194 gtk_widget_ref(X->display_item);
1195 gtk_container_set_border_width(GTK_CONTAINER(X->display_item), 2);
1196 gtk_container_add(GTK_CONTAINER(event_box), X->scrolledwindow);
1197 gtk_widget_show(X->display_item);
1198 gtk_box_pack_start(GTK_BOX(X->kvbox), event_box, FALSE, TRUE, 0);
1199 gtk_widget_show(event_box);
1201 gtk_widget_realize(X->kframe);
1202 gtk_window_set_title(GTK_WINDOW(X->kframe), _(v->tool_label));
1204 X->fin_panel = make_but_panel(X->kvbox, X->fin_buttons,
1205 f_buttons, FROWS, FCOLS, "fin");
1207 X->mode_panel = create_mode_panel(X->kvbox);
1209 X->sci_panel = make_but_panel(X->kvbox, X->sci_buttons,
1210 s_buttons, SROWS, SCOLS, "sci");
1211 set_accuracy_tooltip(v->accuracy);
1213 gtk_widget_show(X->fin_panel);
1214 gtk_widget_show(X->mode_panel);
1215 gtk_widget_show(X->sci_panel);
1217 X->bas_panel = make_but_panel(X->kvbox, X->bas_buttons,
1218 &b_buttons[0], BROWS, BCOLS, "bas");
1219 gtk_widget_show(X->bas_panel);
1221 X->adv_panel = make_but_panel(X->kvbox, X->adv_buttons,
1222 &a_buttons[0], AROWS, ACOLS, "adv");
1223 gtk_widget_show(X->adv_panel);
1224 gtk_window_add_accel_group(GTK_WINDOW(X->kframe), X->kbd_accel);
1225 grey_buttons(v->base);
1226 gtk_window_set_icon(GTK_WINDOW(X->kframe), X->icon);
1227 if (v->modetype == BASIC) {
1228 gtk_window_set_focus(GTK_WINDOW(X->kframe), GTK_WIDGET(BUT_CLR_BAS));
1229 } else {
1230 gtk_window_set_focus(GTK_WINDOW(X->kframe), GTK_WIDGET(BUT_CLR_ADV));
1233 X->khbox = gtk_hbox_new(FALSE, 0);
1234 gtk_widget_show(X->khbox);
1235 gtk_container_add(GTK_CONTAINER(X->kvbox), X->khbox);
1236 X->statusbar = gtk_statusbar_new();
1237 gtk_widget_show(X->statusbar);
1238 gtk_box_pack_start(GTK_BOX(X->khbox), X->statusbar, TRUE, TRUE, 0);
1239 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(X->statusbar), FALSE);
1241 X->status_image = gtk_image_new_from_stock("",
1242 GTK_ICON_SIZE_BUTTON);
1243 gtk_widget_show(X->status_image);
1244 gtk_box_pack_start(GTK_BOX(X->khbox), X->status_image, FALSE, TRUE, 0);
1245 g_signal_connect(G_OBJECT(X->kframe), "key_press_event",
1246 G_CALLBACK(kframe_key_press_cb), NULL);
1248 switch (v->modetype) {
1249 case FINANCIAL:
1250 view_widget = gtk_ui_manager_get_widget(X->ui,
1251 "/MenuBar/ViewMenu/Financial");
1252 break;
1254 case SCIENTIFIC:
1255 view_widget = gtk_ui_manager_get_widget(X->ui,
1256 "/MenuBar/ViewMenu/Scientific");
1257 break;
1259 case ADVANCED:
1260 view_widget = gtk_ui_manager_get_widget(X->ui,
1261 "/MenuBar/ViewMenu/Advanced");
1262 break;
1264 default:
1265 view_widget = gtk_ui_manager_get_widget(X->ui,
1266 "/MenuBar/ViewMenu/Basic");
1267 break;
1270 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(view_widget), TRUE);
1271 gcalc_window_get_menu_items(X);
1273 gconf_client_add_dir(X->client, MENU_KEY_DIR,
1274 GCONF_CLIENT_PRELOAD_NONE, NULL);
1275 gconf_client_notify_add(X->client, MENU_KEY_DIR"/menus_have_icons",
1276 (GConfClientNotifyFunc)
1277 gcalc_window_have_icons_notify,
1278 NULL, NULL, NULL);
1279 gcalc_window_set_unset_image(gconf_client_get_bool(X->client,
1280 MENU_KEY_DIR"/menus_have_icons", NULL));
1282 /* Use loaded Arithmetic Precedence mode setting. */
1283 if (v->syntax == exprs) {
1284 view_widget = gtk_ui_manager_get_widget(X->ui,
1285 "/MenuBar/ViewMenu/ArithmeticPrecedence");
1286 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(view_widget), TRUE);
1291 static void
1292 create_mem_menu(enum menu_type mtype)
1294 char mstr[MAXLINE];
1295 int i, m;
1297 m = (int) mtype;
1298 X->menus[(int) mtype] = gtk_menu_new();
1300 for (i = 0; i < MAXREGS; i++) {
1301 SPRINTF(mstr, "<span weight=\"bold\">%s%d:</span> %s",
1302 /* translators: R is the short form of register used inter alia
1303 in popup menus */
1304 _("R"), i, make_number(v->MPmvals[i], v->base, FALSE, TRUE));
1305 create_menu_item_with_markup(mstr, m, i);
1310 static GtkWidget *
1311 create_mode_panel(GtkWidget *main_vbox)
1313 int i;
1314 AtkObject *access_object;
1315 GtkWidget *base_hbox, *disp_hbox, *trig_hbox;
1316 GtkWidget *row1_hbox, *row2_hbox, *vbox;
1317 GSList *base_gr = NULL;
1318 GSList *disp_gr = NULL;
1319 GSList *trig_gr = NULL;
1321 row1_hbox = gtk_hbox_new(FALSE, 0);
1322 row2_hbox = gtk_hbox_new(FALSE, 0);
1324 vbox = gtk_vbox_new(FALSE, 0);
1325 gtk_widget_ref(vbox);
1326 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
1328 /* Make Trig. type radio button widgets. */
1330 trig_hbox = gtk_hbox_new(FALSE, 0);
1331 gtk_widget_show(trig_hbox);
1333 for (i = 0; i < MAXTRIGMODES; i++) {
1334 X->trig[i] = gtk_radio_button_new_with_mnemonic(NULL, _(ttype_str[i]));
1335 gtk_tooltips_set_tip(X->tips, X->trig[i], _(ttype_desc[i]), "");
1336 g_object_set_data(G_OBJECT(X->trig[i]), "trig", (gpointer) i);
1337 gtk_widget_show(X->trig[i]);
1338 gtk_box_pack_start(GTK_BOX(trig_hbox), X->trig[i], FALSE, FALSE, 0);
1339 gtk_radio_button_set_group(GTK_RADIO_BUTTON(X->trig[i]), trig_gr);
1340 trig_gr = gtk_radio_button_get_group(GTK_RADIO_BUTTON(X->trig[i]));
1341 access_object = gtk_widget_get_accessible(X->trig[i]);
1342 atk_object_set_name(access_object, _(ttype_desc[i]));
1343 g_signal_connect(G_OBJECT(X->trig[i]), "toggled",
1344 G_CALLBACK(trig_cb), NULL);
1347 gtk_box_pack_start(GTK_BOX(row1_hbox), trig_hbox, FALSE, TRUE, 0);
1349 /* Make numeric base radio button widgets. */
1351 base_hbox = gtk_hbox_new(FALSE, 0);
1352 gtk_widget_show(base_hbox);
1354 for (i = 0; i < MAXBASES; i++) {
1355 X->base[i] = gtk_radio_button_new_with_mnemonic(NULL, _(base_str[i]));
1356 gtk_tooltips_set_tip(X->tips, X->base[i], _(base_desc[i]), "");
1357 g_object_set_data(G_OBJECT(X->base[i]), "base", (gpointer) i);
1358 gtk_widget_show(X->base[i]);
1359 gtk_box_pack_start(GTK_BOX(base_hbox), X->base[i], FALSE, FALSE, 0);
1360 gtk_radio_button_set_group(GTK_RADIO_BUTTON(X->base[i]), base_gr);
1361 base_gr = gtk_radio_button_get_group(GTK_RADIO_BUTTON(X->base[i]));
1362 access_object = gtk_widget_get_accessible(X->base[i]);
1363 atk_object_set_name(access_object, _(base_desc[i]));
1364 g_signal_connect(G_OBJECT(X->base[i]), "toggled",
1365 G_CALLBACK(base_cb), NULL);
1368 gtk_box_pack_end(GTK_BOX(row1_hbox), base_hbox, FALSE, TRUE, 0);
1370 /* Make Hyp and Inv trigonometric check boxes. */
1372 X->inv = gtk_check_button_new_with_mnemonic(_("_Inv"));
1373 gtk_tooltips_set_tip(X->tips, X->inv, _(inv_desc), "");
1374 gtk_widget_show(X->inv);
1375 gtk_box_pack_start(GTK_BOX(row2_hbox), X->inv, FALSE, FALSE, 0);
1376 access_object = gtk_widget_get_accessible(X->inv);
1377 atk_object_set_name(access_object, _(inv_desc));
1378 g_signal_connect(G_OBJECT(X->inv), "toggled", G_CALLBACK(inv_cb), NULL);
1380 X->hyp = gtk_check_button_new_with_mnemonic(_("H_yp"));
1381 gtk_tooltips_set_tip(X->tips, X->hyp, _(hyp_desc), "");
1382 gtk_widget_show(X->hyp);
1383 gtk_box_pack_start(GTK_BOX(row2_hbox), X->hyp, FALSE, FALSE, 0);
1384 access_object = gtk_widget_get_accessible(X->hyp);
1385 atk_object_set_name(access_object, _(hyp_desc));
1386 g_signal_connect(G_OBJECT(X->hyp), "toggled", G_CALLBACK(hyp_cb), NULL);
1388 /* Make display type radio button widgets. */
1390 disp_hbox = gtk_hbox_new(FALSE, 0);
1391 gtk_widget_show(disp_hbox);
1393 for (i = 0; i < MAXTRIGMODES; i++) {
1394 X->disp[i] = gtk_radio_button_new_with_mnemonic(NULL, _(dtype_str[i]));
1395 gtk_tooltips_set_tip(X->tips, X->disp[i], _(dtype_desc[i]), "");
1396 g_object_set_data(G_OBJECT(X->disp[i]), "disp", (gpointer) i);
1397 gtk_widget_show(X->disp[i]);
1398 gtk_box_pack_start(GTK_BOX(disp_hbox), X->disp[i], FALSE, FALSE, 0);
1399 gtk_radio_button_set_group(GTK_RADIO_BUTTON(X->disp[i]), disp_gr);
1400 disp_gr = gtk_radio_button_get_group(GTK_RADIO_BUTTON(X->disp[i]));
1401 access_object = gtk_widget_get_accessible(X->disp[i]);
1402 atk_object_set_name(access_object, _(dtype_desc[i]));
1403 g_signal_connect(G_OBJECT(X->disp[i]), "toggled",
1404 G_CALLBACK(disp_cb), NULL);
1407 gtk_box_pack_end(GTK_BOX(row2_hbox), disp_hbox, FALSE, TRUE, 0);
1409 gtk_box_pack_start(GTK_BOX(vbox), row1_hbox, FALSE, FALSE, 0);
1410 gtk_box_pack_start(GTK_BOX(vbox), row2_hbox, FALSE, FALSE, 0);
1411 gtk_box_pack_start(GTK_BOX(main_vbox), vbox, FALSE, TRUE, 0);
1413 return(vbox);
1417 static void
1418 create_rframe()
1420 char line[MAXLINE]; /* Current memory register line. */
1421 char name[MAXLINE];
1422 int i;
1423 GtkWidget *vbox;
1425 X->rframe = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1426 g_object_set_data(G_OBJECT(X->rframe), "rframe", X->rframe);
1427 gtk_window_set_resizable(GTK_WINDOW(X->rframe), TRUE);
1428 gtk_window_set_title(GTK_WINDOW(X->rframe), _("Memory Registers"));
1429 gtk_window_set_icon(GTK_WINDOW(X->rframe), X->icon);
1431 vbox = gtk_vbox_new(FALSE, 0);
1432 gtk_container_add(GTK_CONTAINER(X->rframe), vbox);
1433 gtk_widget_realize(X->rframe);
1435 for (i = 0; i < MAXREGS; i++) {
1436 SPRINTF(line, "<span weight=\"bold\">%s%1d:</span> %s",
1437 _("R"), i, make_number(v->MPmvals[i], v->base, FALSE, TRUE));
1438 X->regs[i] = gtk_label_new("");
1439 gtk_label_set_markup(GTK_LABEL(X->regs[i]), line);
1440 SPRINTF(name, "register_label%1d", i);
1441 gtk_widget_set_name(X->regs[i], name);
1442 gtk_widget_ref(X->regs[i]);
1443 gtk_misc_set_alignment(GTK_MISC(X->regs[i]), 0.0, 0.5);
1444 gtk_misc_set_padding(GTK_MISC(X->regs[i]), 5, 5);
1445 gtk_box_pack_start(GTK_BOX(vbox), X->regs[i], TRUE, TRUE, 0);
1447 gtk_widget_show_all(vbox);
1449 g_signal_connect(G_OBJECT(X->rframe), "delete_event",
1450 G_CALLBACK(dismiss_rframe), NULL);
1454 /*ARGSUSED*/
1455 static void
1456 die_cb(GnomeClient *client, gpointer data)
1458 gtk_main_quit();
1462 /*ARGSUSED*/
1463 static gboolean
1464 dismiss_aframe(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1466 X->aframe = NULL;
1468 return(FALSE);
1472 /*ARGSUSED*/
1473 static gboolean
1474 dismiss_rframe(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1476 set_memory_toggle(FALSE);
1477 put_resource(R_REGS, "false");
1478 gtk_widget_hide(X->rframe);
1480 return(TRUE);
1484 /*ARGSUSED*/
1485 static gboolean
1486 dismiss_spframe(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1488 X->spframe = NULL;
1490 return(FALSE);
1494 static void
1495 create_con_fun_menu(enum menu_type mtype)
1497 char *mstr, mline[MAXLINE];
1498 int i, invalid, m;
1499 GtkWidget *menu_item;
1501 m = (int) mtype;
1502 X->menus[(int) mtype] = gtk_menu_new();
1504 mstr = (mtype == M_CON) ? _("Edit Constants...") : _("Edit Functions...");
1505 menu_item = gtk_menu_item_new_with_label(mstr);
1506 gtk_widget_show(menu_item);
1507 gtk_menu_shell_append(GTK_MENU_SHELL(X->menus[m]), menu_item);
1508 g_signal_connect(G_OBJECT(menu_item), "activate",
1509 G_CALLBACK(new_cf_value), (gpointer) mtype);
1511 for (i = 0; i < MAXCONFUN; i++) {
1512 invalid = 0;
1513 if (mtype == M_CON) {
1514 SPRINTF(mline, "<span weight=\"bold\">%s%1d:</span> %s [%s]",
1515 _("C"), i,
1516 make_number(v->MPcon_vals[i], DEC, FALSE, TRUE),
1517 v->con_names[i]);
1518 } else {
1519 if (!strlen(v->fun_vals[i])) {
1520 invalid = 1;
1521 } else {
1522 SPRINTF(mline, "<span weight=\"bold\">%s%1d:</span> %s [%s]",
1523 _("F"), i, v->fun_vals[i], v->fun_names[i]);
1527 if (!invalid) {
1528 create_menu_item_with_markup(mline, m, i);
1534 static void
1535 create_menu_item_with_markup(char *label, int menu_no, int user_data)
1537 GtkWidget *accel_label;
1538 GtkWidget *menu_item;
1540 accel_label = gtk_accel_label_new("");
1541 gtk_label_set_markup(GTK_LABEL(accel_label), label);
1542 menu_item = gtk_menu_item_new();
1543 gtk_misc_set_alignment(GTK_MISC(accel_label), 0.0, 0.5);
1544 gtk_container_add(GTK_CONTAINER(menu_item), accel_label);
1545 gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(accel_label), menu_item);
1546 gtk_widget_show(accel_label);
1547 gtk_widget_show(menu_item);
1548 g_object_set_data(G_OBJECT(menu_item), "mtype", (gpointer) menu_no);
1549 gtk_menu_shell_append(GTK_MENU_SHELL(X->menus[menu_no]), menu_item);
1550 g_signal_connect(G_OBJECT(menu_item), "activate",
1551 G_CALLBACK(menu_proc_cb), (gpointer) user_data);
1555 /*ARGSUSED*/
1556 static void
1557 disp_cb(GtkToggleButton *button, gpointer user_data)
1559 do_numtype((enum num_type) g_object_get_data(G_OBJECT(button), "disp"));
1563 void
1564 get_constant(int n)
1566 char nkey[MAXLINE], *nline;
1567 char vkey[MAXLINE], *vline;
1569 SPRINTF(nkey, "/apps/%s/constant%1dname", v->appname, n);
1570 if ((nline = gconf_client_get_string(X->client, nkey, NULL)) == NULL) {
1571 return;
1574 SPRINTF(vkey, "/apps/%s/constant%1dvalue", v->appname, n);
1575 if ((vline = gconf_client_get_string(X->client, vkey, NULL)) == NULL) {
1576 return;
1579 MPstr_to_num(vline, DEC, v->MPcon_vals[n]);
1580 STRCPY(v->con_names[n], nline);
1584 static void
1585 get_display() /* The Copy function key has been pressed. */
1587 gchar *string = NULL;
1588 GtkTextBuffer *buffer;
1589 GtkTextIter start, end;
1591 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
1593 if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end) == TRUE) {
1594 string = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
1595 } else {
1596 gtk_text_buffer_get_bounds(buffer, &start, &end);
1597 string = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
1600 if (v->shelf != NULL) {
1601 free(v->shelf);
1603 v->shelf = g_locale_from_utf8(string, strlen(string), NULL, NULL, NULL);
1604 g_free(string);
1606 gtk_clipboard_set_text(gtk_clipboard_get(X->clipboard_atom), v->shelf, -1);
1610 void
1611 get_function(int n)
1613 char nkey[MAXLINE], *nline;
1614 char vkey[MAXLINE], *vline;
1616 SPRINTF(nkey, "/apps/%s/function%1dname", v->appname, n);
1617 if ((nline = gconf_client_get_string(X->client, nkey, NULL)) == NULL) {
1618 return;
1621 SPRINTF(vkey, "/apps/%s/function%1dvalue", v->appname, n);
1622 if ((vline = gconf_client_get_string(X->client, vkey, NULL)) == NULL) {
1623 return;
1626 STRCPY(v->fun_vals[n], convert(vline));
1627 STRCPY(v->fun_names[n], nline);
1631 static char *
1632 get_localized_numeric_point(void)
1634 const char *decimal_point;
1636 decimal_point = localeconv()->decimal_point;
1638 return(g_locale_to_utf8(decimal_point, -1, NULL, NULL, NULL));
1643 get_menu_entry(enum menu_type mtype, int offset)
1645 switch (mtype) {
1646 case M_ACC :
1647 return(offset + '0');
1649 case M_LSHF :
1650 case M_RSHF :
1651 return((offset < 10) ? offset + '0' : offset + 'A' - 10);
1653 default:
1654 fprintf(stderr, "need to handle menu type %d\n", mtype);
1657 return(0);
1661 /*ARGSUSED*/
1662 static void
1663 get_proc(GtkClipboard *clipboard, const gchar *text, gpointer data)
1665 switch (v->syntax) {
1666 case npa: {
1667 int ret = lr_parse((char *) text, v->MPdisp_val);
1669 if (!ret) {
1670 show_display(v->MPdisp_val);
1671 } else {
1672 update_statusbar(_("Clipboard contained malformed calculation"),
1673 "gtk-dialog-error");
1675 break;
1678 case exprs:
1679 exp_append((char *) text);
1680 refresh_display();
1681 break;
1683 default:
1684 assert(0);
1689 /* Get gcalctool resource from merged database. */
1691 char *
1692 get_resource(enum res_type rtype)
1694 char cstr[MAXLINE], key[MAXLINE];
1696 STRCPY(key, calc_res[(int) rtype]);
1697 SPRINTF(cstr, "/apps/%s/%s", v->appname, key);
1699 return(gconf_client_get_string(X->client, cstr, NULL));
1703 void
1704 grey_buttons(enum base_type base)
1706 if (v->modetype == BASIC) {
1707 set_button_state(BUT_0_BAS, (0 < basevals[(int) base]));
1708 set_button_state(BUT_1_BAS, (1 < basevals[(int) base]));
1709 set_button_state(BUT_2_BAS, (2 < basevals[(int) base]));
1710 set_button_state(BUT_3_BAS, (3 < basevals[(int) base]));
1711 set_button_state(BUT_4_BAS, (4 < basevals[(int) base]));
1712 set_button_state(BUT_5_BAS, (5 < basevals[(int) base]));
1713 set_button_state(BUT_6_BAS, (6 < basevals[(int) base]));
1714 set_button_state(BUT_7_BAS, (7 < basevals[(int) base]));
1715 set_button_state(BUT_8_BAS, (8 < basevals[(int) base]));
1716 set_button_state(BUT_9_BAS, (9 < basevals[(int) base]));
1717 } else {
1718 set_button_state(BUT_0_ADV, (0 < basevals[(int) base]));
1719 set_button_state(BUT_1_ADV, (1 < basevals[(int) base]));
1720 set_button_state(BUT_2_ADV, (2 < basevals[(int) base]));
1721 set_button_state(BUT_3_ADV, (3 < basevals[(int) base]));
1722 set_button_state(BUT_4_ADV, (4 < basevals[(int) base]));
1723 set_button_state(BUT_5_ADV, (5 < basevals[(int) base]));
1724 set_button_state(BUT_6_ADV, (6 < basevals[(int) base]));
1725 set_button_state(BUT_7_ADV, (7 < basevals[(int) base]));
1726 set_button_state(BUT_8_ADV, (8 < basevals[(int) base]));
1727 set_button_state(BUT_9_ADV, (9 < basevals[(int) base]));
1730 set_button_state(BUT_A, (10 < basevals[(int) base]));
1731 set_button_state(BUT_B, (11 < basevals[(int) base]));
1732 set_button_state(BUT_C, (12 < basevals[(int) base]));
1733 set_button_state(BUT_D, (13 < basevals[(int) base]));
1734 set_button_state(BUT_E, (14 < basevals[(int) base]));
1735 set_button_state(BUT_F, (15 < basevals[(int) base]));
1739 static void
1740 handle_selection() /* Handle the GET function key being pressed. */
1742 gtk_clipboard_request_text(gtk_clipboard_get(X->clipboard_atom),
1743 get_proc, NULL);
1747 static void
1748 help_cb()
1750 GError *error = NULL;
1752 gnome_help_display_desktop(NULL, "gcalctool", "gcalctool", NULL, &error);
1753 if (error) {
1754 g_warning("Help error: %s\n", error->message);
1755 g_error_free(error);
1756 error = NULL;
1761 /*ARGSUSED*/
1762 static void
1763 hyp_cb(GtkToggleButton *button, gpointer user_data)
1765 v->hyperbolic = !v->hyperbolic;
1769 /*ARGSUSED*/
1770 static void
1771 inv_cb(GtkToggleButton *button, gpointer user_data)
1773 v->inverse = !v->inverse;
1777 static gboolean
1778 check_for_localized_numeric_point(int keyval)
1780 gchar outbuf[10]; /* Minumum size 6. */
1781 gunichar ch;
1783 ch = gdk_keyval_to_unicode(keyval);
1784 g_return_val_if_fail(g_unichar_validate(ch), FALSE);
1786 outbuf[g_unichar_to_utf8(ch, outbuf)] = '\0';
1788 return(strcmp(outbuf, X->lnp) == 0);
1792 static int
1793 check_vals(int n, int keyval, int state,
1794 struct button buttons[], GtkWidget *gtk_buttons[])
1796 int i, j;
1798 state = state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK);
1799 for (i = 0; i < n; i++) {
1800 j = 0;
1801 while (buttons[i].value[j] != 0) {
1802 if (buttons[i].value[j] == keyval) {
1803 if (buttons[i].mods[j] == state) {
1804 button_proc(GTK_BUTTON(gtk_buttons[i]), NULL);
1805 return(TRUE);
1808 j++;
1812 return(FALSE);
1815 /*ARGSUSED*/
1816 static gboolean
1817 kframe_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
1819 int retval = FALSE;
1821 if (check_for_localized_numeric_point(event->keyval) == TRUE) {
1822 event->state = 0;
1823 event->keyval = GDK_KP_Decimal;
1826 switch (v->modetype) {
1827 case BASIC:
1828 retval = check_vals(B_NOBUTTONS, event->keyval, event->state,
1829 b_buttons, X->bas_buttons);
1830 break;
1832 case ADVANCED:
1833 retval = check_vals(A_NOBUTTONS, event->keyval, event->state,
1834 a_buttons, X->adv_buttons);
1835 break;
1837 case FINANCIAL:
1838 retval = check_vals(A_NOBUTTONS, event->keyval, event->state,
1839 a_buttons, X->adv_buttons);
1840 if (retval != TRUE) {
1841 retval = check_vals(F_NOBUTTONS, event->keyval, event->state,
1842 f_buttons, X->fin_buttons);
1844 break;
1846 case SCIENTIFIC:
1847 retval = check_vals(A_NOBUTTONS, event->keyval, event->state,
1848 a_buttons, X->adv_buttons);
1849 if (retval != TRUE) {
1850 retval = check_vals(S_NOBUTTONS, event->keyval, event->state,
1851 s_buttons, X->sci_buttons);
1853 break;
1856 return retval;
1859 void
1860 load_resources() /* Load gconf configuration database for gcalctool. */
1862 char str[MAXLINE];
1864 SPRINTF(str, "/apps/%s", v->appname);
1865 X->client = gconf_client_get_default();
1866 gconf_client_add_dir(X->client, str, GCONF_CLIENT_PRELOAD_NONE, NULL);
1870 void
1871 make_frames()
1873 struct button *n;
1875 X->clipboard_atom = gdk_atom_intern("CLIPBOARD", FALSE);
1876 create_kframe(); /* Create main gcalctool window. */
1877 create_rframe(); /* Create memory register window. */
1878 set_mode(v->modetype);
1880 n = (struct button *) g_object_get_data(G_OBJECT(BUT_ACC), "button");
1881 (void) create_menu(n->mtype, n);
1882 set_accuracy_toggle(v->accuracy);
1883 set_show_tsep_toggle(v->show_tsep);
1884 set_show_zeroes_toggle(v->show_zeroes);
1888 static char *
1889 make_hostname(Display *dpy)
1891 char client_hostname[MAXHOSTNAMELEN + 4];
1892 char hostname[MAXHOSTNAMELEN];
1893 char *display = DisplayString(dpy);
1894 char *scanner = display;
1896 GETHOSTNAME(hostname, MAXHOSTNAMELEN);
1898 while (*scanner) {
1899 scanner++;
1902 while (*scanner != ':') {
1903 scanner--;
1906 *scanner = '\0';
1908 if (strcmp(display, hostname) &&
1909 strcmp(display, "localhost") &&
1910 strcmp(display, "unix") &&
1911 strcmp(display, "")) {
1912 SPRINTF(client_hostname, " [%s] ", hostname);
1913 } else {
1914 STRCPY(client_hostname, "");
1917 *scanner = ':';
1919 return(strdup(client_hostname));
1923 static void
1924 set_accessible_name(GtkWidget *widget, struct button button)
1926 AtkObject *access_object = gtk_widget_get_accessible(widget);
1928 atk_object_set_name(access_object,
1929 (button.astr == NULL) ? button.hstr : button.astr);
1933 void
1934 set_accuracy_menu_item(int accuracy)
1936 char label[MAXLINE];
1938 SPRINTF(label, _("Other (%d) ..."), accuracy);
1939 g_object_set(gtk_ui_manager_get_action(X->ui, "/AccMenu/SPOther"),
1940 "label", label, NULL);
1944 void
1945 set_accuracy_tooltip(int accuracy)
1947 char tooltip[MAXLINE];
1949 SPRINTF(tooltip, _("Set accuracy from 0 to %d numeric places. Currently set to %d places. [a]"),
1950 MAXACC, accuracy);
1951 gtk_tooltips_set_tip(X->tips, BUT_ACC, tooltip, "");
1955 static GtkWidget *
1956 make_but_panel(GtkWidget *vbox, GtkWidget **Gtk_buttons,
1957 struct button buttons[], int rows, int cols, char *tag)
1959 char *label, name[MAXLINE];
1960 int i, j, n;
1961 GtkWidget *l;
1962 GtkWidget *table = gtk_table_new(rows, cols, TRUE);
1964 gtk_table_set_row_spacings(GTK_TABLE(table), 6);
1965 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
1966 gtk_container_set_border_width(GTK_CONTAINER(table), 6);
1968 gtk_widget_ref(table);
1969 gtk_widget_show(table);
1970 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
1972 for (i = 0; i < cols; i++) {
1973 for (j = 0; j < rows; j++) {
1974 n = j*cols + i;
1975 label = _(buttons[n].str);
1976 if (buttons[n].mtype == M_NONE) {
1977 l = gtk_label_new(label);
1978 gtk_widget_show(l);
1979 gtk_label_set_use_markup(GTK_LABEL(l), TRUE);
1980 Gtk_buttons[n] = gtk_button_new();
1981 gtk_container_add(GTK_CONTAINER(Gtk_buttons[n]), l);
1982 } else {
1983 Gtk_buttons[n] = make_menu_button(label, j*cols + i);
1985 set_accessible_name(Gtk_buttons[n], buttons[n]);
1986 g_signal_connect(G_OBJECT(Gtk_buttons[n]), "clicked",
1987 G_CALLBACK(button_proc), (gpointer) (j*cols + i));
1988 SPRINTF(name, "%s_button%1d", tag, n);
1989 gtk_widget_set_name(Gtk_buttons[n], name);
1990 if (buttons[n].hstr != NULL) {
1991 gtk_tooltips_set_tip(X->tips, Gtk_buttons[n],
1992 _(buttons[n].hstr), "");
1994 g_object_set_data(G_OBJECT(Gtk_buttons[n]),
1995 "button", &buttons[n]);
1996 gtk_widget_ref(Gtk_buttons[n]);
1998 if (strcmp(buttons[n].str, " ")) {
1999 gtk_widget_show(Gtk_buttons[n]);
2000 } else {
2001 gtk_widget_hide(Gtk_buttons[n]);
2003 gtk_table_attach(GTK_TABLE(table), Gtk_buttons[n],
2004 i, i+1, j, j+1,
2005 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL | GTK_SHRINK),
2006 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL | GTK_SHRINK),
2007 0, 0);
2011 return(table);
2015 void
2016 make_reg(int n, char *str)
2018 gtk_label_set_markup(GTK_LABEL(X->regs[n]), str);
2022 static GtkWidget *
2023 create_menu(enum menu_type mtype, struct button *n)
2025 int m = (int) mtype;
2027 switch (mtype) {
2028 case M_EXCH :
2029 case M_RCL :
2030 case M_STO :
2031 create_mem_menu(mtype);
2032 break;
2034 case M_CON :
2035 case M_FUN :
2036 create_con_fun_menu(mtype);
2037 break;
2039 default :
2040 break;
2043 if (X->menus[m] == NULL) {
2044 if (mtype == M_ACC) {
2045 X->menus[m] = gtk_ui_manager_get_widget(X->ui, "/AccMenu");
2046 set_accuracy_menu_item(v->accuracy);
2047 } else if (mtype == M_LSHF) {
2048 X->menus[m] = gtk_ui_manager_get_widget(X->ui, "/LeftShiftMenu");
2049 } else if (mtype == M_RSHF) {
2050 X->menus[m] = gtk_ui_manager_get_widget(X->ui, "/RightShiftMenu");
2054 gtk_container_set_border_width(GTK_CONTAINER(X->menus[m]), 1);
2055 X->mrec[m] = n;
2057 return(X->menus[m]);
2061 /*ARGSUSED*/
2062 static void
2063 menu_proc_cb(GtkMenuItem *mi, gpointer user_data)
2065 int mtype = (int) g_object_get_data(G_OBJECT(mi), "mtype");
2067 v->current->value[0] = '0' + (int) user_data;
2069 handle_menu_selection(X->mrec[mtype], v->current->value[0]);
2073 /*ARGSUSED*/
2074 static void
2075 menu_button_button_press_cb(GtkWidget *widget,
2076 GdkEventButton *event, gpointer data)
2078 struct button *n;
2079 GtkWidget *menu;
2081 if (event->button != 1) {
2082 return;
2085 n = (struct button *) g_object_get_data(G_OBJECT(widget), "button");
2086 menu = create_menu(n->mtype, n);
2087 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
2088 event->button, event->time);
2092 /*ARGSUSED*/
2093 static gboolean
2094 menu_button_key_press_cb(GtkWidget *widget,
2095 GdkEventKey *event, gpointer data)
2097 struct button *n;
2098 GdkPoint loc;
2099 GtkWidget *menu;
2101 if (event->keyval == GDK_space) {
2102 n = (struct button *) g_object_get_data(G_OBJECT(widget), "button");
2103 menu = create_menu(n->mtype, n);
2104 gdk_window_get_origin(widget->window, &loc.x, &loc.y);
2105 loc.x += widget->allocation.x;
2106 loc.y += widget->allocation.y;
2107 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, menu_pos_func,
2108 (gpointer) &loc, event->keyval, event->time);
2109 return(TRUE);
2112 return(FALSE);
2116 /*ARGSUSED*/
2117 static void
2118 menu_pos_func(GtkMenu *menu, gint *x, gint *y,
2119 gboolean *push_in, gpointer user_data)
2121 GdkPoint *loc = (GdkPoint *) user_data;
2123 *x = loc->x;
2124 *y = loc->y;
2128 static GtkWidget *
2129 make_menu_button(gchar *label_text, int n)
2131 GtkWidget *arrow, *button, *hbox, *label;
2133 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2134 label = gtk_label_new(label_text);
2135 hbox = gtk_hbox_new(FALSE, 3);
2136 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2137 gtk_box_pack_start(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);
2139 button = gtk_button_new();
2140 gtk_container_add(GTK_CONTAINER(button), hbox);
2142 gtk_widget_set_events(button, GDK_BUTTON_PRESS_MASK);
2143 g_signal_connect(G_OBJECT(button), "button-press-event",
2144 G_CALLBACK(menu_button_button_press_cb), (gpointer) n);
2145 g_signal_connect(G_OBJECT(button), "key-press-event",
2146 G_CALLBACK(menu_button_key_press_cb), (gpointer) n);
2148 gtk_widget_show_all(button);
2150 return(button);
2154 static void
2155 toggle_expressions()
2157 /* TODO: Always do clear things when mode is changed. */
2159 v->syntax = v->syntax ^ 1;
2160 switch (v->syntax) {
2161 case npa:
2162 v->noparens = 0;
2163 MPstr_to_num("0", DEC, v->MPdisp_val);
2164 show_display(v->MPdisp_val);
2165 update_statusbar(_("Activated no operator precedence mode"), "");
2166 break;
2168 case exprs:
2169 v->e.calc_complete = 0;
2170 MPstr_to_num("0", DEC, v->e.ans);
2171 exp_del();
2172 show_display(v->e.ans);
2173 update_statusbar(
2174 _("Activated expression mode with operator precedence"), "");
2175 break;
2177 default:
2178 assert(0);
2180 put_resource(R_SYNTAX, Rsstr[v->syntax]);
2184 /* Handle menu bar menu selection. */
2186 static void
2187 mb_proc(GtkAction *action)
2189 const gchar *name = gtk_action_get_name(action);
2190 int choice;
2192 if (!v->started) {
2193 return;
2196 if (EQUAL(name, "Quit")) {
2197 exit(0);
2198 } else if (EQUAL(name, "Copy")) {
2199 get_display();
2200 } else if (EQUAL(name, "Paste")) {
2201 handle_selection();
2202 } else if (EQUAL(name, "Insert")) {
2203 show_ascii_frame();
2204 } else if (EQUAL(name, "Memory")) {
2205 v->rstate = !v->rstate;
2206 do_memory();
2207 } else if (EQUAL(name, "Contents")) {
2208 help_cb();
2209 } else if (EQUAL(name, "LSPlaces")) {
2210 SSCANF(name,"LSPlaces%d", &choice);
2211 choice += (choice < 10) ? '0' : 'A' - 10;
2212 handle_menu_selection(X->mrec[(int) M_LSHF], choice);
2213 } else if (EQUAL(name, "RSPlaces")) {
2214 SSCANF(name,"RSPlaces%d", &choice);
2215 choice += (choice < 10) ? '0' : 'A' - 10;
2216 handle_menu_selection(X->mrec[(int) M_RSHF], choice);
2217 } else if (EQUAL(name, "ArithmeticPrecedence")) {
2218 toggle_expressions();
2223 /*ARGSUSED*/
2224 static void
2225 mb_base_radio_proc(GtkAction *action, GtkRadioAction *current)
2227 const gchar *name = gtk_action_get_name(GTK_ACTION(current));
2229 if (!v->started) {
2230 return;
2233 if (EQUAL(name, "Basic")) {
2234 reset_mode_values(BASIC);
2235 } else if (EQUAL(name, "Advanced")) {
2236 reset_mode_values(ADVANCED);
2237 } else if (EQUAL(name, "Financial")) {
2238 reset_mode_values(FINANCIAL);
2239 } else if (EQUAL(name, "Scientific")) {
2240 reset_mode_values(SCIENTIFIC);
2245 /*ARGSUSED*/
2246 static void
2247 mb_acc_radio_proc(GtkAction *action, GtkRadioAction *current)
2249 const gchar *name = gtk_action_get_name(GTK_ACTION(current));
2251 if (!v->started) {
2252 return;
2255 if (EQUAL(name, "SPOther")) {
2256 show_precision_frame();
2257 } else {
2258 handle_menu_selection(X->mrec[(int) M_ACC], name[2]);
2263 /*ARGSUSED*/
2264 static void
2265 mstz_proc(GtkAction *action)
2267 GtkWidget *mi;
2269 if (!v->doing_mi) {
2270 v->show_zeroes = !v->show_zeroes;
2271 v->doing_mi = 1;
2272 mi = gtk_ui_manager_get_widget(X->ui, "/AccMenu/Show");
2273 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi), v->show_zeroes);
2274 v->doing_mi = 0;
2276 syntaxdep_show_display(); //show_display(v->MPdisp_val);
2277 put_resource(R_ZEROES, set_bool(v->show_zeroes == TRUE));
2278 make_registers();
2283 /*ARGSUSED*/
2284 static void
2285 new_cf_value(GtkMenuItem *item, gpointer user_data)
2287 enum menu_type mtype = (enum menu_type) user_data;
2289 if (mtype == M_CON) {
2290 X->con_dialog = create_cfframe(mtype, X->con_dialog);
2291 } else {
2292 X->fun_dialog = create_cfframe(mtype, X->fun_dialog);
2297 static void
2298 put_constant(int n, char *con_value, char *con_name)
2300 char key[MAXLINE];
2301 char *cstr = g_strdup(con_value);
2303 /* Constants are written out with no thousands seaparator and with a radix
2304 * character of ".".
2307 SPRINTF(key, "/apps/%s/constant%1dvalue", v->appname, n);
2308 gconf_client_set_string(X->client, key, cstr, NULL);
2309 g_free(cstr);
2311 SPRINTF(key, "/apps/%s/constant%1dname", v->appname, n);
2312 gconf_client_set_string(X->client, key, con_name, NULL);
2316 static void
2317 put_function(int n, char *fun_value, char *fun_name)
2319 char key[MAXLINE];
2321 SPRINTF(key, "/apps/%s/function%1dvalue", v->appname, n);
2322 gconf_client_set_string(X->client, key, fun_value, NULL);
2324 SPRINTF(key, "/apps/%s/function%1dname", v->appname, n);
2325 gconf_client_set_string(X->client, key, fun_name, NULL);
2329 /* Put gcalctool resource into deskset database. */
2331 void
2332 put_resource(enum res_type rtype, char *value)
2334 char cstr[MAXLINE], key[MAXLINE];
2336 STRCPY(key, calc_res[(int) rtype]);
2337 SPRINTF(cstr, "/apps/%s/%s", v->appname, key);
2338 gconf_client_set_string(X->client, cstr, value, NULL);
2342 /*ARGSUSED*/
2343 static void
2344 quit_cb(GtkWidget *widget, gpointer user_data)
2346 gtk_main_quit();
2350 static void
2351 reset_mode_values(enum mode_type mtype)
2353 v->modetype = mtype;
2354 set_item(BASEITEM, DEC);
2355 set_item(NUMITEM, FIX);
2356 v->accuracy = 9;
2357 set_accuracy_toggle(v->accuracy);
2359 v->show_tsep = FALSE;
2360 set_show_tsep_toggle(v->show_tsep);
2361 put_resource(R_TSEP, set_bool(v->show_tsep == TRUE));
2363 v->show_zeroes = FALSE;
2364 set_show_zeroes_toggle(v->show_zeroes);
2365 put_resource(R_ZEROES, set_bool(v->show_zeroes == TRUE));
2367 show_display(v->MPdisp_val);
2368 make_registers();
2369 do_mode();
2373 /*ARGUSED*/
2374 static void
2375 spframe_adj_cb(GtkAdjustment *adj, gpointer data)
2377 g_print("New value is %f\n", adj->value);
2381 /*ARGSUSED*/
2382 static void
2383 spframe_cancel_cb(GtkButton *button, gpointer user_data)
2385 gtk_widget_hide(X->spframe);
2389 /*ARGSUSED*/
2390 static gboolean
2391 spframe_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
2393 if (event->keyval == GDK_minus) {
2394 update_statusbar(_("Accuracy value out of range"),
2395 "gtk-dialog-error");
2396 beep();
2399 return(FALSE);
2403 /*ARGSUSED*/
2404 static void
2405 spframe_ok_cb(GtkButton *button, gpointer user_data)
2407 char intval[5];
2408 int val = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(X->spframe_val));
2410 v->accuracy = val;
2412 SPRINTF(intval, "%d", v->accuracy);
2413 put_resource(R_ACCURACY, intval);
2415 set_accuracy_menu_item(v->accuracy);
2416 set_accuracy_tooltip(v->accuracy);
2417 set_accuracy_toggle(v->accuracy);
2419 make_registers();
2420 refresh_display();
2422 gtk_widget_hide(X->spframe);
2426 static void
2427 set_button_state(GtkWidget *w, int isSensitive)
2429 gtk_widget_set_sensitive(w, isSensitive);
2433 static void
2434 set_accuracy_toggle(int val)
2436 char name[MAXLINE];
2437 GtkWidget *acc;
2439 if (val >= 0 && val <= 9) {
2440 SPRINTF(name, "/AccMenu/SP%c", val + '0');
2441 acc = gtk_ui_manager_get_widget(X->ui, name);
2442 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(acc), TRUE);
2447 void
2448 scroll_right()
2450 if (GTK_WIDGET_VISIBLE(
2451 GTK_SCROLLED_WINDOW(X->scrolledwindow)->hscrollbar)) {
2452 GtkAdjustment *set;
2454 set = gtk_scrolled_window_get_hadjustment(
2455 GTK_SCROLLED_WINDOW(X->scrolledwindow));
2456 gtk_adjustment_set_value(set, set->upper);
2457 gtk_scrolled_window_set_hadjustment(
2458 GTK_SCROLLED_WINDOW(X->scrolledwindow), set);
2463 void
2464 set_display(char *str, int minimize_changes)
2466 char localized[MAX_LOCALIZED];
2467 GtkTextBuffer *buffer;
2468 GtkTextIter start, end;
2469 gchar *text;
2470 gint diff;
2471 gint len1, len2;
2472 gboolean done;
2474 if (str == NULL || *str == 0) {
2475 str = " ";
2476 } else {
2477 if (!v->noparens) {
2478 localize_number(localized, str);
2479 str = localized;
2482 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
2483 gtk_text_buffer_get_bounds(buffer, &start, &end);
2484 text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE);
2485 diff = strcmp (text, str);
2486 if (diff != 0) {
2487 len1 = strlen(text);
2488 len2 = strlen(str);
2490 done = FALSE;
2491 if (minimize_changes) {
2492 if (len1 < len2 && strncmp(text, str, len1) == 0) {
2493 /* Text insertion */
2494 gtk_text_buffer_insert_with_tags_by_name(buffer,
2495 &end,
2496 str + len1,
2498 "x-large",
2499 NULL);
2500 done = TRUE;
2501 } else if (len1 > len2 && strncmp(text, str, len2) == 0) {
2502 /* Text deletion */
2503 gtk_text_buffer_get_iter_at_offset (buffer, &start, len2);
2504 gtk_text_buffer_delete(buffer, &start, &end);
2505 done = TRUE;
2510 if (!done) {
2511 gtk_text_buffer_delete(buffer, &start, &end);
2513 gtk_text_buffer_insert_with_tags_by_name(buffer,
2514 &end,
2515 str,
2517 "x-large",
2518 NULL);
2521 scroll_right();
2522 g_free(text);
2526 void
2527 write_display(char *str)
2529 char localized[MAX_LOCALIZED];
2530 gchar *text;
2531 GtkTextBuffer *buffer;
2532 GtkTextIter start, end;
2534 if (str == NULL || *str == 0) str = " ";
2536 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X->display_item));
2537 gtk_text_buffer_get_bounds(buffer, &start, &end);
2538 text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE);
2540 gtk_text_buffer_delete(buffer, &start, &end);
2542 gtk_text_buffer_insert_with_tags_by_name(buffer,
2543 &end,
2544 str,
2546 "x-large",
2547 NULL);
2548 scroll_right();
2549 g_free(text);
2552 #define SET_MENUBAR_ITEM_STATE(i, state) \
2553 g_object_set(gtk_ui_manager_get_action(X->ui, i), \
2554 "sensitive", state, NULL);
2557 /* When an error condition occurs:
2559 * - make insensitive all buttons except Clr.
2560 * - make all Scientific mode toggles and checkboxes insensitive.
2561 * - make all menubar items insensitive except:
2562 * Calculator->Quit
2563 * Help->Contents
2565 * When the error condition is cleared, resensitise everything, setting
2566 * the numeric base buttons correctly.
2569 void
2570 set_error_state(int error)
2572 int i;
2574 v->error = error;
2576 for (i = 0; i < (BROWS * BCOLS); i++) {
2577 set_button_state(X->bas_buttons[i], !v->error);
2579 /* Clr ("Basic") button always sensitive. */
2580 set_button_state(BUT_CLR_BAS, TRUE);
2582 for (i = 0; i < (AROWS * ACOLS); i++) {
2583 set_button_state(X->adv_buttons[i], !v->error);
2585 /* Clr ("Advanced") button always sensitive. */
2586 set_button_state(BUT_CLR_ADV, TRUE);
2588 for (i = 0; i < (FROWS * FCOLS); i++) {
2589 set_button_state(X->fin_buttons[i], !v->error);
2592 for (i = 0; i < (SROWS * SCOLS); i++) {
2593 set_button_state(X->sci_buttons[i], !v->error);
2596 if (!v->error) {
2597 grey_buttons(v->base);
2600 gtk_widget_set_sensitive(X->mode_panel, !v->error);
2602 SET_MENUBAR_ITEM_STATE("/MenuBar/EditMenu/Copy", !v->error);
2603 SET_MENUBAR_ITEM_STATE("/MenuBar/EditMenu/Paste", !v->error);
2604 SET_MENUBAR_ITEM_STATE("/MenuBar/EditMenu/Insert", !v->error);
2605 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/Basic", !v->error);
2606 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/Advanced", !v->error);
2607 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/Financial", !v->error);
2608 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/Scientific", !v->error);
2609 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/Trailing",
2610 !v->error && (v->modetype == SCIENTIFIC));
2611 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/Thousands", !v->error);
2612 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/Memory", !v->error);
2613 SET_MENUBAR_ITEM_STATE("/MenuBar/ViewMenu/ArithmeticPrecedence", !v->error);
2614 SET_MENUBAR_ITEM_STATE("/MenuBar/HelpMenu/About", !v->error);
2618 void
2619 set_hyp_item(int state)
2621 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->hyp), state);
2625 void
2626 set_inv_item(int state)
2628 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->inv), state);
2632 static void
2633 set_memory_toggle(int state)
2635 GtkWidget *reg;
2637 reg = gtk_ui_manager_get_widget(X->ui, "/MenuBar/ViewMenu/Memory");
2638 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(reg), state);
2642 void
2643 set_mode(enum mode_type mode)
2645 GtkRequisition *r;
2646 gint w, h;
2648 switch (mode) {
2649 case BASIC:
2650 gtk_widget_show(X->bas_panel);
2651 gtk_widget_hide(X->adv_panel);
2652 gtk_widget_hide(X->fin_panel);
2653 gtk_widget_hide(X->mode_panel);
2654 gtk_widget_hide(X->sci_panel);
2655 break;
2657 case ADVANCED:
2658 gtk_widget_hide(X->bas_panel);
2659 gtk_widget_show(X->adv_panel);
2660 gtk_widget_hide(X->fin_panel);
2661 gtk_widget_hide(X->mode_panel);
2662 gtk_widget_hide(X->sci_panel);
2663 break;
2665 case FINANCIAL:
2666 gtk_widget_hide(X->bas_panel);
2667 gtk_widget_show(X->adv_panel);
2668 gtk_widget_show(X->fin_panel);
2669 gtk_widget_hide(X->mode_panel);
2670 gtk_widget_hide(X->sci_panel);
2671 break;
2673 case SCIENTIFIC:
2674 gtk_widget_hide(X->bas_panel);
2675 gtk_widget_show(X->adv_panel);
2676 gtk_widget_hide(X->fin_panel);
2677 gtk_widget_show_all(X->mode_panel);
2678 gtk_widget_show(X->sci_panel);
2679 break;
2682 r = g_new0(GtkRequisition, 1);
2683 gtk_widget_size_request(X->menubar, r);
2684 w = r->width;
2685 h = r->height;
2686 gtk_widget_size_request(X->display_item, r);
2687 w = MAX(w, r->width);
2688 h += r->height;
2690 if (GTK_WIDGET_VISIBLE(X->fin_panel)) {
2691 gtk_widget_size_request(X->fin_panel, r);
2692 w = MAX(w, r->width);
2693 h += r->height;
2696 if (GTK_WIDGET_VISIBLE(X->mode_panel)) {
2697 gtk_widget_size_request(X->mode_panel, r);
2698 w = MAX(w, r->width);
2699 h += r->height;
2702 if (GTK_WIDGET_VISIBLE(X->sci_panel)) {
2703 gtk_widget_size_request(X->sci_panel, r);
2704 w = MAX(w, r->width);
2705 h += r->height;
2708 /* For initial display. */
2709 gtk_window_set_default_size(GTK_WINDOW(X->kframe), w, h);
2710 gtk_window_resize(GTK_WINDOW(X->kframe), w, h);
2712 g_free(r);
2716 static void
2717 set_item(enum item_type itemtype, int val)
2719 if (!v->started) {
2720 return;
2723 switch (itemtype) {
2724 case BASEITEM:
2725 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->base[val]), 1);
2726 break;
2728 case NUMITEM:
2729 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->disp[val]), 1);
2730 break;
2732 case TTYPEITEM:
2733 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X->trig[val]), 1);
2734 break;
2736 default:
2737 break;
2742 /* Set new title for a window. */
2744 void
2745 set_title(enum fcp_type fcptype, char *str)
2747 GtkWidget *f = NULL;
2749 if (fcptype == FCP_KEY) {
2750 f = X->kframe;
2751 } else if (fcptype == FCP_REG) {
2752 f = X->rframe;
2754 gtk_window_set_title(GTK_WINDOW(f), _(str));
2758 static void
2759 set_gcalctool_icon(void)
2761 X->icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
2762 "gnome-calculator", 48, 0, NULL);
2766 static void
2767 set_show_tsep_toggle(int state)
2769 GtkWidget *mi;
2771 mi = gtk_ui_manager_get_widget(X->ui, "/MenuBar/ViewMenu/Thousands");
2772 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi), state);
2776 static void
2777 set_show_zeroes_toggle(int state)
2779 GtkWidget *mi;
2781 v->doing_mi = 1; /* Hack to get [a,m]stz_proc() to just return. */
2782 mi = gtk_ui_manager_get_widget(X->ui, "/AccMenu/Show");
2783 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi), state);
2785 mi = gtk_ui_manager_get_widget(X->ui, "/MenuBar/ViewMenu/Trailing");
2786 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi), state);
2787 g_object_set(gtk_ui_manager_get_action(X->ui,
2788 "/MenuBar/ViewMenu/Trailing"),
2789 "sensitive", v->modetype == SCIENTIFIC, NULL);
2790 v->doing_mi = 0;
2794 static void
2795 show_ascii_frame() /* Display ASCII popup. */
2797 if (X->aframe == NULL) {
2798 create_aframe();
2801 if (gdk_window_is_visible(X->aframe->window) == FALSE) {
2802 ds_position_popup(X->kframe, X->aframe, DS_POPUP_LEFT);
2804 gtk_window_set_focus(GTK_WINDOW(X->kframe), GTK_WIDGET(X->aframe_ch));
2805 gtk_widget_show(X->aframe);
2809 static void
2810 show_precision_frame() /* Display Set Precision popup. */
2812 if (X->spframe == NULL) {
2813 create_spframe();
2816 if (gdk_window_is_visible(X->spframe->window) == FALSE) {
2817 ds_position_popup(X->kframe, X->spframe, DS_POPUP_LEFT);
2819 gtk_window_set_focus(GTK_WINDOW(X->spframe), GTK_WIDGET(X->spframe_val));
2820 gtk_widget_show(X->spframe);
2824 /*ARGSUSED*/
2825 static void
2826 trig_cb(GtkToggleButton *button, gpointer user_data)
2828 do_trigtype((enum trig_type) g_object_get_data(G_OBJECT(button), "trig"));
2832 void
2833 start_tool()
2835 v->started = 1;
2836 set_item(BASEITEM, v->base);
2837 set_item(TTYPEITEM, v->ttype);
2838 set_item(NUMITEM, v->dtype);
2840 gtk_widget_show(X->kframe);
2841 gtk_main();
2845 /*ARGSUSED*/
2846 static void
2847 ts_proc(GtkAction *action)
2849 if (!v->started) {
2850 return;
2853 v->show_tsep = !v->show_tsep;
2855 syntaxdep_show_display(); //show_display(v->MPdisp_val);
2856 put_resource(R_TSEP, set_bool(v->show_tsep == TRUE));
2857 make_registers();
2861 void
2862 win_display(enum fcp_type fcptype, int state)
2864 GtkWidget *f = NULL;
2866 if (fcptype == FCP_REG) {
2867 v->rstate = state;
2868 f = X->rframe;
2871 if (state && gdk_window_is_visible(f->window)) {
2872 gdk_window_raise(f->window);
2873 return;
2875 if (state) {
2876 if (fcptype == FCP_REG) {
2877 set_memory_toggle(v->rstate);
2878 ds_position_popup(X->kframe, f, DS_POPUP_ABOVE);
2881 if (state) {
2882 gtk_widget_show(f);
2883 } else {
2884 gtk_widget_hide(f);