diff --git a/TODO.md b/TODO.md index 3a3622e..4fe29d8 100644 --- a/TODO.md +++ b/TODO.md @@ -1,8 +1,6 @@ # TODO in libg1m ## Find out what these formats are/how to parse them -- G1L (languages for fx calculators?); -- G1N (???); -- G3L (languages for cg calculators); +- G1N (main menu icons); - G3M (like G1M?); - G1K/G3K (keys?). diff --git a/include/libg1m.h b/include/libg1m.h index b536505..839df6e 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -111,6 +111,33 @@ typedef struct { int revision; } g1m_version_t; +/* ************************************************************************** */ +/* E-activities related types */ +/* ************************************************************************** */ +/* line type */ +typedef enum { + g1m_linetype_title = 0x01, + g1m_linetype_text = 0x02, + g1m_linetype_picture = 0x04, + g1m_linetype_eact = 0x08 +} g1m_eact_line_type_t; + +/* line */ +typedef struct g1m_line_s { + int type; + + /* for subcontents */ + char name[17]; + + /* content */ + char *content; + + /* subcontents */ + int count; + int _size; + struct g1m_line_s **lines; +} g1m_line_t; + /* ************************************************************************** */ /* General types */ /* ************************************************************************** */ @@ -155,7 +182,9 @@ typedef struct { int width, height; uint32_t **pixels; /* 0x0RGB */ - /* TODO: e-activities */ + /* E-ACTIVITIES RELATED DATA */ + g1m_line_t *line; + g1m_line_t _linedata; } g1m_t; /* ************************************************************************** */ diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index 493d5cc..8e72030 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -110,6 +110,7 @@ G1M_PROTOTYPE_PIX(16bits) /* Parsing */ int g1m_parse(g1m_t *handle, FILE *stream); void g1m_free_mcs(g1m_t *handle); +void g1m_free_line_content(g1m_line_t *line); /* Checksum-ing */ uint32_t g1m_checksum32(void *mem, size_t size, uint32_t checksum); diff --git a/src/fontcharacter/string.c b/src/fontcharacter/string.c index f6ae561..14101c8 100644 --- a/src/fontcharacter/string.c +++ b/src/fontcharacter/string.c @@ -63,12 +63,10 @@ size_t g1m_fcstombs(char *dst, const FONTCHARACTER *src, size_t n) { char buf[2]; size_t len = 0; - - /* because last thing is for terminating zero */ - if (!n--) return (len); + n--; /* terminating character */ /* main loop */ - while (n) { + while (n--) { if (!*src) break ; diff --git a/src/parse/eact.c b/src/parse/eact.c index 03be42b..77ba911 100644 --- a/src/parse/eact.c +++ b/src/parse/eact.c @@ -9,23 +9,13 @@ /* ************************************************************************** */ #include -/* ************************************************************************** */ -/* Line correspondance type and prototype */ -/* ************************************************************************** */ -/* Correspondance type */ -struct eact_line_type_corresp { - int rawtype; - - int (*parse)(g1m_t*, uint8_t*, size_t); - char *info; -}; - -/* Correspondances tab prototype */ -static struct eact_line_type_corresp eact_line_types[]; - /* ************************************************************************** */ /* Content parsing */ /* ************************************************************************** */ +/* line content parsing function prototype */ +static int eact_parse_line(g1m_line_t *handle, uint8_t *buf, size_t size, + uint_fast8_t type); + /** * eact_parse_content_eact: * Parse an EACT in an EACT, from the subheader. @@ -36,7 +26,8 @@ static struct eact_line_type_corresp eact_line_types[]; * @return the error code (0 if ok). */ -static int eact_parse_content_eact(g1m_t *handle, uint8_t *buf, size_t bufsize) +static int eact_parse_content_eact(g1m_line_t *handle, uint8_t *buf, + size_t bufsize) { int err; @@ -56,11 +47,24 @@ static int eact_parse_content_eact(g1m_t *handle, uint8_t *buf, size_t bufsize) return (g1m_error_eof); struct line_descriptor *lds = (void*)&buf[sizeof(struct eact_eactheader)]; + /* prepare the handle */ + handle->type = g1m_linetype_eact; + handle->count = 0; + handle->_size = ehd.line_count; + handle->lines = malloc(sizeof(g1m_line_t*) * handle->_size); + if (!handle->lines) return (g1m_error_alloc); + bzero(handle->lines, sizeof(g1m_line_t*) * handle->_size); + /* browse the lines */ log_info("%d lines to browse", ehd.line_count); if (ehd.line_count) lds[0].entry_offset = be32toh(lds[0].entry_offset << 8); for (uint_fast32_t i = 0; i < ehd.line_count; i++) { + /* allocate line */ + g1m_line_t *line = malloc(sizeof(g1m_line_t)); + err = g1m_error_alloc; + if (!line) goto fail; + /* get line size * for this, we'll calculate the distance to the next line offset. * if there is no next line (last line), then the data left will be @@ -80,29 +84,29 @@ static int eact_parse_content_eact(g1m_t *handle, uint8_t *buf, size_t bufsize) uint_fast32_t entry_offset = lds[i].entry_offset; /* check if buffer is big enough */ + err = g1m_error_eof; if (entry_offset + linesize > bufsize) - return (g1m_error_eof); + goto loop_fail; /* look for the line type */ - struct eact_line_type_corresp *ltype = eact_line_types; - while (ltype->parse) { - if (ltype->rawtype == entry_type) - break; - ltype++; - } - if (!ltype->parse) { - log_error("[%ld] unknown line type: %02x", i + 1, entry_type); - continue; - } + err = eact_parse_line(line, &buf[entry_offset], linesize, entry_type); + if (err) goto loop_fail; - /* act */ - log_info("[%ld] is '%s' (0x%02x)", i + 1, ltype->info, entry_type); - if ((err = (*ltype->parse)(handle, &buf[entry_offset], linesize))) - return (err); + /* store and continue */ + handle->lines[handle->count++] = line; + continue; + + loop_fail: + g1m_free_line_content(line); + free(line); + goto fail; } /* no error */ return (0); +fail: + g1m_free_line_content(handle); + return (err); } /* ************************************************************************** */ @@ -112,7 +116,7 @@ static int eact_parse_content_eact(g1m_t *handle, uint8_t *buf, size_t bufsize) struct eact_content_type_corresp { char *type; - int (*parse)(g1m_t*, uint8_t*, size_t); + int (*parse)(g1m_line_t*, uint8_t*, size_t); }; /* Correspondance list */ @@ -124,48 +128,6 @@ static struct eact_content_type_corresp eact_content_types[] = { /* ************************************************************************** */ /* Line parsing */ /* ************************************************************************** */ -/** - * eact_parse_line_calculation: - * Parse a calculation. - * - * @arg handle the handle. - * @arg buf the buffer. - * @arg size the buffer size. - * @return the error code (0 if ok). - */ - -static int eact_parse_line_calculation(g1m_t *handle, uint8_t *buf, size_t size) -{ - (void)handle; - (void)buf; - (void)size; - /* TODO */ - log_info("Calculation raw data is:"); - logm_info(buf, size); - return (0); -} - -/** - * eact_parse_line_result: - * Parse a calculation result. - * - * @arg handle the handle. - * @arg buf the buffer. - * @arg size the buffer size. - * @return the error code (0 if ok). - */ - -static int eact_parse_line_result(g1m_t *handle, uint8_t *buf, size_t size) -{ - (void)handle; - (void)buf; - (void)size; - /* TODO */ - log_info("Calculation result raw data is:"); - logm_info(buf, size); - return (0); -} - /** * eact_parse_line_content: * Parse an E-Activity content. @@ -176,7 +138,8 @@ static int eact_parse_line_result(g1m_t *handle, uint8_t *buf, size_t size) * @return the error code (0 if ok). */ -static int eact_parse_line_content(g1m_t *handle, uint8_t *buf, size_t size) +static int eact_parse_line_content(g1m_line_t *handle, uint8_t *buf, + size_t size) { /* read content header */ size_t could_read = min(size, sizeof(struct eact_contentheader)); @@ -188,6 +151,10 @@ static int eact_parse_line_content(g1m_t *handle, uint8_t *buf, size_t size) log_info("Type is '%.8s'", hd.type); log_info("Name is '%.16s'", hd.name); + /* store info */ + handle->name[16] = 0; + strncpy(handle->name, (char*)hd.name, 16); + /* prepare for next */ if (size == could_read) return (0); @@ -215,6 +182,49 @@ static int eact_parse_line_content(g1m_t *handle, uint8_t *buf, size_t size) return (0); } +/** + * eact_parse_line_calculation: + * Parse a calculation. + * + * @arg handle the handle. + * @arg buf the buffer. + * @arg size the buffer size. + * @return the error code (0 if ok). + */ + +static int eact_parse_line_calculation(g1m_line_t *handle, uint8_t *buf, + size_t size) +{ + (void)handle; + (void)buf; + (void)size; + /* TODO */ + log_info("Calculation raw data is:"); + logm_info(buf, size); + return (0); +} + +/** + * eact_parse_line_result: + * Parse a calculation result. + * + * @arg handle the handle. + * @arg buf the buffer. + * @arg size the buffer size. + * @return the error code (0 if ok). + */ + +static int eact_parse_line_result(g1m_line_t *handle, uint8_t *buf, size_t size) +{ + (void)handle; + (void)buf; + (void)size; + /* TODO */ + log_info("Calculation result raw data is:"); + logm_info(buf, size); + return (0); +} + /** * eact_parse_line_stdheading: * Parse standard heading line. @@ -225,14 +235,19 @@ static int eact_parse_line_content(g1m_t *handle, uint8_t *buf, size_t size) * @return the error code (0 if ok). */ -static int eact_parse_line_stdheading(g1m_t *handle, uint8_t *buf, size_t size) +static int eact_parse_line_stdheading(g1m_line_t *handle, uint8_t *buf, + size_t size) { - (void)handle; - (void)buf; - (void)size; - /* TODO */ + /* log */ log_info("Standard heading raw data is:"); logm_info(buf, size); + + /* set handle info */ + handle->type = g1m_linetype_text; + handle->content = strdup((char*)buf); + if (!handle->content) return (g1m_error_alloc); + + /* no error */ return (0); } @@ -246,14 +261,23 @@ static int eact_parse_line_stdheading(g1m_t *handle, uint8_t *buf, size_t size) * @return the error code (0 if ok). */ -static int eact_parse_line_picture(g1m_t *handle, uint8_t *buf, size_t size) +static int eact_parse_line_picture(g1m_line_t *handle, uint8_t *buf, + size_t size) { - (void)handle; - (void)buf; - (void)size; - /* TODO */ + /* log */ log_info("Picture raw data is:"); logm_info(buf, size); + + /* get the size of the multi-byte string */ + size_t sz = g1m_fcstombs(NULL, (FONTCHARACTER*)buf, 0); + if (sz == (size_t)-1) return (g1m_error_magic); + + /* make the string */ + handle->content = malloc(sz + 1); + if (!handle->content) return (g1m_error_alloc); + g1m_fcstombs(handle->content, (FONTCHARACTER*)buf, 0); + + /* no error */ return (0); } @@ -267,14 +291,19 @@ static int eact_parse_line_picture(g1m_t *handle, uint8_t *buf, size_t size) * @return the error code (0 if ok). */ -static int eact_parse_line_text(g1m_t *handle, uint8_t *buf, size_t size) +static int eact_parse_line_text(g1m_line_t *handle, uint8_t *buf, size_t size) { - (void)handle; - (void)buf; - (void)size; - /* TODO */ + /* log */ log_info("Text raw data is:"); logm_info(buf, size); + + /* set handle info */ + handle->type = g1m_linetype_text; + handle->content = strdup((char*)buf); + if (!handle->content) return (g1m_error_alloc); + + /* TODO: manage text coloration */ + /* no error */ return (0); } @@ -288,7 +317,7 @@ static int eact_parse_line_text(g1m_t *handle, uint8_t *buf, size_t size) * @return the error code (0 if ok). */ -static int eact_parse_line_code(g1m_t *handle, uint8_t *buf, size_t size) +static int eact_parse_line_code(g1m_line_t *handle, uint8_t *buf, size_t size) { (void)handle; (void)buf; @@ -302,6 +331,14 @@ static int eact_parse_line_code(g1m_t *handle, uint8_t *buf, size_t size) /* ************************************************************************** */ /* Line Type correspondance list */ /* ************************************************************************** */ +/* Correspondance type */ +struct eact_line_type_corresp { + int rawtype; + + int (*parse)(g1m_line_t*, uint8_t*, size_t); + char *info; +}; + /* All correspondances */ static struct eact_line_type_corresp eact_line_types[] = { {eact_ltype_calc, eact_parse_line_calculation, @@ -321,6 +358,37 @@ static struct eact_line_type_corresp eact_line_types[] = { {} }; +/** + * eact_parse_line: + * Parse a line [content]. + * + * @arg handle the handle. + * @arg buf the buffer. + * @arg size the buffer size. + * @arg type the type. + * @return the error code (0 if ok). + */ + +static int eact_parse_line(g1m_line_t *handle, uint8_t *buf, size_t size, + uint_fast8_t type) +{ + /* look for the line type */ + struct eact_line_type_corresp *linetype = eact_line_types; + while (linetype->parse) { + if (linetype->rawtype == type) + break; + linetype++; + } + if (!linetype->parse) { + log_error("unknown line type: %02x", type); + return (0); + } + + /* act */ + log_info("line type is '%s' (0x%02x)", linetype->info, type); + return ((*linetype->parse)(handle, buf, size)); +} + /* ************************************************************************** */ /* Main parsing functions */ /* ************************************************************************** */ @@ -371,6 +439,9 @@ int g1m_parse_eact(g1m_t * handle, FILE *stream, uint8_t buf[bufsize]; READ(&buf, bufsize) + /* prepare handle */ + handle->line = &handle->_linedata; + /* parse content */ - return (eact_parse_line_content(handle, buf, bufsize)); + return (eact_parse_line_content(handle->line, buf, bufsize)); } diff --git a/src/user/free.c b/src/user/free.c index 8b687e9..0a36684 100644 --- a/src/user/free.c +++ b/src/user/free.c @@ -10,6 +10,28 @@ #include #include +/** + * g1m_free_line_content: + * Free an e-activity line content. + * + * @arg handle the line handle. + */ + +void g1m_free_line_content(g1m_line_t *line) +{ + if (line->type & (g1m_linetype_title | g1m_linetype_text + | g1m_linetype_picture)) + free(line->content); + + if (line->type & g1m_linetype_eact) { + for (int i = 0; i < line->count; i++) { + g1m_free_line_content(line->lines[i]); + free(line->lines[i]); + } + free(line->lines); + } +} + /** * g1m_free_mcsfile: * Free an MCS file handle. @@ -108,6 +130,10 @@ void g1m_free(g1m_t *handle) if (handle->type & g1m_type_picture) free(handle->pixels); + /* e-activities time! */ + if (handle->type & g1m_type_eact) + g1m_free_line_content(handle->line); + /* free the handle */ free(handle); }