GnuCash  5.6-150-g038405b370+
pricecell-gnome.c
1 /********************************************************************\
2  * This program is free software; you can redistribute it and/or *
3  * modify it under the terms of the GNU General Public License as *
4  * published by the Free Software Foundation; either version 2 of *
5  * the License, or (at your option) any later version. *
6  * *
7  * This program is distributed in the hope that it will be useful, *
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
10  * GNU General Public License for more details. *
11  * *
12  * You should have received a copy of the GNU General Public License*
13  * along with this program; if not, contact: *
14  * *
15  * Free Software Foundation Voice: +1-617-542-5942 *
16  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
17  * Boston, MA 02110-1301, USA gnu@gnu.org *
18  * *
19 \********************************************************************/
20 
21 /* pricecell-gnome.c
22  *
23  * Implements gnome dependent price cell functions :
24  *
25  * Often the decimal key in the keypad is not mapped to the correct locale
26  * decimal point, the function PriceDirect handle this case.
27  */
28 
29 #include <config.h>
30 
31 #include <locale.h>
32 #include <gdk/gdkkeysyms.h>
33 
34 #include "gnc-locale-utils.h"
35 #include "gnc-exp-parser.h"
36 #include "gnc-ui-util.h"
37 #include "pricecell.h"
38 #include "pricecell-gnome.h"
39 
40 #ifdef G_OS_WIN32
41 # include <gdk/gdkwin32.h>
42 #endif
43 
44 static gboolean
45 gnc_price_cell_direct_update (BasicCell *bcell,
46  int *cursor_position,
47  int *start_selection,
48  int *end_selection,
49  void *gui_data)
50 {
51  PriceCell *cell = (PriceCell *) bcell;
52  GdkEventKey *event = gui_data;
53  struct lconv *lc;
54  gboolean is_return;
55 
56  if (event->type != GDK_KEY_PRESS)
57  return FALSE;
58 
59  lc = gnc_localeconv ();
60 
61  is_return = FALSE;
62 
63  switch (event->keyval)
64  {
65  case GDK_KEY_Return:
66  if (!(event->state &
67  (GDK_MODIFIER_INTENT_DEFAULT_MOD_MASK)))
68  is_return = TRUE;
69  /* fall through */
70 
71  case GDK_KEY_KP_Enter:
72  {
73  char *error_loc;
74  gnc_numeric amount;
75  gboolean parse_ok;
76  gboolean changed = FALSE;
77 
78  if (!cell->need_to_parse)
79  return FALSE;
80 
81  parse_ok = gnc_exp_parser_parse (cell->cell.value,
82  &amount, &error_loc);
83 
84  if (parse_ok)
85  changed = gnc_price_cell_set_value (cell, amount);
86  else if (!cell->cell.value || cell->cell.value[0] == '\0')
87  changed = gnc_price_cell_set_value (cell,
88  gnc_numeric_zero ());
89  else
90  *cursor_position = error_loc - cell->cell.value;
91 
92  /* If there is a problem with the parse, swallow
93  * the key so we stay put. */
94  if (!parse_ok)
95  return TRUE;
96 
97  /* If nothing has changed, let the key cause a
98  * cursor activation no matter what. */
99  if (!changed)
100  return FALSE;
101 
102  /* If it's not a plain return, stay put. This
103  * allows a 'calculator' style operation using
104  * keypad enter where you can keep entering more
105  * items to add, say. */
106  return !is_return;
107  }
108 
109  case GDK_KEY_KP_Decimal:
110  break;
111 
112  default:
113  return FALSE;
114  }
115 
116  /* This point is only reached when the KP_Decimal key is pressed. */
117  gnc_basic_cell_insert_decimal(bcell,
118  cell->print_info.monetary
119  ? lc->mon_decimal_point[0]
120  : lc->decimal_point[0],
121  cursor_position,
122  start_selection,
123  end_selection);
124 
125  cell->need_to_parse = TRUE;
126 
127  return TRUE;
128 }
129 
130 BasicCell *
131 gnc_price_cell_gnome_new (void)
132 {
133  BasicCell *cell;
134 
135  cell = gnc_price_cell_new ();
136 
137  cell->direct_update = gnc_price_cell_direct_update;
138 
139  return cell;
140 }
141 
142 void
143 gnc_basic_cell_insert_decimal(BasicCell *bcell,
144  char decimal_point,
145  int *cursor_position,
146  int *start_selection,
147  int *end_selection)
148 {
149  GString *newval_gs;
150  gint start, end;
151  gchar *buf;
152 
153  /* allocate space for newval_ptr : oldval + one letter ( the
154  decimal_point ) */
155  newval_gs = g_string_new("");
156 
157  start = MIN(*start_selection, *end_selection);
158  end = MAX(*start_selection, *end_selection);
159 
160  /* length in bytes, not chars. do not use g_utf8_strlen. */
161  buf = g_malloc0(strlen(bcell->value) + 1);
162  g_utf8_strncpy(buf, bcell->value, start);
163  g_string_append(newval_gs, buf);
164  g_free(buf);
165 
166  g_string_append_unichar(newval_gs, decimal_point);
167 
168  buf = g_utf8_offset_to_pointer(bcell->value, end);
169  g_string_append(newval_gs, buf);
170 
171  /* update the cursor position */
172  *cursor_position = start + 1;
173 
174  gnc_basic_cell_set_value_internal (bcell, newval_gs->str);
175 
176  g_string_free (newval_gs, TRUE);
177 }
178 
utility functions for the GnuCash UI
The PriceCell object implements a cell handler that stores a single double-precision value...
Definition: pricecell.h:54
GNCPrintAmountInfo print_info
controls printing of zero values
Definition: pricecell.h:60
gboolean need_to_parse
amount printing context
Definition: pricecell.h:61
gboolean gnc_price_cell_set_value(PriceCell *cell, gnc_numeric amount)
updates amount, returns TRUE if string representation actually changed
Definition: pricecell.c:219
BasicCell * gnc_price_cell_new(void)
installs a callback to handle price recording
Definition: pricecell.c:168