00001 #include <stdio.h> 00002 #include <mb.h> 00003 #include "calculator_scr.h" 00004 00005 typedef struct _calc_data calc_data_t; 00006 struct _calc_data { 00007 X_MB_runtime_t *rt; 00008 calculator_scr_t *code; 00009 }; 00010 00011 static struct { 00012 int c; 00013 int off; 00014 } tgt_list[] = { 00015 { 0, OFFSET(calculator_scr_t, but_0) }, 00016 { 1, OFFSET(calculator_scr_t, but_1) }, 00017 { 2, OFFSET(calculator_scr_t, but_2) }, 00018 { 3, OFFSET(calculator_scr_t, but_3) }, 00019 { 4, OFFSET(calculator_scr_t, but_4) }, 00020 { 5, OFFSET(calculator_scr_t, but_5) }, 00021 { 6, OFFSET(calculator_scr_t, but_6) }, 00022 { 7, OFFSET(calculator_scr_t, but_7) }, 00023 { 8, OFFSET(calculator_scr_t, but_8) }, 00024 { 9, OFFSET(calculator_scr_t, but_9) }, 00025 { '+', OFFSET(calculator_scr_t, but_add) }, 00026 { '-', OFFSET(calculator_scr_t, but_minus) }, 00027 { '*', OFFSET(calculator_scr_t, but_mul) }, 00028 { '/', OFFSET(calculator_scr_t, but_div) }, 00029 { '=', OFFSET(calculator_scr_t, but_eq) }, 00030 { 'c', OFFSET(calculator_scr_t, but_clr) } 00031 }; 00032 00033 static int real_compute(int op, int v1, int v2) { 00034 int r = v1; 00035 00036 switch(op) { 00037 case '+': 00038 r = v1 + v2; 00039 break; 00040 case '-': 00041 r = v1 - v2; 00042 break; 00043 case '*': 00044 r = v1 * v2; 00045 break; 00046 case '/': 00047 r = v1; 00048 if(v2) 00049 r /= v2; 00050 break; 00051 case 'n': 00052 r = v2; 00053 break; 00054 case 'N': 00055 break; 00056 } 00057 00058 return r; 00059 } 00060 00061 static void show_text(calc_data_t *calc_data, int num, int saved, int op, 00062 const char *suffix) { 00063 char buf[20]; 00064 redraw_man_t *rdman; 00065 00066 rdman = X_MB_rdman(calc_data->rt); 00067 00068 sprintf(buf, "%d%s", num, suffix); 00069 sh_text_set_text(calc_data->code->screen_text, buf); 00070 rdman_shape_changed(rdman, calc_data->code->screen_text); 00071 00072 if(op == 'n') 00073 sprintf(buf, "None"); 00074 else 00075 sprintf(buf, "%d%c", saved, op); 00076 sh_text_set_text(calc_data->code->saved_text, buf); 00077 rdman_shape_changed(rdman, calc_data->code->saved_text); 00078 } 00079 00080 static void compute(calc_data_t *calc_data, coord_t *tgt) { 00081 int i; 00082 coord_t **coord_p; 00083 redraw_man_t *rdman; 00084 static int valid_num = 0; 00085 static int factor = 1; 00086 static int num = 0; 00087 static int op = 'n'; 00088 static int saved = 0; 00089 char buf[2] = " "; 00090 00091 for(i = 0; i < 16; i++) { 00092 coord_p = (coord_t **)((void *)calc_data->code + tgt_list[i].off); 00093 if(*coord_p == (void *)tgt) 00094 break; 00095 } 00096 if(i >= 16) return; 00097 00098 if(i < 10) { 00099 num = num * 10 + i; 00100 show_text(calc_data, num * factor, saved, op, ""); 00101 valid_num = 1; 00102 } else { 00103 switch(tgt_list[i].c) { 00104 case 'c': 00105 saved = num = 0; 00106 factor = 1; 00107 valid_num = 0; 00108 op = 'n'; 00109 show_text(calc_data, 0, saved, op, ""); 00110 break; 00111 00112 case '-': 00113 if(!valid_num) { 00114 factor *= -1; 00115 valid_num = 1; 00116 break; 00117 } 00118 case '+': 00119 case '*': 00120 case '/': 00121 saved = real_compute(op, saved, num * factor); 00122 buf[0] = tgt_list[i].c; 00123 show_text(calc_data, saved, saved, 'n', buf); 00124 op = tgt_list[i].c; 00125 num = 0; 00126 factor = 1; 00127 valid_num = 0; 00128 break; 00129 00130 case '=': 00131 saved = real_compute(op, saved, num * factor); 00132 show_text(calc_data, saved, 0, 'n', ""); 00133 num = 0; 00134 op = 'N'; 00135 break; 00136 } 00137 } 00138 rdman = X_MB_rdman(calc_data->rt); 00139 rdman_redraw_changed(rdman); 00140 } 00141 00142 static void buttons_handler(event_t *evt, void *arg) { 00143 calc_data_t *calc_data = (calc_data_t *)arg; 00144 00145 switch(evt->type) { 00146 case EVT_MOUSE_BUT_PRESS: 00147 compute(calc_data, (coord_t *)evt->cur_tgt); 00148 break; 00149 } 00150 } 00151 00152 static void setup_observers(calc_data_t *calc_data) { 00153 calculator_scr_t *calculator_scr; 00154 ob_factory_t *factory; 00155 subject_t *subject; 00156 coord_t *coord; 00157 redraw_man_t *rdman; 00158 int off; 00159 int i; 00160 00161 calculator_scr = calc_data->code; 00162 rdman = X_MB_rdman(calc_data->rt); 00163 factory = rdman_get_ob_factory(rdman); 00164 00165 for(i = 0; i < 16; i++) { 00166 off = tgt_list[i].off; 00167 coord = OFF2TYPE(calculator_scr, off, coord_t *); 00168 subject = coord_get_mouse_event(coord); 00169 subject_add_observer(factory, subject, buttons_handler, calc_data); 00170 } 00171 } 00172 00173 int main(int argc, char * const argv[]) { 00174 X_MB_runtime_t *rt; 00175 redraw_man_t *rdman; 00176 calculator_scr_t *calculator_scr; 00177 calc_data_t calc_data; 00178 00179 rt = X_MB_new(":0.0", 300, 400); 00180 00181 rdman = X_MB_rdman(rt); 00182 calculator_scr = calculator_scr_new(rdman, rdman->root_coord); 00183 00184 calc_data.rt = rt; 00185 calc_data.code = calculator_scr; 00186 setup_observers(&calc_data); 00187 00188 X_MB_handle_connection(rt); 00189 00190 calculator_scr_free(calculator_scr); 00191 X_MB_free(rt); 00192 00193 return 0; 00194 }