2 * - by Richard W.M. Jones <rich@annexia.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * $Id: 02_toy_calculator.c,v 1.9 2002/11/07 10:49:00 rich Exp $
28 #include "ml_window.h"
29 #include "ml_table_layout.h"
30 #include "ml_text_label.h"
32 #include "ml_button.h"
34 /* Main entry point to the app. */
35 static void app_main (ml_session);
38 handle_request (rws_request rq)
40 return ml_entry_point (rq, app_main);
43 /* Private per-session data. */
46 ml_text_label disp; /* The display. */
47 char digits[16]; /* Display digits (only 10+1 used). */
48 double reg; /* Hidden register. */
49 int op; /* Operation: PLUS, MINUS, TIMES, DIVIDE. */
52 /* Lots of callback functions for each button. */
53 static void press_button_0 (ml_session, void *);
54 static void press_button_1 (ml_session, void *);
55 static void press_button_2 (ml_session, void *);
56 static void press_button_3 (ml_session, void *);
57 static void press_button_4 (ml_session, void *);
59 static void press_button_5 (ml_session, void *);
60 static void press_button_6 (ml_session, void *);
61 static void press_button_7 (ml_session, void *);
62 static void press_button_8 (ml_session, void *);
63 static void press_button_9 (ml_session, void *);
65 static void press_button_DOT (ml_session, void *);
66 static void press_button_EQUALS (ml_session, void *);
67 static void press_button_PLUS (ml_session, void *);
68 static void press_button_MINUS (ml_session, void *);
69 static void press_button_TIMES (ml_session, void *);
70 static void press_button_DIVIDE (ml_session, void *);
71 static void press_button_CLEAR (ml_session, void *);
72 static void press_button_AC (ml_session, void *);
74 /* These are used as indexes in the b[] array. */
85 app_main (ml_session session)
87 pool pool = ml_session_pool (session);
95 /* Create the private, per-session data area and save it in the
98 data = pmalloc (pool, sizeof *data);
100 /* Create the top-level window. */
101 w = new_ml_window (session, pool);
103 /* Create the box surrounding the calculator. */
104 box = new_ml_box (pool);
106 /* A table layout widget is used to arrange the buttons and the screen.
107 * There are 6 rows, each with 4 columns.
109 tbl = new_ml_table_layout (pool, 6, 4);
111 /* Create the numeric buttons. */
112 b[0] = new_ml_button (pool, "0");
113 ml_button_set_callback (b[0], press_button_0, session, data);
114 ml_widget_set_property (b[0], "button.style", "key");
115 b[1] = new_ml_button (pool, "1");
116 ml_button_set_callback (b[1], press_button_1, session, data);
117 ml_widget_set_property (b[1], "button.style", "key");
118 b[2] = new_ml_button (pool, "2");
119 ml_button_set_callback (b[2], press_button_2, session, data);
120 ml_widget_set_property (b[2], "button.style", "key");
121 b[3] = new_ml_button (pool, "3");
122 ml_button_set_callback (b[3], press_button_3, session, data);
123 ml_widget_set_property (b[3], "button.style", "key");
124 b[4] = new_ml_button (pool, "4");
125 ml_button_set_callback (b[4], press_button_4, session, data);
126 ml_widget_set_property (b[4], "button.style", "key");
128 b[5] = new_ml_button (pool, "5");
129 ml_button_set_callback (b[5], press_button_5, session, data);
130 ml_widget_set_property (b[5], "button.style", "key");
131 b[6] = new_ml_button (pool, "6");
132 ml_button_set_callback (b[6], press_button_6, session, data);
133 ml_widget_set_property (b[6], "button.style", "key");
134 b[7] = new_ml_button (pool, "7");
135 ml_button_set_callback (b[7], press_button_7, session, data);
136 ml_widget_set_property (b[7], "button.style", "key");
137 b[8] = new_ml_button (pool, "8");
138 ml_button_set_callback (b[8], press_button_8, session, data);
139 ml_widget_set_property (b[8], "button.style", "key");
140 b[9] = new_ml_button (pool, "9");
141 ml_button_set_callback (b[9], press_button_9, session, data);
142 ml_widget_set_property (b[9], "button.style", "key");
144 /* Create the other buttons. */
145 b[DOT] = new_ml_button (pool, ".");
146 ml_button_set_callback (b[DOT], press_button_DOT, session, data);
147 ml_widget_set_property (b[DOT], "button.style", "key");
148 b[EQUALS] = new_ml_button (pool, "=");
149 ml_button_set_callback (b[EQUALS], press_button_EQUALS, session, data);
150 ml_widget_set_property (b[EQUALS], "button.style", "key");
151 b[PLUS] = new_ml_button (pool, "+");
152 ml_button_set_callback (b[PLUS], press_button_PLUS, session, data);
153 ml_widget_set_property (b[PLUS], "button.style", "key");
154 b[MINUS] = new_ml_button (pool, "-");
155 ml_button_set_callback (b[MINUS], press_button_MINUS, session, data);
156 ml_widget_set_property (b[MINUS], "button.style", "key");
157 b[TIMES] = new_ml_button (pool, "x");
158 ml_button_set_callback (b[TIMES], press_button_TIMES, session, data);
159 ml_widget_set_property (b[TIMES], "button.style", "key");
160 b[DIVIDE] = new_ml_button (pool, "/");
161 ml_button_set_callback (b[DIVIDE], press_button_DIVIDE, session, data);
162 ml_widget_set_property (b[DIVIDE], "button.style", "key");
163 b[CLEAR] = new_ml_button (pool, "C");
164 ml_button_set_callback (b[CLEAR], press_button_CLEAR, session, data);
165 ml_widget_set_property (b[CLEAR], "button.style", "key");
166 b[AC] = new_ml_button (pool, "AC");
167 ml_button_set_callback (b[AC], press_button_AC, session, data);
169 /* Create the display. */
170 disp = new_ml_text_label (pool, "0");
171 ml_widget_set_property (disp, "font.weight", "bold");
172 ml_widget_set_property (disp, "font.size", "large");
174 /* Pack the buttons and display into the table layout widget. */
175 ml_table_layout_pack (tbl, disp, 0, 0);
176 ml_table_layout_set_colspan (tbl, 0, 0, 4);
177 ml_table_layout_set_align (tbl, 0, 0, "right");
179 ml_table_layout_pack (tbl, b[CLEAR], 1, 2);
180 ml_table_layout_pack (tbl, b[AC], 1, 3);
182 ml_table_layout_pack (tbl, b[7], 2, 0);
183 ml_table_layout_pack (tbl, b[8], 2, 1);
184 ml_table_layout_pack (tbl, b[9], 2, 2);
185 ml_table_layout_pack (tbl, b[DIVIDE], 2, 3);
187 ml_table_layout_pack (tbl, b[4], 3, 0);
188 ml_table_layout_pack (tbl, b[5], 3, 1);
189 ml_table_layout_pack (tbl, b[6], 3, 2);
190 ml_table_layout_pack (tbl, b[TIMES], 3, 3);
192 ml_table_layout_pack (tbl, b[1], 4, 0);
193 ml_table_layout_pack (tbl, b[2], 4, 1);
194 ml_table_layout_pack (tbl, b[3], 4, 2);
195 ml_table_layout_pack (tbl, b[MINUS], 4, 3);
197 ml_table_layout_pack (tbl, b[DOT], 5, 0);
198 ml_table_layout_pack (tbl, b[0], 5, 1);
199 ml_table_layout_pack (tbl, b[EQUALS], 5, 2);
200 ml_table_layout_pack (tbl, b[PLUS], 5, 3);
202 /* Pack the table into the box and the box into the window. */
203 ml_box_pack (box, tbl);
204 ml_window_pack (w, box);
206 /* Save the display widget in the per-session data structure so
207 * that the callback functions can update it.
210 strcpy (data->digits, "0");
215 static void press_button_N (ml_session, int, void *);
218 press_button_0 (ml_session session, void *vp)
220 press_button_N (session, 0, vp);
224 press_button_1 (ml_session session, void *vp)
226 press_button_N (session, 1, vp);
230 press_button_2 (ml_session session, void *vp)
232 press_button_N (session, 2, vp);
236 press_button_3 (ml_session session, void *vp)
238 press_button_N (session, 3, vp);
242 press_button_4 (ml_session session, void *vp)
244 press_button_N (session, 4, vp);
248 press_button_5 (ml_session session, void *vp)
250 press_button_N (session, 5, vp);
254 press_button_6 (ml_session session, void *vp)
256 press_button_N (session, 6, vp);
260 press_button_7 (ml_session session, void *vp)
262 press_button_N (session, 7, vp);
266 press_button_8 (ml_session session, void *vp)
268 press_button_N (session, 8, vp);
272 press_button_9 (ml_session session, void *vp)
274 press_button_N (session, 9, vp);
278 press_button_N (ml_session session, int n, void *vp)
280 struct data *data = (struct data *) vp;
283 if (strcmp (data->digits, "0") == 0)
284 data->digits[0] = '\0';
286 len = strlen (data->digits);
288 if ((strchr (data->digits, '.') && len < 11) || len < 10)
290 data->digits[len] = '0' + n;
291 data->digits[len+1] = '\0';
292 ml_widget_set_property (data->disp, "text", data->digits);
297 press_button_DOT (ml_session session, void *vp)
299 struct data *data = (struct data *) vp;
300 int len = strlen (data->digits);
302 if (strchr (data->digits, '.') == 0 && len < 10)
304 strcat (data->digits, ".");
305 ml_widget_set_property (data->disp, "text", data->digits);
310 press_button_EQUALS (ml_session session, void *vp)
312 struct data *data = (struct data *) vp;
317 sscanf (data->digits, "%lf", &a);
319 if (data->op == PLUS)
321 else if (data->op == MINUS)
323 else if (data->op == TIMES)
325 else if (data->op == DIVIDE && a != 0)
328 snprintf (data->digits, 10, "%g", data->reg);
329 ml_widget_set_property (data->disp, "text", data->digits);
335 press_button_PLUS (ml_session session, void *vp)
337 struct data *data = (struct data *) vp;
339 /* Act like we just pressed the EQUALS key. */
340 press_button_EQUALS (session, data);
342 sscanf (data->digits, "%lf", &data->reg);
343 strcpy (data->digits, "0"); /* But DON'T update the label yet. */
348 press_button_MINUS (ml_session session, void *vp)
350 struct data *data = (struct data *) vp;
352 /* Act like we just pressed the EQUALS key. */
353 press_button_EQUALS (session, data);
355 sscanf (data->digits, "%lf", &data->reg);
356 strcpy (data->digits, "0"); /* But DON'T update the label yet. */
361 press_button_TIMES (ml_session session, void *vp)
363 struct data *data = (struct data *) vp;
365 /* Act like we just pressed the EQUALS key. */
366 press_button_EQUALS (session, data);
368 sscanf (data->digits, "%lf", &data->reg);
369 strcpy (data->digits, "0"); /* But DON'T update the label yet. */
374 press_button_DIVIDE (ml_session session, void *vp)
376 struct data *data = (struct data *) vp;
378 /* Act like we just pressed the EQUALS key. */
379 press_button_EQUALS (session, data);
381 sscanf (data->digits, "%lf", &data->reg);
382 strcpy (data->digits, "0"); /* But DON'T update the label yet. */
387 press_button_CLEAR (ml_session session, void *vp)
389 struct data *data = (struct data *) vp;
391 strcpy (data->digits, "0");
392 ml_widget_set_property (data->disp, "text", "0");
396 press_button_AC (ml_session session, void *vp)
398 struct data *data = (struct data *) vp;
400 strcpy (data->digits, "0");
402 ml_widget_set_property (data->disp, "text", "0");