diff --git a/eeshow/diff.c b/eeshow/diff.c index bda0f08..4dca702 100644 --- a/eeshow/diff.c +++ b/eeshow/diff.c @@ -161,7 +161,7 @@ static void *diff_init(int argc, char *const *argv) for (arg = optind; arg != argc - 1; arg++) if (!lib_parse(&new_lib, argv[arg], &sch_file)) goto fail_parse; - if (!sch_parse(&new_sch, &sch_file, &new_lib)) + if (!sch_parse(&new_sch, &sch_file, &new_lib, NULL)) goto fail_parse; file_close(&sch_file); diff --git a/eeshow/gui.c b/eeshow/gui.c index c3668e8..4e8c953 100644 --- a/eeshow/gui.c +++ b/eeshow/gui.c @@ -66,6 +66,7 @@ struct gui_hist { /* caching support */ void **oids; /* file object IDs */ + struct sch_ctx sch_ctx; struct lib lib; /* combined library */ struct gui_hist *next; @@ -964,7 +965,6 @@ static const struct sheet *parse_files(struct gui_hist *hist, int n_args, char **args, bool recurse, const struct gui_hist *prev) { char *rev = NULL; - struct sch_ctx sch_ctx; struct file sch_file; struct file lib_files[n_args - 1]; int libs_open, i; @@ -974,13 +974,13 @@ static const struct sheet *parse_files(struct gui_hist *hist, if (hist->vcs_hist) rev = vcs_git_get_rev(hist->vcs_hist); - sch_init(&sch_ctx, recurse); + sch_init(&hist->sch_ctx, recurse); ok = file_open_revision(&sch_file, rev, args[n_args - 1], NULL); if (rev) free(rev); if (!ok) { - sch_free(&sch_ctx); + sch_free(&hist->sch_ctx); return NULL; } @@ -1010,7 +1010,8 @@ static const struct sheet *parse_files(struct gui_hist *hist, if (!lib_parse_file(&hist->lib, lib_files +i)) goto fail; - if (!sch_parse(&sch_ctx, &sch_file, &hist->lib)) + if (!sch_parse(&hist->sch_ctx, &sch_file, &hist->lib, + libs_cached ? &prev->sch_ctx : NULL)) goto fail; for (i = 0; i != libs_open; i++) @@ -1024,12 +1025,12 @@ static const struct sheet *parse_files(struct gui_hist *hist, * with - when sharing unchanged item - possibly many duplicate * pointers. */ - return sch_ctx.sheets; + return hist->sch_ctx.sheets; fail: while (libs_open--) file_close(lib_files + libs_open); - sch_free(&sch_ctx); + sch_free(&hist->sch_ctx); lib_free(&hist->lib); file_close(&sch_file); return NULL; diff --git a/eeshow/main.c b/eeshow/main.c index e678df6..841cbf7 100644 --- a/eeshow/main.c +++ b/eeshow/main.c @@ -215,7 +215,7 @@ found: optind = 0; /* reset getopt */ - if (!sch_parse(&sch_ctx, &sch_file, &lib)) + if (!sch_parse(&sch_ctx, &sch_file, &lib, NULL)) return 1; file_close(&sch_file); diff --git a/eeshow/sch-parse.c b/eeshow/sch-parse.c index 2959f50..0ce5c85 100644 --- a/eeshow/sch-parse.c +++ b/eeshow/sch-parse.c @@ -288,9 +288,9 @@ static struct sheet *new_sheet(struct sch_ctx *ctx) sheet->next_obj = &sheet->objs; sheet->next = NULL; - sheet->children = NULL; - sheet->next_child = &sheet->children; - sheet->next_sib = NULL; + sheet->has_children = 0; + + sheet->oid = NULL; sheet->parent = ctx->curr_sheet; ctx->curr_sheet = sheet; @@ -312,27 +312,44 @@ static void end_sheet(struct sch_ctx *ctx) static bool parse_line(const struct file *file, void *user, const char *line); +#include static const struct sheet *recurse_sheet(struct sch_ctx *ctx, const struct file *related) { const char *name = ctx->obj.u.sheet.file; struct sheet *sheet; struct file file; + void *oid; bool res; if (!file_open(&file, name, related)) return NULL; + sheet = new_sheet(ctx); + oid = file_oid(&file); + sheet->oid = oid; + + if (ctx->prev && oid) { + const struct sheet *other; + + for (other = ctx->prev->sheets; other; other = other->next) + if (!other->has_children && + file_oid_eq(other->oid, oid)) { + end_sheet(ctx); + sheet->title = other->title; + sheet->objs = other->objs; + return sheet; + } + } + ctx->state = sch_descr; res = file_read(&file, parse_line, ctx); file_close(&file); if (!res) - return NULL; /* caller MUST clean up */ + return NULL; /* leave it to caller to clean up */ end_sheet(ctx); - *ctx->curr_sheet->next_child = sheet; - ctx->curr_sheet->next_child = &sheet->next_sib; - sheet->next_sib = NULL; + ctx->curr_sheet->has_children = 1; return sheet; } @@ -560,9 +577,11 @@ static bool parse_line(const struct file *file, void *user, const char *line) } -bool sch_parse(struct sch_ctx *ctx, struct file *file, const struct lib *lib) +bool sch_parse(struct sch_ctx *ctx, struct file *file, const struct lib *lib, + const struct sch_ctx *prev) { ctx->lib = lib; + ctx->prev = prev; return file_read(file, parse_line, ctx); } @@ -611,6 +630,7 @@ static void free_sheet(struct sheet *sch) if (!sch) return; free((char *) sch->title); + free(sch->oid); for (obj = sch->objs; obj; obj = next) { next = obj->next; switch (obj->type) { diff --git a/eeshow/sch.h b/eeshow/sch.h index 4bb08f9..4d2e534 100644 --- a/eeshow/sch.h +++ b/eeshow/sch.h @@ -99,9 +99,10 @@ struct sheet { struct sheet *parent; struct sheet *next; - struct sheet *children; /* "child" sub-sheets */ - struct sheet **next_child; - struct sheet *next_sib; /* siblings sub-sheets of this sheet */ + bool has_children; /* aka sub-sheets */ + + /* caching */ + void *oid; }; struct sch_ctx { @@ -115,6 +116,9 @@ struct sch_ctx { struct sheet *sheets; struct sheet **next_sheet; + /* for caching */ + const struct sch_ctx *prev; + const struct lib *lib; }; @@ -122,7 +126,8 @@ struct sch_ctx { void decode_alignment(struct text *txt, char hor, char vert); void sch_render(const struct sheet *sheet); -bool sch_parse(struct sch_ctx *ctx, struct file *file, const struct lib *lib); +bool sch_parse(struct sch_ctx *ctx, struct file *file, const struct lib *lib, + const struct sch_ctx *prev); void sch_init(struct sch_ctx *ctx, bool recurse); void sch_free(struct sch_ctx *ctx);