From 692f58c421a9b045c45bca6185fa2b441bd7d62b Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Fri, 5 Dec 2014 16:04:27 -0500 Subject: [PATCH] start on grid cell allocation so we can get to displaying text ;) NB: unfinished yet Signed-off-by: Chris Michael --- src/bin/grid.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++- src/bin/grid.h | 52 ++++++++++- 2 files changed, 297 insertions(+), 2 deletions(-) diff --git a/src/bin/grid.c b/src/bin/grid.c index b3b0e74..0020e03 100644 --- a/src/bin/grid.c +++ b/src/bin/grid.c @@ -230,13 +230,188 @@ _smart_size(Evas_Object *obj, int w, int h, Eina_Bool force) _selection_set(obj, EINA_FALSE); - /* TODO: call grid resize function to allocate cells */ + /* call grid resize function to allocate cells */ + _grid_resize(obj, w, h); _smart_calculate(obj); evas_event_thaw(sd->evas); } +static void +_grid_cell_copy(Grid *sd, Grid_Cell *src, Grid_Cell *dst, int n) +{ + int i = 0; + + for (; i < n; i++) + { + /* TODO */ + /* _handle_block_codepoint_overwrite(sd, dst[i].codepoint, src[i].codepoint); */ + dst[i] = src[i]; + } +} + +static void +_grid_limit_coord(Grid *sd, Grid_State *state) +{ + state->wrapnext = 0; + if (state->cx >= sd->w) state->cx = sd->w - 1; + if (state->cy >= sd->h) state->cy = sd->h - 1; + if (state->had_cr_x >= sd->w) state->had_cr_x = sd->w - 1; + if (state->had_cr_y >= sd->h) state->had_cr_y = sd->h - 1; +} + +ssize_t +_grid_line_length(const Grid_Cell *cells, ssize_t nb_cells) +{ + ssize_t len = nb_cells; + + for (len = nb_cells - 1; len >= 0; len--) + { + const Grid_Cell *cell; + + cell = cells + len; + if ((cell->codepoint != 0) && (cell->att.bg != COL_INVIS)) + return len + 1; + } + + return 0; +} + +static int +_grid_line_find_top(Grid *sd, int y_end, int *top) +{ + int y_start = y_end; + + while (y_start > 0) + { + if (GRID_CELLS(sd, sd->w - 1, y_start - 1).att.autowrapped) + y_start--; + else + { + *top = y_start; + return 0; + } + } + while (-y_start < sd->backscroll_num) + { + Grid_Save *gs; + + gs = sd->back[(y_start + sd->backpos - 1 + sd->backmax) % sd->backmax]; + if (gs) + gs = _grid_save_extract(gs); + if (!gs) return -1; + + sd->back[(y_start + sd->backpos - 1 + sd->backmax) % sd->backmax] = gs; + if (gs->cell[gs->w - 1].att.autowrapped) + y_start--; + else + { + *top = y_start; + return 0; + } + } + *top = y_start; + return 0; +} + +static int +_grid_line_rewrap(Grid *sd, int y_start, int y_end, Grid_Cell *cells2, Grid_Save **back2, int w2, int y2_end, int *new_y2_start) +{ + int x, x2, y, y2, y2_start; + int len, len_last, len_remaining, copy_width, ts2_width; + Grid_Save *gs, *gs2; + Grid_Cell *line, *line2 = NULL; + + if (y_end >= 0) + len_last = _grid_line_length(&GRID_CELLS(sd, 0, y_end), sd->w); + else + { + gs = _grid_save_extract(sd->back[(y_end + sd->backpos + + sd->backmax) % sd->backmax]); + if (!gs) return -1; + sd->back[(y_end + sd->backpos + sd->backmax) % sd->backmax] = gs; + len_last = gs->w; + } + len_remaining = len_last + (y_end - y_start) * sd->w; + y2_start = y2_end; + if (len_remaining) + y2_start -= (len_remaining + w2 - 1) / w2 - 1; + else + { + if (y2_start < 0) + back2[y2_start + sd->backmax] = _grid_save_new(0); + *new_y2_start = y2_start; + return 0; + } + if (-y2_start > sd->backmax) + { + y_start += ((-y2_start - sd->backmax) * w2) / sd->w; + x = ((-y2_start - sd->backmax) * w2) % sd->w; + len_remaining -= (-y2_start - sd->backmax) * w2; + y2_start = -sd->backmax; + } + else + x = 0; + + y = y_start; + x2 = 0; + y2 = y2_start; + + while (y <= y_end) + { + if (y >= 0) + line = &GRID_CELLS(sd, 0, y); + else + { + gs = _grid_save_extract(sd->back[(y + sd->backpos + + sd->backmax) % sd->backmax]); + if (!gs) return -1; + sd->back[(y + sd->backpos + sd->backmax) % sd->backmax] = gs; + line = gs->cell; + } + if (y == y_end) + len = len_last; + else + len = sd->w; + line[len - 1].att.autowrapped = 0; + while (x < len) + { + copy_width = MIN(len - x, w2 - x2); + if (x2 == 0) + { + if (y2 >= 0) + line2 = cells2 + (y2 * w2); + else + { + ts2_width = MIN(len_remaining, w2); + gs2 = _grid_save_new(ts2_width); + if (!gs2) return -1; + line2 = gs2->cell; + back2[y2 + sd->backmax] = gs2; + } + } + if (line2) + { + _grid_cell_copy(sd, line + x, line2 + x2, copy_width); + x += copy_width; + x2 += copy_width; + len_remaining -= copy_width; + if ((x2 == w2) && (y2 != y2_end)) + { + line2[x2 - 1].att.autowrapped = 1; + x2 = 0; + y2++; + } + } + } + x = 0; + y++; + } + *new_y2_start = y2_start; + return 0; +} + /* external functions */ Evas_Object * _grid_add(Evas *evas) @@ -323,3 +498,73 @@ _grid_window_set(Evas_Object *obj, Evas_Object *win) if (!(sd = evas_object_smart_data_get(obj))) return; sd->win = win; } + +void +_grid_resize(Evas_Object *obj, int nw, int nh) +{ + Grid *sd; + Grid_Cell *new_cells = NULL; + Grid_Save **new_back = NULL; + int y_start, y_end, new_y_start = 0, new_y_end, i; + + /* try to get the objects smart data */ + if (!(sd = evas_object_smart_data_get(obj))) return; + + if ((sd->w == nw) && (sd->h == nh)) return; + if ((nw == nh) && (nw == 1)) return; + + _grid_save_freeze(); + + new_cells = calloc(1, sizeof(Grid_Cell) * nw * nh); + if (!new_cells) goto err; + + free(sd->cells2); + sd->cells2 = calloc(1, sizeof(Grid_Cell) * nw * nh); + if (!sd->cells2) goto err; + + new_back = calloc(sizeof(Grid_Save *), sd->backmax); + + y_end = sd->state.cy; + new_y_end = nh - 1; + while ((y_end >= -sd->backscroll_num) && (new_y_end >= -sd->backmax)) + { + if (_grid_line_find_top(sd, y_end, &y_start) < 0) goto err; + if (_grid_line_rewrap(sd, y_start, y_end, new_cells, + new_back, nw, new_y_end, + &new_y_start) < 0) + goto err; + y_end = y_start - 1; + new_y_end = new_y_start - 1; + } + + free(sd->cells); + sd->cells = new_cells; + for (i = 1; i <= sd->backscroll_num; i++) + _grid_save_free(sd->back[(sd->backpos - i + sd->backmax) % sd->backmax]); + free(sd->back); + sd->back = new_back; + + sd->w = nw; + sd->h = nh; + sd->state.cy = MIN((nh - 1) - new_y_start, nh - 1); + sd->state.cx = _grid_line_length(new_cells + ((nh - 1) * nw), nw); + sd->circular_offset = MAX(new_y_start, 0); + sd->backpos = 0; + sd->backscroll_num = MAX(-new_y_start, 0); + sd->state.had_cr = 0; + + /* if (altbuf) termpty_screen_swap(ty); */ + + _grid_limit_coord(sd, &(sd->state)); + _grid_limit_coord(sd, &(sd->swap)); + _grid_limit_coord(sd, &(sd->save)); + + _grid_save_thaw(); + + return; + +err: + _grid_save_thaw(); + free(new_cells); + free(new_back); +} diff --git a/src/bin/grid.h b/src/bin/grid.h index c68dd32..cd77a38 100644 --- a/src/bin/grid.h +++ b/src/bin/grid.h @@ -1,6 +1,20 @@ #ifndef _GRID_H_ # define _GRID_H_ 1 +#define COL_DEF 0 +#define COL_BLACK 1 +#define COL_RED 2 +#define COL_GREEN 3 +#define COL_YELLOW 4 +#define COL_BLUE 5 +#define COL_MAGENTA 6 +#define COL_CYAN 7 +#define COL_WHITE 8 +#define COL_INVIS 9 + +#define COL_INVERSE 10 +#define COL_INVERSEBG 11 + typedef struct _Grid_Att Grid_Att; struct _Grid_Att { @@ -59,6 +73,33 @@ struct _Grid_Save_Comp unsigned int wout; // output width in Grid_Cells }; +typedef struct _Grid_State Grid_State; +struct _Grid_State +{ + int cx, cy; + Grid_Att att; + unsigned char charset; + unsigned char charsetch; + unsigned char chset[4]; + int scroll_y1, scroll_y2; + int had_cr_x, had_cr_y; + int margin_top; // soon, more to come... + unsigned int multibyte : 1; + unsigned int alt_kp : 1; + unsigned int insert : 1; + unsigned int appcursor : 1; + unsigned int wrap : 1; + unsigned int wrapnext : 1; + unsigned int hidecursor : 1; + unsigned int crlf : 1; + unsigned int had_cr : 1; + unsigned int send_bs : 1; + unsigned int kbd_lock : 1; + unsigned int reverse : 1; + unsigned int no_autorepeat : 1; + unsigned int cjk_ambiguous_wide : 1; +}; + typedef struct _Grid Grid; struct _Grid { @@ -70,10 +111,12 @@ struct _Grid int w, h; - int backmax, backpos; + int circular_offset, circular_offset2; + int backmax, backpos, backscroll_num; Grid_Cell *cells, *cells2; Grid_Save **back; + Grid_State state, save, swap; struct { @@ -98,5 +141,12 @@ struct _Grid Evas_Object *_grid_add(Evas *evas); void _grid_update(Evas_Object *obj); void _grid_window_set(Evas_Object *obj, Evas_Object *win); +void _grid_resize(Evas_Object *obj, int nw, int nh); + +#define GRID_CELLS(SD, X, Y) \ + SD->cells[X + (((Y + SD->circular_offset) % SD->h) * SD->w)] + +#define GRID_FMTCLR(ATT) \ + (ATT).autowrapped = (ATT).newline = (ATT).tab = 0 #endif