#include #include "cabecera.h" #include #define _(String) gettext (String) #define G_ASCII_DTOSTR_BUF_SIZE (29 + 10) extern GnomeCanvasGroup *root30, *root32; extern GnomeCanvasPoints *points30; GnomeCanvasItem *item30; extern GtkWidget *entry31, *boton32; gdouble X, Y, X1, Y1; GArray *numeradores, *denominadores, *pos_signos; GString *signos; gchar *cadena; gint32 num_final, den_final; void opera_sin_parentesis() { gint32 valor, n, d; gint i, primero, n_signos_por; dibuja_expresion_sin_parentesis(signos->str, X1, Y1); gboolean prod_div=FALSE, final=FALSE; for (i=0; ilen; i++) if ((signos->str[i]==':')||(signos->str[i]=='*')) { prod_div=TRUE; primero= i; break; } while (prod_div&&(!final)) { if (signos->str[primero]==':') { n=g_array_index(numeradores, gint32, primero)*g_array_index(denominadores, gint32, primero+1); d=g_array_index(numeradores, gint32, primero+1)*g_array_index(denominadores, gint32, primero); if ((n>9999999)||(d>9999999)||(n<-9999999)||(d<-9999999)) { numeros_grandes(); final=TRUE; } else { g_array_remove_range (numeradores, primero, 2); g_array_remove_range (denominadores, primero, 2); g_array_insert_val(numeradores, primero, n); g_array_insert_val(denominadores, primero, d); g_string_erase (signos, primero, 1); dibuja_expresion_sin_parentesis(signos->str, X1, Y1); } } if (signos->str[primero]=='*') { n_signos_por=1; if (primerolen) { for (i=primero+1; ilen; i++) if (signos->str[i]=='*') { n_signos_por=n_signos_por+1; } else break; } n=g_array_index(numeradores, gint32, primero); d=g_array_index(denominadores, gint32, primero); for (i=1; i<=n_signos_por; i++) { n=n*g_array_index(numeradores, gint32, primero+i); d=d*g_array_index(denominadores, gint32, primero+i); } if ((n>9999999)||(d>9999999)||(n<-9999999)||(d<-9999999)) { numeros_grandes(); final=TRUE; } else { g_array_remove_range (numeradores, primero, n_signos_por+1); g_array_remove_range (denominadores, primero, n_signos_por+1); g_array_insert_val(numeradores, primero, n); g_array_insert_val(denominadores, primero, d); g_string_erase (signos, primero, n_signos_por); dibuja_expresion_sin_parentesis(signos->str, X1, Y1); num_final=n; den_final=d; } } prod_div=FALSE; for (i=0; ilen; i++) if ((signos->str[i]==':')||(signos->str[i]=='*')) { prod_div=TRUE; primero= i; break; } } if (numeradores->len>1) { if (igual_denominador()) sum_rest_igual_den(); else { for (i=0; ilen; i++) if (g_array_index(denominadores, gint32, i)<0) { valor=-1*g_array_index(numeradores, gint32, i); g_array_remove_index (numeradores, i); g_array_insert_val(numeradores, i, valor ); valor=-1*g_array_index(denominadores, gint32, i); g_array_remove_index (denominadores, i); g_array_insert_val(denominadores, i, valor); dibuja_expresion_sin_parentesis(signos->str, X1, Y1); } if (m_c_m()<9999999) { for (i=0; ilen; i++) { valor=m_c_m()*g_array_index(numeradores, gint32, i)/g_array_index(denominadores, gint32, i); g_array_remove_index (numeradores, i); g_array_insert_val(numeradores,i, valor); } valor=m_c_m(); g_array_remove_range (denominadores, 0, denominadores->len); for (i=0; ilen; i++) g_array_append_val(denominadores, valor); sum_rest_igual_den(); } else numeros_grandes(); } } } gboolean llena_arrays(gchar *cadena) { gint i; signos=g_string_new (""); pos_signos=g_array_new(TRUE, FALSE, sizeof (gint)); numeradores=g_array_new(TRUE, FALSE, sizeof (gint)); denominadores=g_array_new(TRUE, FALSE, sizeof (gint)); for (i=0; i0 )) { g_string_append_c(signos, cadena[i]); g_array_append_val(pos_signos, i); } if (cadena[0]=='(') guarda_num_den(cadena, 1, g_array_index(pos_signos, gint, 0)); else guarda_num_den(cadena, 0, g_array_index(pos_signos, gint, 0)); for (i=0; ilen; i++) { if (i+1!=signos->len) { if (cadena[g_array_index(pos_signos, gint, i)+1]=='(') guarda_num_den(cadena, g_array_index(pos_signos, gint, i)+2, g_array_index(pos_signos, gint, i+1)); else guarda_num_den(cadena, g_array_index(pos_signos, gint, i)+1, g_array_index(pos_signos, gint, i+1)); } else { if (cadena[g_array_index(pos_signos, gint, i)+1]=='(') guarda_num_den(cadena, g_array_index(pos_signos, gint, i)+2, strlen(cadena)); else guarda_num_den(cadena, g_array_index(pos_signos, gint, i)+1, strlen(cadena)); } } gboolean resultado=FALSE; for (i=0; ilen; i++) if ((g_array_index(numeradores, gint32, i)>9999999)||(g_array_index(denominadores, gint32, i)>9999999)||(g_array_index(numeradores, gint32, i)<-9999999)||(g_array_index(denominadores, gint32, i)<-9999999)) resultado=TRUE; return resultado; } void dibuja_expresion_sin_parentesis(gchar *signos, gdouble x, gdouble y) { gint i; gchar *nume, *deno; char buf1[G_ASCII_DTOSTR_BUF_SIZE], buf2[G_ASCII_DTOSTR_BUF_SIZE]; X1=x; Y1=y; for (i=0; i<=strlen(signos); i++) { nume=g_ascii_dtostr(buf1, sizeof(buf1), g_array_index(numeradores, gint32, i)); if (strlen(nume) >7) { numeros_grandes(); return; } deno=g_ascii_dtostr(buf2, sizeof(buf2), g_array_index(denominadores, gint32, i)); dibuja_fraccion(nume, deno ,root32, X1, Y1); if (i==strlen(signos)&&(numeradores->len>1)) dibuja_signo2(root32, "=", X1, Y1); else { if (signos[i]=='+') dibuja_signo2(root32, "+", X1, Y1); if (signos[i]=='-') dibuja_signo2(root32, "-", X1, Y1); if (signos[i]=='*') dibuja_signo2(root32, "·", X1, Y1); if (signos[i]==':') dibuja_signo2(root32, ":", X1, Y1); } } if (X1>300) { X1=25; Y1=Y1+70; } } void dibuja_expresion_con_parentesis(gchar *signos, gdouble x, gdouble y) { gint i, j, p; gchar *nume, *deno; char buf1[G_ASCII_DTOSTR_BUF_SIZE], buf2[G_ASCII_DTOSTR_BUF_SIZE]; X1=x; Y1=y; if (cadena[0]=='(') { parentesis('i', root32, X1, Y1); for (i=1; i<=strlen(cadena); i++) if (cadena[i]=='(') parentesis('i', root32, X1, Y1); else break; } for (i=0; i<=strlen(signos); i++) { nume=g_ascii_dtostr(buf1, sizeof(buf1), g_array_index(numeradores, gint32, i)); deno=g_ascii_dtostr(buf2, sizeof(buf2), g_array_index(denominadores, gint32, i)); dibuja_fraccion(nume, deno ,root32, X1, Y1); if (i==strlen(signos)) { if (cadena[strlen(cadena)-1]==')') { parentesis('d', root32, X1, Y1); for (j=strlen(cadena)-2; j>=0; j--) if (cadena[j]==')') parentesis('d', root32, X1, Y1); else break; } dibuja_signo2(root32, "=", X1, Y1); } else { p=g_array_index(pos_signos,gint,i)-1; if (cadena[p]==')') parentesis('d', root32, X1, Y1); for (j=p-1; j>=0; j--) if (cadena[j]==')') parentesis('d', root32, X1, Y1); else break; if (signos[i]=='+') dibuja_signo2(root32, "+", X1, Y1); if (signos[i]=='-') dibuja_signo2(root32, "-", X1, Y1); if (signos[i]=='*') dibuja_signo2(root32, "·", X1, Y1); if (signos[i]==':') dibuja_signo2(root32, ":", X1, Y1); gint p=g_array_index(pos_signos,gint,i)+1; if (cadena[p]=='(') { parentesis('i', root32, X1, Y1); for (j=p+1; i<=strlen(cadena); j++) if (cadena[j]=='(') parentesis('i', root32, X1, Y1); else break; } } } X1=25; Y1=Y1+70; } void busca_expresion_entre_parenteis() { gint i, n, max, inicio, fin; gchar *cadenita; GString *corriente, *corriente2; char buf1[G_ASCII_DTOSTR_BUF_SIZE], buf2[G_ASCII_DTOSTR_BUF_SIZE]; n=0; max=0; inicio=0; fin=1; for (i=0; imax) { max=n; inicio=i; } } for (i=inicio+1; ilen!=0) { parentesis('[', root32, X1, Y1); opera_sin_parentesis(); parentesis(']', root32, X1, Y1); for (i=0; istr, X1, Y1); busca_expresion_entre_parenteis(); } void guarda_num_den(gchar *cadena, gint inicio, gint fin) { gint i; gint32 numero; GString *numerador=g_string_new(""); GString *denominador=g_string_new(""); gboolean barra=FALSE; for (i=inicio; ilen==0) g_string_append_c(denominador, '1'); numero=g_ascii_strtod(numerador->str ,NULL); g_array_append_val(numeradores, numero); numero=g_ascii_strtod(denominador->str ,NULL); g_array_append_val(denominadores, numero); g_string_free(numerador, TRUE); g_string_free(denominador, TRUE); } gboolean igual_denominador() { gboolean igual=TRUE; gint i; for (i=1; ilen; i++) if (g_array_index(denominadores, gint32, 0)!=g_array_index(denominadores, gint32, i)) { igual=FALSE; return igual; } return igual; } gint32 m_c_m () { gint i, j; gint32 max, producto, mcm; gboolean fin; max=g_array_index(denominadores, gint32, 0); mcm=max; producto=g_array_index(denominadores, gint32, 0); for (i=1; ilen; i++) { if (g_array_index(denominadores, gint32, i)>max) max=g_array_index(denominadores, gint32, i); producto=producto*g_array_index(denominadores, gint32, i); } for (i=1; mcmlen; j++) if (mcm%g_array_index(denominadores, gint32, j)!=0) fin=FALSE; if (fin) break; } return mcm; } void callback33 (GtkWidget *widget, gchar data) { Aceptar(); } void Aceptar() { borra_canvas(root32); X1=25.0; Y1=30.0; gchar *cadena, *error; gint i, j, h, num_par_i=0, num_par_d=0; gboolean digito, terminar; error=""; cadena=gtk_editable_get_chars(GTK_EDITABLE(entry31),0,-1); if (cadena[0]=='/') { if (cadena[1]!='/') error=_("Expresión incorrecta: \nPrimera fracción sin numerador."); if (cadena[1]=='/') error=_("Expresión incorrecta: \nVarios signos de fracción seguidos."); } if (strlen(error)==0) { if (cadena[0]=='*') error=_("Expresión incorrecta: \nPrimer carácter no puede ser '*'"); if (cadena[0]==':') error=_("Expresión incorrecta: \nPrimer carácter no puede ser ':'"); } if (strlen(error)==0) { terminar=FALSE; for (i=0; i ó <:>"); break; } if (strlen(error)==0) if (cadena[strlen(cadena)-1]=='/') error=_("Expresión incorrecta: \nÚltima fracción sin denominador"); if (strlen(error)==0) if (!g_ascii_isdigit (cadena[strlen(cadena)-1])) if (cadena[strlen(cadena)-1]!=')') error=_("Expresión incorrecta: \nLa expresión no termina correctamente"); if (strlen(error)>0) { muestra_error(error); g_free (cadena); gtk_widget_set_sensitive(boton32, FALSE); } else { gtk_widget_set_sensitive(boton32, TRUE); gtk_widget_grab_focus (boton32); } } void callback31 (GtkWidget *widget, gchar data) { gtk_entry_set_text (GTK_ENTRY(entry31), ""); borra_canvas(root32); } void insert_text_handler (GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer data) { int i; GString *result; gboolean SI; result = g_string_new(""); for (i = 0; i < length; i++) { SI = FALSE; if (g_ascii_isdigit (text[i])) SI=TRUE; if ((text[i]=='+')||(text[i]=='-')||(text[i]=='*')||(text[i]==':')) SI=TRUE; if ((text[i]=='/')||(text[i]==')')||(text[i]=='(')) SI=TRUE; if (SI) g_string_append_c(result, text[i]); } g_signal_handlers_block_by_func (editable, (gpointer) insert_text_handler, data); if (SI) gtk_editable_insert_text (editable, result->str, length, position); g_signal_handlers_unblock_by_func (editable, (gpointer) insert_text_handler, data); g_signal_stop_emission_by_name (editable, "insert_text"); g_string_free (result, TRUE); } void callback_31 (GtkEditable *editable, gpointer user_data) { gint i, j, f; GString *signos; gchar *cadena; GArray *pos_signos; gchar *sign; borra_canvas(root30); X=20.0; Y=15.0; cadena=gtk_editable_get_chars(GTK_EDITABLE(entry31),0,-1); signos=g_string_new (""); pos_signos=g_array_new(TRUE, FALSE, sizeof (gint)); for (i=0; i0)) { g_string_append_c(signos, cadena[i]); g_array_append_val(pos_signos, i); } sign=signos->str; gboolean barra=FALSE, ERROR=FALSE; gint inicio=0, fin; GString *numerador=g_string_new(""); GString *denominador=g_string_new(""); g_signal_handlers_block_by_func (editable, (gpointer) callback_31, user_data); if (cadena[0]=='(') { parentesis('i', root30, X, Y); if (cadena[1]!='(') inicio=1; else { inicio=2; parentesis('i', root30, X, Y); for (i=2; ilen==0) { for (i=inicio; i0)&&((g_ascii_isdigit(cadena[i-1]))|| (cadena[i-1]=='/') ) ) { muestra_error(_("Expresión incorrecta: \nFalta signo de operación antes de paréntesis '(' ")); ERROR=TRUE; } for (i=0; ilen, root30, X, Y); dibuja_fraccion(numerador->str, denominador->str, root30, X, Y); f=strlen(cadena)-1; if (cadena[f]==')') { parentesis('d', root30, X, Y); for (i=f-1; i>=0; i--) if (cadena[i]==')') parentesis('d', root30, X, Y); else break; } } } else { g_string_erase(numerador,0,-1); g_string_erase(denominador,0,-1); for (i=inicio; i0)&&((g_ascii_isdigit(cadena[i-1]))|| (cadena[i-1]=='/') ) ) { muestra_error(_("Expresión incorrecta: \nFalta signo de operación antes de paréntesis '(' ")); ERROR=TRUE; } for (i=0; istr, denominador->str, root30, X, Y); f=g_array_index(pos_signos, gint, 0)-1; if (cadena[f]==')') { parentesis('d', root30, X, Y); for (i=f-1; i>=0; i--) if (cadena[i]==')') parentesis('d', root30, X, Y); else break; } } for (j=0; jlen; j++) { barra=FALSE; if (sign[j]=='+') dibuja_signo2(root30, "+", X, Y); if (sign[j]=='-') dibuja_signo2(root30, "-", X, Y); if (sign[j]=='*') dibuja_signo2(root30, "·", X, Y); if (sign[j]==':') dibuja_signo2(root30, ":", X, Y); g_string_erase(numerador,0,-1); g_string_erase(denominador,0,-1); gint p=g_array_index(pos_signos, gint, j)+1; if (j+1==signos->len) { if (cadena[p]=='(') { parentesis('i', root30, X, Y); if (cadena[p+1]!='(') inicio=p+1; else { inicio=p+2; parentesis('i', root30, X, Y); for (i=p+2; ilen, root30, X, Y); dibuja_fraccion(numerador->str, denominador->str, root30, X, Y); f=strlen(cadena)-1; if (cadena[f]==')') { parentesis('d', root30, X, Y); for (i=f-1; i>=0; i--) if (cadena[i]==')') parentesis('d', root30, X, Y); else break; } } else { if (cadena[p]=='(') { parentesis('i', root30, X, Y); if (cadena[p+1]!='(') inicio=p+1; else { inicio=p+2; parentesis('i', root30, X, Y); for (i=p+2; istr, denominador->str, root30, X, Y); f=g_array_index(pos_signos, gint, j+1)-1; if (cadena[f]==')') { parentesis('d', root30, X, Y); for (i=f-1; i>=0; i--) if (cadena[i]==')') parentesis('d', root30, X, Y); else break; } } } } if (ERROR) borra_canvas(root30); g_signal_handlers_unblock_by_func (editable, (gpointer) callback_31, user_data); g_signal_stop_emission_by_name (editable, "changed"); g_free (cadena); g_array_free(pos_signos, TRUE); g_string_free(numerador, TRUE); g_string_free(denominador, TRUE); } void callback32 (GtkWidget *widget, gchar data) { gint i,j ; gboolean calcula=TRUE, semaforo=FALSE; cadena=gtk_editable_get_chars(GTK_EDITABLE(entry31),0,-1); if (llena_arrays(cadena)) numeros_grandes(); else { for (i=0; ilen; i++) if (g_array_index(denominadores, gint, i) == 0) calcula=FALSE; if (calcula==FALSE) muestra_error(_(" Algún denominador es CERO. \n No se puede dividir por 0 ")); else { while ((cadena[0]=='(')&&(cadena[strlen(cadena)-1]==')')) { semaforo=FALSE; for (i=1; ilen; i++) { if ((i!=0)&&(g_array_index(numeradores, gint32, i)<0)) g_string_append(num, "("); temporal =g_ascii_dtostr(buf, sizeof(buf), g_array_index(numeradores, gint32, i)); g_string_append(num, temporal); if ((i!=0)&&(g_array_index(numeradores, gint32, i)<0)) g_string_append(num, ")"); if (signos->str[i]=='+') num_resultado=num_resultado+g_array_index(numeradores, gint32, i+1); if (signos->str[i]=='-') num_resultado=num_resultado-g_array_index(numeradores, gint32, i+1); if (i+1!=numeradores->len) { if (signos->str[i]=='+') temporal="+"; if (signos->str[i]=='-') temporal="-"; g_string_append(num, temporal); } } dibuja_fraccion(num->str, denom->str, root32, X1, Y1); dibuja_signo2(root32, "=", X1, Y1); dibuja_fraccion(g_ascii_dtostr(buf, sizeof(buf), num_resultado), denom->str, root32, X1, Y1); den_final=g_array_index(denominadores, gint32, 0); num_final=num_resultado; g_string_free(num, TRUE); g_string_free(denom, TRUE); } gboolean on_entry31_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { if ((event->keyval == 0xFF0D)||(event->keyval == 0xFF8D)) Aceptar(); return FALSE; } void numeros_grandes() { gtk_widget_set_sensitive(boton32, FALSE); muestra_error(_("gMatESO no es un programa de cálculo científico.\nNo debes introducir números grandes, ni expresiones cuyos cálculos den lugar a números de más de 8 cifras")); }