Reorganized some sources, added some manpages and BCD utilities, corrected MCS parsing error
This commit is contained in:
parent
31130131c6
commit
ab03cc8228
|
@ -0,0 +1,46 @@
|
|||
G1M_ERROR(3)
|
||||
============
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: libg1m
|
||||
:man manual: libg1m manual
|
||||
|
||||
NAME
|
||||
----
|
||||
g1m_error - all errors from libg1m
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,c]
|
||||
----
|
||||
#include <libg1m.h>
|
||||
|
||||
int err = g1m_some_function(handle, ...);
|
||||
if (err) switch (err) {
|
||||
case g1m_error_...:
|
||||
/* oh my god! they killed kenny! */
|
||||
break;
|
||||
}
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Every function in libg1m returns either zero if everything went alright, or
|
||||
the code of the error that happened. The error codes are the following:
|
||||
|
||||
*g1m_error_nostream*::
|
||||
Provided or generated stream was *NULL*.
|
||||
*g1m_error_noread*::
|
||||
Stream was not readable.
|
||||
*g1m_error_magic*::
|
||||
File might be corrupted.
|
||||
*g1m_error_eof*::
|
||||
Unexpected End Of File.
|
||||
|
||||
String descriptions of the error can be dynamically obtained by using
|
||||
*g1m_strerror*(3).
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libg1m*(3),
|
||||
*g1m_strerror*(3)
|
|
@ -0,0 +1,36 @@
|
|||
G1M_FCTOMB(3)
|
||||
=============
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: libg1m
|
||||
:man manual: libg1m manual
|
||||
|
||||
NAME
|
||||
----
|
||||
g1m_fctomb - FONTCHARACTER to multi-byte
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,c]
|
||||
----
|
||||
#include <libg1m.h>
|
||||
|
||||
int g1m_fctomb(char *s, FONTCHARACTER fc);
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Convert a FONTCHARACTER character to its multibyte representation,
|
||||
and stores it at the beginning of the character array pointed to by
|
||||
*s*.
|
||||
|
||||
The programmer must ensure that there is room for at least 2 bytes at
|
||||
*s*.
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
This function returns the length of the calculated multibyte function.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libg1m*(3), *g1m_mbtofc*(3)
|
|
@ -0,0 +1 @@
|
|||
g1m_open.3.txt
|
|
@ -0,0 +1,37 @@
|
|||
G1M_FREE(3)
|
||||
=========
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: libg1m
|
||||
:man manual: libg1m manual
|
||||
|
||||
NAME
|
||||
----
|
||||
g1m_free - free a handle
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,c]
|
||||
----
|
||||
#include <libg1m.h>
|
||||
|
||||
void g1m_free(g1m_t *handle);
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Frees a handle opened with *g1m_open*(3) or *g1m_fopen*(3).
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
This function returns zero if everything went well, and the error code
|
||||
otherwise.
|
||||
|
||||
ERRORS
|
||||
------
|
||||
See *g1m_error*(3).
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libg1m*(3),
|
||||
*g1m_open*(3)
|
|
@ -0,0 +1,41 @@
|
|||
G1M_OPEN(3)
|
||||
=========
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: libg1m
|
||||
:man manual: libg1m manual
|
||||
|
||||
NAME
|
||||
----
|
||||
g1m_open, g1m_fopen - open and decode a file
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,c]
|
||||
----
|
||||
#include <libg1m.h>
|
||||
|
||||
int g1m_open(g1m_t **handle, const char *path);
|
||||
int g1m_fopen(g1m_t **handle, FILE *stream);
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Open and decode a file. If everything goes well, the handle is stored at
|
||||
**handle*.
|
||||
|
||||
For *g1m_fopen*, the stream only requires reading (writing and seeking
|
||||
capabilities are not required).
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
This function returns zero if everything went well, and the error code
|
||||
otherwise.
|
||||
|
||||
ERRORS
|
||||
------
|
||||
See *g1m_error*(3).
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libg1m*(3)
|
|
@ -0,0 +1,32 @@
|
|||
G1M_STRERROR(3)
|
||||
===============
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: libg1m
|
||||
:man manual: libg1m manual
|
||||
|
||||
NAME
|
||||
----
|
||||
g1m_strerror - get error string of a libg1m error
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,c]
|
||||
----
|
||||
#include <libg1m.h>
|
||||
|
||||
const char g1m_strerror(int err);
|
||||
|
||||
printf("Couldn't perform action: %s\n", g1m_strerror(g1m_error_nostream));
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Get the string description of a libg1m error.
|
||||
|
||||
Never use an invalid error code! It could cause a segfault.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libg1m*(3),
|
||||
*g1m_error*(3)
|
|
@ -14,12 +14,32 @@ SYNOPSIS
|
|||
[source,c]
|
||||
----
|
||||
#include <libg1m.h>
|
||||
|
||||
g1m_t *handle;
|
||||
int err = g1m_open(&handle, "TEST.g1m");
|
||||
if (err) {
|
||||
printf("Could not open file: %s\n", g1m_strerror(err));
|
||||
if (err == g1m_error_nostream)
|
||||
printf("Could not open stream because: %s\n", strerror(errno));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (handle->type & g1m_type_addin)
|
||||
printf("Add-in internal name is '%s'\n", handle->internal_name);
|
||||
else
|
||||
printf("Not an add-in!\n");
|
||||
|
||||
g1m_free(handle);
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
libg1m enables reading (parsing) and writing of g** files : g1m, g1a.
|
||||
libg1m is a library meant to decode CASIO's
|
||||
g[1-3]* files : g1m/g1r, g1a, g1e, g3a, g3e, g3p.
|
||||
Its aim is to support everything with a Standard Header.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*g1m_open(3)*
|
||||
*g1m_open*(3),
|
||||
*g1m_free*(3),
|
||||
*g1m_error*(3)
|
||||
|
|
|
@ -35,6 +35,23 @@ struct bcd {
|
|||
/* ************************************************************************** */
|
||||
/* BCD utilities */
|
||||
/* ************************************************************************** */
|
||||
/* none yet -- TODO */
|
||||
/* Arithmetic */
|
||||
int g1m_bcd_is_nonzero(struct bcd *bcd);
|
||||
|
||||
/* String/BCD */
|
||||
char *g1m_bcdtoa(struct bcd *bcd);
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Inline BCD utilities */
|
||||
/* ************************************************************************** */
|
||||
/* check if BCD number is negative */
|
||||
static inline int g1m_bcd_is_negative(struct bcd *bcd)
|
||||
{
|
||||
return ((bcd->BCDval[0] & 0xf0) >= 0x50);
|
||||
}
|
||||
|
||||
/* macros */
|
||||
# define g1m_bcd_is_positive(B) (~g1m_bcd_is_negative(B) & 1)
|
||||
# define g1m_bcd_is_zero(B) (!g1m_bcd_is_nonzero(B))
|
||||
|
||||
#endif /* LIBG1M_BCD_H */
|
||||
|
|
|
@ -20,9 +20,14 @@
|
|||
* Keep in mind that all numbers in the MCS format are BCD-encoded.
|
||||
* Because of some precision issue, we'll deliver them to the user as is.
|
||||
*
|
||||
* So now we are not restricted to only one part. Remember the `number` field
|
||||
* of the Standard Header? Well, it's the number of parts there is.
|
||||
* And each part have a header, so let's describe it here. */
|
||||
* So now we are not restricted to one part. Remember the `number` field in
|
||||
* the Standard Header? We once thought it was the number of parts to come.
|
||||
* But no. In general, we have one subpart per part, but in some case, we
|
||||
* have more, like for the LISTFILEs. And that is how we realized the `number`
|
||||
* in the Standard Header wasn't the number of parts, but the total number
|
||||
* of subparts.
|
||||
*
|
||||
* Each part have a header, and here it is: */
|
||||
|
||||
struct mcs_subheader {
|
||||
/* main ID ("PROGRAM", zero padded) */
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* utils/bcd.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* libg1m/internals/bcd.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/11/03 01:02:10 |___/ */
|
||||
/* Last updated: 2016/11/21 16:15:37 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
#ifndef LIBG1M_INTERNALS_BCD_H
|
||||
# define LIBG1M_INTERNALS_BCD_H
|
||||
# include <libg1m/bcd.h>
|
||||
# include <string.h>
|
||||
# define upr(N) ((bytes[(N)] & 0xf0) >> 4)
|
||||
# define lwr(N) (bytes[(N)] & 0xf)
|
||||
|
||||
/* BCD-related utilities could go here. TODO.
|
||||
* Things that would be cool:
|
||||
* - Basic operations (adding, substracting, multiplying);
|
||||
* - BCD/float conversions.
|
||||
*
|
||||
* Things that would be 20% cooler:
|
||||
* - A GNU libc printf conversion function. */
|
||||
int g1m_bcd_get_exponent(struct bcd *bcd);
|
||||
int g1m_bcd_get_exponent_neg(struct bcd *bcd, int *neg);
|
||||
|
||||
#endif /* LIBG1M_INTERNALS_BCD_H */
|
|
@ -0,0 +1,38 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* bcd/get_exponent.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/11/21 16:14:08 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals/bcd.h>
|
||||
|
||||
/**
|
||||
* g1m_bcd_get_exponent:
|
||||
* Get exponent.
|
||||
*/
|
||||
|
||||
int g1m_bcd_get_exponent(struct bcd *bcd)
|
||||
{
|
||||
unsigned char *bytes = bcd->BCDval;
|
||||
|
||||
int exp = upr(0) * 100 + lwr(0) * 10 + upr(1);
|
||||
return ((exp % 500) - 99);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_bcd_get_exponent_neg:
|
||||
* Get exponent and if it is negative.
|
||||
*/
|
||||
|
||||
int g1m_bcd_get_exponent_neg(struct bcd *bcd, int *neg)
|
||||
{
|
||||
unsigned char *bytes = bcd->BCDval;
|
||||
|
||||
*neg = 0;
|
||||
int exp = upr(0) * 100 + lwr(0) * 10 + upr(1);
|
||||
if (exp >= 500) exp -= 500, *neg = 1;
|
||||
return (exp - 99);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* bcd/is_zero.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/11/21 16:07:53 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals/bcd.h>
|
||||
|
||||
/**
|
||||
* g1m_bcd_is_nonzero:
|
||||
* Check if a BCD is zero.
|
||||
*
|
||||
* @arg bcd pointer to the bcd.
|
||||
* @return true or false.
|
||||
*/
|
||||
|
||||
|
||||
int g1m_bcd_is_nonzero(struct bcd *bcd)
|
||||
{
|
||||
static struct bcd ref = {.BCDval = {}};
|
||||
unsigned char *bytes = bcd->BCDval;
|
||||
|
||||
return (lwr(1) | memcmp(&bytes[2], &ref.BCDval[2], 7));
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* bcd/to_ascii.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/11/21 13:54:41 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals/bcd.h>
|
||||
#define VISIBLE_PRECISION 5
|
||||
|
||||
/**
|
||||
* g1m_bcdtoa:
|
||||
* Simple BCD to string function.
|
||||
*
|
||||
* @arg bcd The BCD number.
|
||||
* @return The allocated string.
|
||||
*/
|
||||
|
||||
char *g1m_bcdtoa(struct bcd *bcd)
|
||||
{
|
||||
char buf[50], *p = buf;
|
||||
unsigned char *bytes = bcd->BCDval;
|
||||
|
||||
/* get the exponent */
|
||||
int neg = 0;
|
||||
int exp = g1m_bcd_get_exponent_neg(bcd, &neg);
|
||||
if (neg) *p++ = '-';
|
||||
|
||||
/* get the mantissa */
|
||||
char mant[15];
|
||||
for (int i = 0; i < 15; i += 2)
|
||||
mant[i] = lwr(i / 2 + 1);
|
||||
for (int i = 1; i < 15; i += 2)
|
||||
mant[i] = upr(i / 2 + 2);
|
||||
|
||||
/* calculate number of significant digits */
|
||||
int signif;
|
||||
for (signif = 15; signif && !mant[signif - 1]; signif--);
|
||||
if (!signif) exp = 0;
|
||||
|
||||
/* put integer part */
|
||||
int num = 0;
|
||||
if (exp > 0) {
|
||||
while (exp > 0 && signif) {
|
||||
exp--;
|
||||
signif--;
|
||||
*p++ = mant[num++] + '0';
|
||||
}
|
||||
if (exp > 0 && exp < VISIBLE_PRECISION) while (exp) {
|
||||
exp--;
|
||||
*p++ = '0';
|
||||
}
|
||||
} else
|
||||
*p++ = '0';
|
||||
|
||||
/* put decimal part */
|
||||
if (signif) {
|
||||
*p++ = '.';
|
||||
/* put some zeroes */
|
||||
if (exp < 0 && exp > -VISIBLE_PRECISION) while (exp) {
|
||||
exp++;
|
||||
*p++ = '0';
|
||||
}
|
||||
/* put the numbers */
|
||||
while (signif--)
|
||||
*p++ = mant[num++] + '0';
|
||||
}
|
||||
|
||||
/* put exponent */
|
||||
if (exp) {
|
||||
*p++ = '^';
|
||||
int exp_neg = exp < 0;
|
||||
if (exp_neg) {
|
||||
*p++ = '(';
|
||||
*p++ = '-';
|
||||
exp = -exp;
|
||||
}
|
||||
int eprec = 100;
|
||||
while (exp < eprec)
|
||||
eprec /= 10;
|
||||
while (eprec) {
|
||||
*p++ = exp / eprec + '0';
|
||||
exp %= eprec;
|
||||
eprec /= 10;
|
||||
}
|
||||
if (exp_neg) *p++ = ')';
|
||||
}
|
||||
|
||||
/* put string end */
|
||||
*p = 0;
|
||||
|
||||
/* duplicate and send to user */
|
||||
return (strdup(buf));
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* fontcharacter/character.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/11/21 13:29:30 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/fontcharacter.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* g1m_mbtofc:
|
||||
* Multi-byte to FONTCHARACTER.
|
||||
*
|
||||
* Based on what is said in the fx-9860G SDK.
|
||||
* Let's hope it stays true.
|
||||
*
|
||||
* Based on how `mbtowc` works.
|
||||
*
|
||||
* @arg pfc pointer to the FONTCHARACTER character.
|
||||
* @arg s the multi-byte source string.
|
||||
* @arg n the size of the source buffer.
|
||||
* @return the number of bytes used (-1 if error).
|
||||
*/
|
||||
|
||||
int g1m_mbtofc(FONTCHARACTER *pfc, const char *s, size_t n)
|
||||
{
|
||||
/* null string? */
|
||||
if (!s)
|
||||
return (2);
|
||||
|
||||
/* no space? */
|
||||
if (!n)
|
||||
return (-1);
|
||||
|
||||
/* extended char? */
|
||||
if (strchr("\x7F\xF7\xF9\xE5\x56\x57", *s))
|
||||
{
|
||||
if (n < 2) return (-1);
|
||||
*pfc = (*s << 8) + *(s + 1);
|
||||
return (2);
|
||||
}
|
||||
|
||||
/* single-byte character */
|
||||
*pfc = *s;
|
||||
return (*s != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_fctomb:
|
||||
* FONTCHARACTER to multi-byte.
|
||||
*
|
||||
* Based on the same document, and on how `wctomb` works.
|
||||
*
|
||||
* Do you think a battery has self-consciousness?
|
||||
*
|
||||
* @arg s pointer to the multi-byte string.
|
||||
* @arg fc the FONTCHARACTER character.
|
||||
* @return the
|
||||
*/
|
||||
|
||||
int g1m_fctomb(char *s, FONTCHARACTER fc)
|
||||
{
|
||||
/* no string? */
|
||||
if (!s)
|
||||
return (2);
|
||||
|
||||
/* extended? */
|
||||
if (fc > 0xff) {
|
||||
*s++ = fc >> 8;
|
||||
*s = fc & 0xff;
|
||||
return (2);
|
||||
}
|
||||
|
||||
/* normal char. */
|
||||
*s = fc;
|
||||
return (fc != 0);
|
||||
}
|
|
@ -1,89 +1,15 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* utils/fontcharacter.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* fontcharacter/string.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/11/03 00:56:55 |___/ */
|
||||
/* Last updated: 2016/11/21 13:29:30 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
#include <libg1m/fontcharacter.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Single character conversion */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* g1m_mbtofc:
|
||||
* Multi-byte to FONTCHARACTER.
|
||||
*
|
||||
* Based on what is said in the fx-9860G SDK.
|
||||
* Let's hope it stays true.
|
||||
*
|
||||
* Based on how `mbtowc` works.
|
||||
*
|
||||
* @arg pfc pointer to the FONTCHARACTER character.
|
||||
* @arg s the multi-byte source string.
|
||||
* @arg n the size of the source buffer.
|
||||
* @return the number of bytes used (-1 if error).
|
||||
*/
|
||||
|
||||
int g1m_mbtofc(FONTCHARACTER *pfc, const char *s, size_t n)
|
||||
{
|
||||
/* null string? */
|
||||
if (!s)
|
||||
return (2);
|
||||
|
||||
/* no space? */
|
||||
if (!n)
|
||||
return (-1);
|
||||
|
||||
/* extended char? */
|
||||
if (strchr("\x7F\xF7\xF9\xE5\x56\x57", *s))
|
||||
{
|
||||
if (n < 2) return (-1);
|
||||
*pfc = (*s << 8) + *(s + 1);
|
||||
return (2);
|
||||
}
|
||||
|
||||
/* single-byte character */
|
||||
*pfc = *s;
|
||||
return (*s != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_fctomb:
|
||||
* FONTCHARACTER to multi-byte.
|
||||
*
|
||||
* Based on the same document, and on how `wctomb` works.
|
||||
*
|
||||
* Do you think a battery has self-consciousness?
|
||||
*
|
||||
* @arg s pointer to the multi-byte string.
|
||||
* @arg fc the FONTCHARACTER character.
|
||||
* @return the
|
||||
*/
|
||||
|
||||
int g1m_fctomb(char *s, FONTCHARACTER fc)
|
||||
{
|
||||
/* no string? */
|
||||
if (!s)
|
||||
return (2);
|
||||
|
||||
/* extended? */
|
||||
if (fc > 0xff) {
|
||||
*s++ = fc >> 8;
|
||||
*s = fc & 0xff;
|
||||
return (2);
|
||||
}
|
||||
|
||||
/* normal char. */
|
||||
*s = fc;
|
||||
return (fc != 0);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* String conversion */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* g1m_mbstofcs:
|
||||
* Multi-byte string to FONTCHARACTER string.
|
|
@ -165,7 +165,9 @@ static int g1m_parse_mcs_spreadsheet(g1m_mcsfile_t *handle, FILE *stream,
|
|||
cells_count++;
|
||||
|
||||
/* log it */
|
||||
log_info("[%ld, %ld] not empty.", c, i);
|
||||
char *bcd_string = g1m_bcdtoa(&cell);
|
||||
log_info("[%ld, %ld] contains '%s'.", c, i, bcd_string);
|
||||
free(bcd_string);
|
||||
}
|
||||
|
||||
/* iterate bit and rd */
|
||||
|
@ -236,8 +238,6 @@ static int g1m_parse_mcs_list(g1m_mcsfile_t *handle, FILE *stream,
|
|||
size_t elsize = sizeof(struct bcd) * elcount;
|
||||
struct bcd real[elcount];
|
||||
struct bcd imgn[elcount];
|
||||
bzero(real, elsize);
|
||||
bzero(imgn, elsize);
|
||||
|
||||
/* browse real elements */
|
||||
log_info("Browsing %d list elements", elcount);
|
||||
|
@ -246,10 +246,11 @@ static int g1m_parse_mcs_list(g1m_mcsfile_t *handle, FILE *stream,
|
|||
|
||||
/* browse imaginary elements */
|
||||
if (size) {
|
||||
log_info("Browsing their complex parts");
|
||||
log_info("They have complex parts!");
|
||||
size_t toread = min(size, elsize);
|
||||
READ(&imgn, toread)
|
||||
}
|
||||
} else
|
||||
bzero(imgn, elsize);
|
||||
|
||||
/* fill final tab */
|
||||
handle->rows = elcount;
|
||||
|
@ -264,6 +265,20 @@ static int g1m_parse_mcs_list(g1m_mcsfile_t *handle, FILE *stream,
|
|||
|
||||
/* main copying loop */
|
||||
for (uint_fast32_t y = 0; y < elcount; y++) {
|
||||
/* log */
|
||||
#if LOGLEVEL <= ll_info
|
||||
char *real_string = g1m_bcdtoa(&real[y]);
|
||||
if (g1m_bcd_is_zero(&imgn[y]))
|
||||
log_info("Cell #%ld is %s.", y, real_string);
|
||||
else {
|
||||
char *imgn_string = g1m_bcdtoa(&imgn[y]);
|
||||
log_info("Cell #%ld is %s+%si.", y, real_string, imgn_string);
|
||||
free(imgn_string);
|
||||
}
|
||||
free(real_string);
|
||||
#endif
|
||||
|
||||
/* prepare index and store */
|
||||
tab[y] = &rws[y];
|
||||
tab[y][0] = (g1m_mcs_cell_t){
|
||||
.used = 1,
|
||||
|
@ -505,9 +520,10 @@ int g1m_parse_mcs(g1m_t *handle, FILE *stream, uint_fast16_t num)
|
|||
int err = g1m_error_alloc;
|
||||
|
||||
/* No "global" header for MCS parts, because this "global header"
|
||||
* was the standard header.
|
||||
* allocate memory for the subparts */
|
||||
handle->part_count = num;
|
||||
* was the standard header. */
|
||||
|
||||
/* allocate memory for the subparts */
|
||||
handle->part_count = 0;
|
||||
handle->_parts_size = num;
|
||||
handle->parts = malloc(sizeof(g1m_mcs_t*) * num);
|
||||
if (!handle->parts) return (g1m_error_alloc);
|
||||
|
@ -534,9 +550,14 @@ int g1m_parse_mcs(g1m_t *handle, FILE *stream, uint_fast16_t num)
|
|||
if (!pmcs[i]) goto fail;
|
||||
g1m_mcs_t *mcs = pmcs[i];
|
||||
|
||||
/* increment parts count, and remove to num the "extra" subparts */
|
||||
handle->part_count++;
|
||||
num -= hd.subcount - 1;
|
||||
|
||||
/* prepare it */
|
||||
mcs->file_count = hd.subcount;
|
||||
mcs->_files_size = hd.subcount;
|
||||
if (!hd.subcount) continue;
|
||||
mcs->files = malloc(sizeof(g1m_mcsfile_t*) * hd.subcount);
|
||||
if (!mcs->files) goto fail;
|
||||
bzero(mcs->files, sizeof(g1m_mcsfile_t*) * hd.subcount);
|
||||
|
|
Reference in New Issue