view examples/calculator/main.c @ 186:530bb7728546 include_mb_test

Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'. This is the solution that I dicussed with FourDollars, last night.
author Thinker K.F. Li <thinker@branda.to>
date Wed, 05 Nov 2008 15:24:01 +0800
parents 3a4d6179e6a9
children 54fdc2a65242
line wrap: on
line source

#include <stdio.h>
#include <mb.h>
#include "calculator_scr.h"

typedef struct _calc_data calc_data_t;
struct _calc_data {
    X_MB_runtime_t *rt;
    calculator_scr_t *code;
};

static struct {
    int c;
    int off;
} tgt_list[] = {
    { 0, OFFSET(calculator_scr_t, but_0) },
    { 1, OFFSET(calculator_scr_t, but_1) },
    { 2, OFFSET(calculator_scr_t, but_2) },
    { 3, OFFSET(calculator_scr_t, but_3) },
    { 4, OFFSET(calculator_scr_t, but_4) },
    { 5, OFFSET(calculator_scr_t, but_5) },
    { 6, OFFSET(calculator_scr_t, but_6) },
    { 7, OFFSET(calculator_scr_t, but_7) },
    { 8, OFFSET(calculator_scr_t, but_8) },
    { 9, OFFSET(calculator_scr_t, but_9) },
    { '+', OFFSET(calculator_scr_t, but_add) },
    { '-', OFFSET(calculator_scr_t, but_minus) },
    { '*', OFFSET(calculator_scr_t, but_mul) },
    { '/', OFFSET(calculator_scr_t, but_div) },
    { '=', OFFSET(calculator_scr_t, but_eq) },
    { 'c', OFFSET(calculator_scr_t, but_clr) }
};

static int real_compute(int op, int v1, int v2) {
    int r = v1;

    switch(op) {
    case '+':
	r = v1 + v2;
	break;
    case '-':
	r = v1 - v2;
	break;
    case '*':
	r = v1 * v2;
	break;
    case '/':
	r = v1;
	if(v2)
	    r /= v2;
	break;
    case 'n':
	r = v2;
	break;
    case 'N':
	break;
    }

    return r;
}

static void show_text(calc_data_t *calc_data, int num, int saved, int op,
		      const char *suffix) {
    char buf[20];
    redraw_man_t *rdman;

    rdman = X_MB_rdman(calc_data->rt);

    sprintf(buf, "%d%s", num, suffix);
    sh_text_set_text(calc_data->code->screen_text, buf);
    rdman_shape_changed(rdman, calc_data->code->screen_text);

    if(op == 'n')
	sprintf(buf, "None");
    else
	sprintf(buf, "%d%c", saved, op);
    sh_text_set_text(calc_data->code->saved_text, buf);
    rdman_shape_changed(rdman, calc_data->code->saved_text);
}

static void compute(calc_data_t *calc_data, coord_t *tgt) {
    int i;
    coord_t **coord_p;
    redraw_man_t *rdman;
    static int valid_num = 0;
    static int factor = 1;
    static int num = 0;
    static int op = 'n';
    static int saved = 0;
    char buf[2] = " ";

    for(i = 0; i < 16; i++) {
	coord_p = (coord_t **)((void *)calc_data->code + tgt_list[i].off);
	if(*coord_p == (void *)tgt)
	    break;
    }
    if(i >= 16) return;

    if(i < 10) {
	num = num * 10 + i;
	show_text(calc_data, num * factor, saved, op, "");
	valid_num = 1;
    } else {
	switch(tgt_list[i].c) {
	case 'c':
	    saved = num = 0;
	    factor = 1;
	    valid_num = 0;
	    op = 'n';
	    show_text(calc_data, 0, saved, op, "");
	    break;

	case '-':
	    if(!valid_num) {
		factor *= -1;
		valid_num = 1;
		break;
	    }
	case '+':
	case '*':
	case '/':
	    saved = real_compute(op, saved, num * factor);
	    buf[0] = tgt_list[i].c;
	    show_text(calc_data, saved, saved, 'n', buf);
	    op = tgt_list[i].c;
	    num = 0;
	    factor = 1;
	    valid_num = 0;
	    break;

	case '=':
	    saved = real_compute(op, saved, num * factor);
	    show_text(calc_data, saved, 0, 'n', "");
	    num = 0;
	    op = 'N';
	    break;
	}
    }
    rdman = X_MB_rdman(calc_data->rt);
    rdman_redraw_changed(rdman);
}

static void buttons_handler(event_t *evt, void *arg) {
    calc_data_t *calc_data = (calc_data_t *)arg;

    switch(evt->type) {
    case EVT_MOUSE_BUT_PRESS:
	compute(calc_data, (coord_t *)evt->cur_tgt);
	break;
    }
}

static void setup_observers(calc_data_t *calc_data) {
    calculator_scr_t *calculator_scr;
    ob_factory_t *factory;
    subject_t *subject;
    coord_t *coord;
    redraw_man_t *rdman;
    int off;
    int i;

    calculator_scr = calc_data->code;
    rdman = X_MB_rdman(calc_data->rt);
    factory = rdman_get_ob_factory(rdman);

    for(i = 0; i < 16; i++) {
	off = tgt_list[i].off;
	coord = OFF2TYPE(calculator_scr, off, coord_t *);
	subject = coord_get_mouse_event(coord);
	subject_add_observer(factory, subject, buttons_handler, calc_data);
    }
}

int main(int argc, char * const argv[]) {
    X_MB_runtime_t *rt;
    redraw_man_t *rdman;
    calculator_scr_t *calculator_scr;
    calc_data_t calc_data;

    rt = X_MB_new(":0.0", 300, 400);

    rdman = X_MB_rdman(rt);
    calculator_scr = calculator_scr_new(rdman, rdman->root_coord);

    calc_data.rt = rt;
    calc_data.code = calculator_scr;
    setup_observers(&calc_data);

    X_MB_handle_connection(rt);

    calculator_scr_free(calculator_scr);
    X_MB_free(rt);

    return 0;
}