juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

modes_gfx.c (17072B)


      1 /* modes_gfx.c - pantallas de los modos en pixeles (Ecuaciones, Tabla, Grafico, Estadistica). */
      2 #include <string.h>
      3 #include "calc_gfx.h"
      4 #include "dmath.h"
      5 #include "str.h"
      6 
      7 #define BG      RGB(18, 22, 30)
      8 #define PANEL   RGB(30, 36, 50)
      9 #define FG      RGB(236, 236, 236)
     10 #define DIM     RGB(130, 138, 156)
     11 #define ACC     RGB(255, 200, 60)
     12 #define RESC    RGB(140, 220, 255)
     13 #define SEL     RGB(48, 58, 80)
     14 #define CURS    RGB(255, 226, 0)
     15 #define ERRC    RGB(255, 100, 90)
     16 #define FCOL    RGB(120, 200, 255)
     17 #define GCOL    RGB(255, 140, 90)
     18 
     19 int eq_cells(int type);
     20 const char *stat_type_name(int t);
     21 void graph_trace(Calc *c);
     22 
     23 extern Layout g_lay[];                 /* render.c */
     24 #define L_in g_lay[0]
     25 #define L_v  (g_lay + 1)
     26 static Expr tmp;
     27 
     28 /* z = re + im i como expresion */
     29 static void cplx_expr(const Calc *c, const Cplx *z, Expr *out)
     30 {
     31     static Expr a;
     32     bool im0 = !z->im.v.m;
     33     calc_result_expr(c, &z->re, false, out);
     34     if (im0) return;
     35     Num im = z->im;
     36     bool neg = im.v.neg;
     37     if (neg) im = num_neg(im);
     38     calc_result_expr(c, &im, false, &a);
     39     out->cur = out->n;
     40     if (!z->re.v.m) { ex_clear(out); if (neg) ex_insert_raw(out, '-'); }
     41     else ex_insert_raw(out, neg ? '-' : '+');
     42     bool one = im.exact && ex_is_int(&im.x) && im.x.a == 1;
     43     if (!one) ex_insert_expr(out, &a);
     44     ex_insert_raw(out, 'i');
     45 }
     46 
     47 static void val_text(const Calc *c, const Num *v, bool err, char *b, int n)
     48 {
     49     if (err || num_bad(v)) { str_put(b, n, 0, "Error"); return; }
     50     fmt_plain(v, &c->fmt, false, b, n);
     51 }
     52 
     53 static void header(Surface *s, const Calc *c, const char *title)
     54 {
     55     gfx_rect(s, 0, 0, 320, 320, BG);
     56     gfx_rect(s, 0, 0, 320, 14, PANEL);
     57     cf_text(s, &cf_small, 3, 1, calc_ang_name(c->ang), FG);
     58     if (c->shift) { gfx_rect(s, 14, 1, 9, 12, ACC); cf_text(s, &cf_small, 16, 1, "S", BG); }
     59     const char *t = c->msg[0] ? c->msg : title;
     60     cf_text(s, &cf_small, 160 - cf_text_w(&cf_small, t) / 2, 1, t, c->msg[0] ? ACC : DIM);
     61 }
     62 
     63 static void help(Surface *s, const char *t)
     64 {
     65     gfx_rect(s, 0, 306, 320, 14, PANEL);
     66     cf_text(s, &cf_small, 4, 307, t, DIM);
     67 }
     68 
     69 /* caja de edicion abajo (con la entrada c->in) */
     70 static int input_box(Surface *s, const Calc *c, const char *label, int y)
     71 {
     72     int h = L_in.asc + L_in.desc;
     73     if (h < 15) h = 15;
     74     gfx_rect(s, 0, y, 320, h + 8, PANEL);
     75     gfx_rect(s, 0, y, 320, 1, ACC);
     76     int x = 6;
     77     if (label) x += cf_text(s, &cf_big, 6, y + 4 + L_in.asc - 11, label, ACC) + 4;
     78     int sc = 0, cx = L_in.gx[c->in.cur];
     79     if (x + cx > 310) sc = x + cx - 310;
     80     gfx_clip(s, x, y + 1, 316 - x, h + 6);
     81     layout_draw(s, &L_in, x - sc, y + 4, FG, c->in.cur, CURS);
     82     gfx_noclip(s);
     83     return h + 8;
     84 }
     85 
     86 /* ------------------------------------------------------------ ecuaciones */
     87 
     88 static const char *const EQ_TITLE[] = { "Sistema 2×2", "Sistema 3×3", "Polinomio de grado 2", "Polinomio de grado 3", "SOLVE" };
     89 
     90 static void eqn_paint(Surface *s, Calc *c)
     91 {
     92     EqnState *q = &c->eq;
     93     header(s, c, EQ_TITLE[q->type]);
     94     char b[80];
     95     if (q->type == EQ_SOLVE && q->phase == 0) {
     96         cf_text(s, &cf_bold, 8, 24, "Ecuación con X (sin = es = 0):", ACC);
     97         int p = str_put(b, sizeof b, 0, "Empieza a buscar en X = ");
     98         fmt_plain(&c->vars[VAR_X], &c->fmt, true, b + p, (int)sizeof b - p);
     99         cf_text(s, &cf_small, 8, 44, b, DIM);
    100         input_box(s, c, 0, 200);
    101         help(s, "Enter resuelve   Esc borra / cambia el tipo");
    102         return;
    103     }
    104     if (q->phase == 0) {
    105         static const char *const HDR[][4] = {
    106             { "a", "b", "c" }, { "a", "b", "c", "d" }, { "a", "b", "c" }, { "a", "b", "c", "d" } };
    107         static const char *const FORM_TXT[] = { "a·x + b·y = c", "a·x + b·y + c·z = d", "a·x² + b·x + c = 0", "a·x³ + b·x² + c·x + d = 0" };
    108         cf_text(s, &cf_big, 8, 22, FORM_TXT[q->type], DIM);
    109         int cols = q->type == EQ_SYS2 || q->type == EQ_POLY2 ? 3 : 4;
    110         int rows = eq_cells(q->type) / cols, cw = 300 / cols;
    111         for (int j = 0; j < cols; j++) cf_text(s, &cf_bold, 12 + j * cw + cw / 2 - 4, 46, HDR[q->type][j], ACC);
    112         for (int i = 0; i < rows; i++)
    113             for (int j = 0; j < cols; j++) {
    114                 int k = i * cols + j, x = 10 + j * cw, y = 64 + i * 26;
    115                 bool sel = k == q->sel;
    116                 gfx_box(s, x, y, cw - 4, 22, sel ? SEL : PANEL, sel ? ACC : RGB(50, 58, 76));
    117                 val_text(c, &q->coef[k], false, b, sizeof b);
    118                 gfx_clip(s, x + 2, y, cw - 8, 22);
    119                 cf_text(s, &cf_big, x + cw - 8 - cf_text_w(&cf_big, b), y + 5, b, FG);
    120                 gfx_noclip(s);
    121             }
    122         if (q->editing) input_box(s, c, "=", 250);
    123         help(s, q->editing ? "Enter guarda   Esc cancela" : "Tipeá un valor   Enter resuelve   Esc tipo");
    124         return;
    125     }
    126     /* soluciones */
    127     int y = 26;
    128     if (q->note[0]) { cf_text(s, &cf_bold, 10, 40, q->note, ERRC); help(s, "Esc vuelve"); return; }
    129     static const char *const VN[] = { "x", "y", "z" };
    130     static const char *const XN[] = { "x1", "x2", "x3" };
    131     int n = q->nsol;
    132     if (q->type == EQ_SOLVE) {
    133         calc_result_expr(c, &q->solve_x, false, &tmp);
    134         layout_expr(&tmp, &METRIC_PX, &L_v[0]);
    135         cf_text(s, &cf_bold, 10, y + L_v[0].asc - 11, "X =", ACC);
    136         layout_draw(s, &L_v[0], 50, y, RESC, -1, 0);
    137         y += L_v[0].asc + L_v[0].desc + 12;
    138         int p = str_put(b, sizeof b, 0, "L-R = ");
    139         fmt_plain(&q->solve_lr, &c->fmt, true, b + p, (int)sizeof b - p);
    140         cf_text(s, &cf_big, 10, y, b, DIM);
    141         help(s, "Esc vuelve a la ecuación (X quedó guardado)");
    142         return;
    143     }
    144     for (int i = 0; i < n; i++) {
    145         cplx_expr(c, &q->sol[i], &tmp);
    146         layout_expr(&tmp, &METRIC_PX, &L_v[i]);
    147         const char *nm = q->type <= EQ_SYS3 ? VN[i] : XN[i];
    148         bool sel = i == q->shown;
    149         int h = L_v[i].asc + L_v[i].desc;
    150         if (sel) gfx_rect(s, 4, y - 3, 312, h + 6, SEL);
    151         cf_text(s, &cf_bold, 10, y + L_v[i].asc - 11, nm, ACC);
    152         cf_text(s, &cf_big, 34, y + L_v[i].asc - 11, "=", DIM);
    153         layout_draw(s, &L_v[i], 50, y, RESC, -1, 0);
    154         y += h + 12;
    155     }
    156     if (q->type == EQ_POLY2 && q->nsol) {
    157         bool mx = q->coef[0].v.neg;
    158         cf_text(s, &cf_small, 10, y, mx ? "Máximo:" : "Mínimo:", DIM);
    159         y += 14;
    160         calc_result_expr(c, &q->sol[2].re, false, &tmp);
    161         layout_expr(&tmp, &METRIC_PX, &L_v[4]);
    162         calc_result_expr(c, &q->sol[2].im, false, &tmp);
    163         layout_expr(&tmp, &METRIC_PX, &L_v[5]);
    164         cf_text(s, &cf_big, 10, y + L_v[4].asc - 11, "x =", DIM);
    165         layout_draw(s, &L_v[4], 50, y, FG, -1, 0);
    166         y += L_v[4].asc + L_v[4].desc + 8;
    167         cf_text(s, &cf_big, 10, y + L_v[5].asc - 11, "y =", DIM);
    168         layout_draw(s, &L_v[5], 50, y, FG, -1, 0);
    169     }
    170     help(s, "↑↓ elige   Tab decimal   Esc vuelve");
    171 }
    172 
    173 /* ------------------------------------------------------------ tabla */
    174 
    175 static void table_paint(Surface *s, Calc *c)
    176 {
    177     TableState *t = &c->tb;
    178     header(s, c, "Tabla");
    179     char b[64];
    180     if (t->phase < 2) {
    181         cf_text(s, &cf_bold, 8, 24, t->phase == 0 ? "f(x) =" : "g(x) =", ACC);
    182         cf_text(s, &cf_small, 8, 44, "Escribí la función con x (o X). Enter sigue.", DIM);
    183         if (t->phase == 1) {
    184             cf_text(s, &cf_small, 8, 60, "f(x) ya está. ↑ vuelve a f(x).", DIM);
    185         }
    186         input_box(s, c, t->phase == 0 ? "f(x)=" : "g(x)=", 200);
    187         help(s, "Enter: rango de la tabla   Esc borra");
    188         return;
    189     }
    190     int cols = t->use_g ? 3 : 2, cw = 310 / cols;
    191     static const char *const H[] = { "x", "f(x)", "g(x)" };
    192     for (int j = 0; j < cols; j++) cf_text(s, &cf_bold, 8 + j * cw + cw - 10 - cf_text_w(&cf_bold, H[j]), 18, H[j], ACC);
    193     gfx_rect(s, 4, 33, 312, 1, DIM);
    194     int rows = 15;
    195     if (t->sel < t->top) t->top = t->sel;
    196     if (t->sel >= t->top + rows) t->top = t->sel - rows + 1;
    197     for (int r = t->top; r < t->rows && r < t->top + rows; r++) {
    198         int y = 36 + (r - t->top) * 16;
    199         if (r == t->sel) gfx_rect(s, 4, y - 1, 312, 16, SEL);
    200         for (int j = 0; j < cols; j++) {
    201             const Num *v = j == 0 ? &t->x[r] : j == 1 ? &t->fx[r] : &t->gx[r];
    202             bool err = j == 1 ? t->ferr[r] : j == 2 ? t->gerr[r] : false;
    203             val_text(c, v, err, b, sizeof b);
    204             gfx_clip(s, 8 + j * cw, y, cw - 4, 16);
    205             int w = cf_text_w(&cf_big, b);
    206             cf_text(s, &cf_big, 8 + j * cw + cw - 10 - w, y + 1, b, err ? ERRC : j ? RESC : FG);
    207             gfx_noclip(s);
    208         }
    209     }
    210     if (!t->rows) cf_text(s, &cf_big, 10, 60, "No hay filas (revisá el rango)", ERRC);
    211     /* valor completo de la fila elegida */
    212     if (t->rows) {
    213         calc_result_expr(c, &t->fx[t->sel], false, &tmp);
    214         layout_expr(&tmp, &METRIC_PX, &L_v[0]);
    215         gfx_rect(s, 0, 280 - L_v[0].asc - L_v[0].desc, 320, L_v[0].asc + L_v[0].desc + 26, PANEL);
    216         if (!t->ferr[t->sel]) layout_draw(s, &L_v[0], 312 - L_v[0].w, 296 - L_v[0].asc - L_v[0].desc, RESC, -1, 0);
    217     }
    218     help(s, "↑↓ recorre   Enter/Esc edita f(x)");
    219 }
    220 
    221 /* ------------------------------------------------------------ grafico */
    222 
    223 #define GY0 15
    224 #define GH  262
    225 
    226 static int gy_of(Dec y, const GraphState *g)
    227 {
    228     Dec r = dec_div(dec_mul_int(dec_sub(g->ymax, y), GH - 1), dec_sub(g->ymax, g->ymin));
    229     int64_t v;
    230     if (!dec_to_int(dec_round_int(r), &v) || v < -10000 || v > 10000) return r.neg ? -10000 : 10000;
    231     return (int)v;
    232 }
    233 
    234 static int gx_of(Dec x, const GraphState *g)
    235 {
    236     Dec r = dec_div(dec_mul_int(dec_sub(x, g->xmin), 319), dec_sub(g->xmax, g->xmin));
    237     int64_t v;
    238     if (!dec_to_int(dec_round_int(r), &v) || v < -10000 || v > 10000) return r.neg ? -10000 : 10000;
    239     return (int)v;
    240 }
    241 
    242 /* paso "lindo" de la grilla: 1, 2 o 5 por 10^k, unas 8 divisiones */
    243 static Dec nice_step(Dec span)
    244 {
    245     Dec s = dec_div_int(span, 8);
    246     if (!s.m) return DEC_ONE;
    247     Dec p = dec_scale10(DEC_ONE, s.e);
    248     Dec m = dec_div(s, p);
    249     int64_t k;
    250     dec_to_int(dec_round_int(m), &k);
    251     k = k <= 1 ? 1 : k <= 3 ? 2 : k <= 7 ? 5 : 10;
    252     return dec_mul_int(p, k);
    253 }
    254 
    255 static void curve(Surface *s, const int16_t *ys, Color col)
    256 {
    257     for (int i = 0; i < 320; i++) {
    258         if (ys[i] == INT16_MIN) continue;
    259         int y = ys[i];
    260         if (i > 0 && ys[i - 1] != INT16_MIN) {
    261             int py = ys[i - 1];
    262             if ((py < -GH || py > 2 * GH) && (y < -GH || y > 2 * GH)) continue;
    263             if (py - y < GH && y - py < GH) {
    264                 int a = py < y ? py : y, b = py < y ? y : py;
    265                 if (a < 0) a = 0;
    266                 if (b > GH - 1) b = GH - 1;
    267                 if (a <= b && b - a > 0) gfx_rect(s, i, GY0 + a, 1, b - a + 1, col);
    268                 continue;
    269             }
    270         }
    271         if (y >= 0 && y < GH) gfx_rect(s, i, GY0 + y, 1, 1, col);
    272     }
    273 }
    274 
    275 static void graph_paint(Surface *s, Calc *c)
    276 {
    277     GraphState *g = &c->gr;
    278     header(s, c, "Gráfico");
    279     char b[96];
    280     if (g->phase < 2) {
    281         cf_text(s, &cf_bold, 8, 24, g->phase == 0 ? "f(x) =" : "g(x) =", g->phase == 0 ? FCOL : GCOL);
    282         cf_text(s, &cf_small, 8, 44, "Escribí la función con x. Enter grafica.", DIM);
    283         cf_text(s, &cf_small, 8, 58, g->phase == 0 ? "↓ agrega una segunda función g(x)." : "↑ vuelve a f(x). Esc la saca.", DIM);
    284         input_box(s, c, g->phase == 0 ? "f(x)=" : "g(x)=", 200);
    285         help(s, "Enter grafica   w ventana (en el gráfico)");
    286         return;
    287     }
    288     gfx_clip(s, 0, GY0, 320, GH);
    289     /* grilla */
    290     Dec stx = nice_step(dec_sub(g->xmax, g->xmin)), sty = nice_step(dec_sub(g->ymax, g->ymin));
    291     Dec x0 = dec_mul(dec_floor(dec_div(g->xmin, stx)), stx);
    292     for (int i = 0; i < 40; i++) {
    293         Dec x = dec_add(x0, dec_mul_int(stx, i));
    294         if (dec_cmp(x, g->xmax) > 0) break;
    295         int px = gx_of(x, g);
    296         if (px >= 0 && px < 320) gfx_rect(s, px, GY0, 1, GH, RGB(30, 36, 48));
    297     }
    298     Dec y0 = dec_mul(dec_floor(dec_div(g->ymin, sty)), sty);
    299     for (int i = 0; i < 40; i++) {
    300         Dec y = dec_add(y0, dec_mul_int(sty, i));
    301         if (dec_cmp(y, g->ymax) > 0) break;
    302         int py = gy_of(y, g);
    303         if (py >= 0 && py < GH) gfx_rect(s, 0, GY0 + py, 320, 1, RGB(30, 36, 48));
    304     }
    305     /* ejes */
    306     int ax = gx_of(DEC_ZERO, g), ay = gy_of(DEC_ZERO, g);
    307     if (ax >= 0 && ax < 320) gfx_rect(s, ax, GY0, 1, GH, DIM);
    308     if (ay >= 0 && ay < GH) gfx_rect(s, 0, GY0 + ay, 320, 1, DIM);
    309     if (g->use_g) curve(s, g->gy, GCOL);
    310     curve(s, g->fy, FCOL);
    311     /* trazo */
    312     gfx_rect(s, g->tx, GY0, 1, GH, RGB(70, 70, 40));
    313     const int16_t *ys = g->curve ? g->gy : g->fy;
    314     if (ys[g->tx] != INT16_MIN && ys[g->tx] >= 0 && ys[g->tx] < GH) gfx_disc(s, g->tx, GY0 + ys[g->tx], 3, CURS);
    315     gfx_noclip(s);
    316     /* datos abajo */
    317     gfx_rect(s, 0, GY0 + GH, 320, 306 - GY0 - GH, PANEL);
    318     Dec x = dec_add(g->xmin, dec_div_int(dec_mul_int(dec_sub(g->xmax, g->xmin), g->tx), 319));
    319     Num xn = num_dec(dec_round_sig(x, 10));
    320     int p = str_put(b, sizeof b, 0, "x=");
    321     p = fmt_plain(&xn, &c->fmt, true, b + p, 40) + p;
    322     p = str_put(b, sizeof b, p, g->curve ? "  g=" : "  f=");
    323     if (num_bad(&g->tval)) str_put(b, sizeof b, p, "-");
    324     else fmt_plain(&g->tval, &c->fmt, true, b + p, (int)sizeof b - p);
    325     cf_text(s, &cf_small, 4, GY0 + GH + 1, b, g->curve ? GCOL : FCOL);
    326     help(s, "← → traza  ↑↓ curva  + - zoom  w ventana  Esc edita");
    327 }
    328 
    329 /* ------------------------------------------------------------ estadistica */
    330 
    331 static void stat_paint(Surface *s, Calc *c)
    332 {
    333     StatState *t = &c->st;
    334     header(s, c, stat_type_name(t->type));
    335     char b[64];
    336     if (t->phase == 1) {
    337         int rows = 18;
    338         if (t->rtop > t->nres - rows) t->rtop = t->nres > rows ? t->nres - rows : 0;
    339         for (int i = t->rtop; i < t->nres && i < t->rtop + rows; i++) {
    340             int y = 20 + (i - t->rtop) * 16;
    341             cf_text(s, &cf_bold, 10, y, t->rlabel[i], ACC);
    342             val_text(c, &t->rval[i], t->rerr[i], b, sizeof b);
    343             cf_text(s, &cf_big, 310 - cf_text_w(&cf_big, b), y, b, RESC);
    344         }
    345         help(s, "↑↓ recorre   Esc vuelve a los datos");
    346         return;
    347     }
    348     int cols = t->type == ST_1VAR ? 1 : 2;
    349     cf_text(s, &cf_bold, 40, 18, "x", ACC);
    350     if (cols == 2) cf_text(s, &cf_bold, 190, 18, "y", ACC);
    351     gfx_rect(s, 4, 33, 312, 1, DIM);
    352     int rows = t->editing ? 12 : 15;
    353     if (t->row < t->top) t->top = t->row;
    354     if (t->row >= t->top + rows) t->top = t->row - rows + 1;
    355     for (int r = t->top; r <= t->n && r < t->top + rows; r++) {
    356         int y = 36 + (r - t->top) * 16;
    357         str_int(b, sizeof b, 0, r + 1);
    358         cf_text(s, &cf_small, 6, y + 2, b, DIM);
    359         for (int j = 0; j < cols; j++) {
    360             int x = 30 + j * 150;
    361             bool sel = r == t->row && j == t->col;
    362             if (sel) gfx_rect(s, x, y - 1, 146, 16, SEL);
    363             if (r < t->n) {
    364                 val_text(c, j ? &t->y[r] : &t->x[r], false, b, sizeof b);
    365                 cf_text(s, &cf_big, x + 140 - cf_text_w(&cf_big, b), y, b, FG);
    366             }
    367         }
    368     }
    369     if (t->editing) input_box(s, c, "=", 250);
    370     help(s, t->editing ? "Enter guarda   Esc cancela" : "Tipeá valores  Supr borra fila  Enter resultados");
    371 }
    372 
    373 /* ------------------------------------------------------------ matrices */
    374 
    375 static void matrix_paint(Surface *s, Calc *c)
    376 {
    377     MatState *t = &c->mt;
    378     const MVal *m = t->target < 4 ? &t->m[t->target] : &t->v[t->target - 4];
    379     char title[24], b[64];
    380     int p = str_put(title, sizeof title, 0, t->target < 4 ? "Mat" : "Vct");
    381     char l[2] = { (char)('A' + t->target % 4), 0 };
    382     str_put(title, sizeof title, p, l);
    383     header(s, c, title);
    384     cf_text(s, &cf_bold, 10, 20, title, ACC);
    385     int cw = 300 / m->c;
    386     if (cw > 90) cw = 90;
    387     for (int i = 0; i < m->r; i++)
    388         for (int j = 0; j < m->c; j++) {
    389             int k = i * m->c + j, x = 10 + j * cw, y = 44 + i * 26;
    390             bool sel = k == t->sel;
    391             gfx_box(s, x, y, cw - 4, 22, sel ? SEL : PANEL, sel ? ACC : RGB(50, 58, 76));
    392             val_text(c, mv_get(m, i, j), false, b, sizeof b);
    393             gfx_clip(s, x + 2, y, cw - 8, 22);
    394             cf_text(s, &cf_big, x + cw - 8 - cf_text_w(&cf_big, b), y + 5, b, FG);
    395             gfx_noclip(s);
    396         }
    397     if (t->editing) input_box(s, c, "=", 250);
    398     help(s, t->editing ? "Enter guarda   Esc cancela" : "Tipeá un valor   = otra   Enter/Esc a las cuentas");
    399 }
    400 
    401 /* ------------------------------------------------------------ despacho */
    402 
    403 void modes_prepare(Calc *c)
    404 {
    405     layout_expr(&c->in, &METRIC_PX, &L_in);
    406     if (c->mode == MODE_GRAPH && c->gr.phase == 2) {
    407         c->gr.w = 320;
    408         c->gr.h = GH;
    409         if (!c->gr.ready) { graph_compute(c); graph_trace(c); }
    410     }
    411 }
    412 
    413 void modes_paint(Surface *s, Calc *c)
    414 {
    415     switch (c->mode) {
    416     case MODE_EQN: eqn_paint(s, c); break;
    417     case MODE_TABLE: table_paint(s, c); break;
    418     case MODE_GRAPH: graph_paint(s, c); break;
    419     case MODE_STAT: stat_paint(s, c); break;
    420     case MODE_MATRIX: matrix_paint(s, c); break;
    421     }
    422 }