Exemple #1
0
bool lay_init_su( const char *p, su *in_su )
{
    bool        cvterr  = true;
    const char  *pa = NULL;     // start of value text
    char        *ps = NULL;     // destination for value text
    char        sign;
    size_t      len;
    su          *s;

    s = in_su;
    pa = p;
    ps = s->su_txt;
    *ps = '\0';

    while( *p && (*p == ' ' ) ) {   // just in case
        p++;
    }
    while( *p && (*p != ' ' ) ) {
        p++;
    }
    len = p - pa;

    if( (len + 1) > MAX_SU_CHAR ) {                 // won't fit
        xx_line_err( err_inv_att_val, val_start );
        scan_start = scan_stop;
        return( cvterr );
    }
    memcpy( ps, pa, len );
    ps[len] = '\0';

    s->su_u = SU_undefined;
    if( *ps == '+' ) {                   // not allowed with tags
        xx_line_err( err_inv_att_val, ps );
        scan_start = scan_stop;
        return( cvterr );
    } else if( *ps == '-' ) {            // not relative, just negative
        sign = *ps;
        if( *(ps + 1) == '+' || *(ps + 1) == '-' ) {  // only one sign is allowed
            xx_line_err( err_inv_att_val, ps );
            scan_start = scan_stop;
            return( cvterr );
        }
    } else {
        sign = '+';
    }
    if( !*ps ) {                          // value end reached, not valid
        xx_line_err( err_inv_att_val, ps );
        scan_start = scan_stop;
        return( cvterr );
    }
    s->su_relative = false;             // no relative positioning with tags

    if( su_layout_special( in_su ) ) {
        cvterr = false;
    } else {
        cvterr = internal_to_su( in_su, true, pa );
    }

    return( cvterr );
}
Exemple #2
0
bool att_val_to_su( su * in_su, bool pos )
{
    bool        cvterr  = true;
    char    *   ps      = NULL; // destination for value text
    char        sign;
    su      *   s;

    s = in_su;
    ps = s->su_txt;
    *ps = '\0';

    if( (val_len + 1) > MAX_SU_CHAR ) {             // won't fit
        xx_line_err( err_inv_att_val, val_start );
        scan_start = scan_stop;
        return( cvterr );
    }
    memcpy( ps, val_start, val_len );
    ps[val_len] = '\0';

    s->su_u = SU_undefined;
    if( *ps == '+' ) {                   // not allowed with tags
        xx_line_err( err_inv_att_val, ps );
        scan_start = scan_stop;
        return( cvterr );
    } else if( *ps == '-' ) {            // not relative, just negative
        if( pos ) {                     // value must be positive
            xx_line_err( err_inv_att_val, ps );
            scan_start = scan_stop;
            return( cvterr );
        }
        sign = *ps;
        if( *(ps + 1) == '+' || *(ps + 1) == '-' ) {  // only one sign is allowed
            xx_line_err( err_inv_att_val, ps );
            scan_start = scan_stop;
            return( cvterr );
        }
    } else {
        sign = '+';
    }
    if( !*ps ) {                          // value end reached, not valid
        xx_line_err( err_inv_att_val, ps );
        scan_start = scan_stop;
        return( cvterr );
    }
    s->su_relative = false;             // no relative positioning with tags

    if( su_layout_special( in_su ) ) {
        cvterr = false;
    } else {
        cvterr = internal_to_su( in_su, true, val_start );
    }

    return( cvterr );
}
Exemple #3
0
bool    att_val_to_SU( su * converted, bool pos )
{
    bool        converterror    = true;
    bool        is_cp           = false;
    char    *   p               = NULL; // source of value text
    char    *   pd              = NULL; // ptr to decimal point
    char    *   pd1             = NULL; // ptr to 0.1 decimal
    char    *   pdn             = NULL; // ptr to last digit +1
    char    *   ps              = NULL; // destination for value text
    char    *   pu              = NULL; // ptr to trailing unit
    char        sign;
    char        unit[4];
    int         i;
    ldiv_t      div;
    long        k;
    long        wh;
    long        wd;
    su      *   s;

    if( (val_len + 1) > MAX_SU_CHAR ) {             // won't fit
        xx_line_err( err_inv_att_val, val_start );
        scan_start = scan_stop + 1;
        return( converterror );
    }
    unit[3] = '\0';
    unit[2] = '\0';
    unit[1] = '\0';
    unit[0] = '\0';
    s = converted;
    p = val_start;
    ps = s->su_txt;
    *ps = '\0';
    wd = 0;
    wh = 0;

    s->su_u = SU_undefined;
    if( *p == '+' ) {                   // not allowed with tags
        xx_line_err( err_inv_att_val, p );
        scan_start = scan_stop + 1;
        return( converterror );
    } else if( *p == '-' ) {            // not relative, just negative
        if( pos ) {                     // value must be positive
            xx_line_err( err_inv_att_val, p );
            scan_start = scan_stop + 1;
            return( converterror );
        }
        sign = *p;
        *ps++ = *p++;
        if( *p == '+' || *p == '-' ) {  // only one sign is allowed
            xx_line_err( err_inv_att_val, p );
            scan_start = scan_stop + 1;
            return( converterror );
        }
    } else {
        sign = '+';
    }
    if( (p - val_start) >= val_len ) {  // value end reached, not valid
        xx_line_err( err_inv_att_val, p );
        scan_start = scan_stop + 1;
        return( converterror );
    }
    s->su_relative = false;             // no relative positioning with tags

    /***********************************************************************/
    /*  Special for layout :BANREGION                                      */
    /***********************************************************************/

    if( isalpha( *p ) ) {
        converterror = su_layout_special( &p, converted );
        if( !converterror ) {
            return( converterror );         // layout special ok
        }
    }

    for( i = 0; i < 4; i++ ) {              // max four digits in whole part
        if( (*p >= '0') && (*p <= '9') ) {
            wh = (10 * wh) + (*p - '0');
            *ps++ = *p++;
        } else {
            break;
        }
        if( (p - val_start) > val_len ) {   // value end reached
            break;
        }
    }
    if( (*p >= '0') && (*p <= '9') ) {      // too many digits in whole part
        xx_line_err( err_inv_att_val, p );
        scan_start = scan_stop + 1;
        return( converterror );
    }

    if( ((p - val_start) < val_len) && *p == '.' ) {   // check for decimal point
        pd = p;
        *ps++ = *p++;
        pd1 = p;                            // remember start of decimals
        for( i = 0; i < 2; i++ ) {          // max two digits in decimals
            if( (*p >= '0') && (*p <= '9') ) {
                wd = 10 * wd + *p - '0';
                *ps++ = *p++;
            } else {
                break;
            }
            if( (p - val_start) > val_len ) {  // value end reached
                break;
            }
        }
        pdn = p;
        if( pd1 == p ) {                        // no decimals
            pd1 = NULL;
            pdn = NULL;
        }
        if( (*p >= '0') && (*p <= '9') ) {      // too many digits in decimals
            xx_line_err( err_inv_att_val, pdn );
            scan_start = scan_stop + 1;
            return( converterror );
        }
    }

    k = 0;
    pu = p;
    for( i = 0; i < 2; i++ ) {                  // max two characters in unit
        if( *p && isalpha( *p ) ) {
            unit[k++] = tolower( *p );          // save Unit
            *ps++ = *p++;
        } else {
            break;
        }
        if( (p - val_start) > val_len ) {   // value end reached
            break;
        }
    }
    if( *p && isalpha( *p ) ) {             // too many characters in unit
        xx_line_err( err_inv_att_val, p );
        scan_start = scan_stop + 1;
        return( converterror );
    }

    /***********************************************************************/
    /*  check for valid unit                                               */
    /***********************************************************************/
    if( unit[1] == '\0' ) {           // single letter unit
        switch( unit[0] ) {
        case 'i' :
            s->su_u = SU_inch;
            break;
        case 'm' :
            s->su_u = SU_ems;
            if( pd != NULL ) {          // no decimals with "M"
                xx_line_err( err_inv_att_val, pd );
                scan_start = scan_stop + 1;
                return( converterror );
            }
            break;
        case 'c' :
            s->su_u = SU_cicero;
            is_cp = true;
            break;
        case 'p' :
            s->su_u = SU_pica;
            is_cp = true;
            break;
        case '\0' :                     // no unit is characters or lines
            s->su_u = SU_chars_lines;
            break;
        default:
            xx_line_err( err_inv_att_val, pu );
            scan_start = scan_stop + 1;
            return( converterror );
            break;
        }
    } else {                            // two letter unit
        if( unit[1] == 'm' ) {          // cm, mm ?
            if( unit[0] == 'c' ) {
                s->su_u = SU_cm;
            } else if( unit[0] == 'm' ) {
                s->su_u = SU_mm;
            } else {                    // invalid unit
                xx_line_err( err_inv_att_val, pu );
                scan_start = scan_stop + 1;
                return( converterror );
            }
        } else if( unit[0] == 'd' ) {   // dv ?
            if( unit[1] == 'v' ) {
                s->su_u = SU_dv;
            }
        } else {                        // invalid unit
            xx_line_err( err_inv_att_val, pu );
            scan_start = scan_stop + 1;
            return( converterror );
        }
    }

    if( is_cp ) {       // "C" and "P" can be followed by max four digits
        for( i = 0; i < 4; i++ ) {
            if( (*p >= '0') && (*p <= '9') ) {
                wd = (10 * wd) + (*p - '0');
                *ps++ = *p++;
            }
            if( (p - val_start) > val_len ) {   // value end reached
                break;
            }
        }
    }
    if( (*p >= '0') && (*p <= '9') ) {      // too many digits after "C" or "P"
        xx_line_err( err_inv_att_val, p );
        scan_start = scan_stop + 1;
        return( converterror );
    }

    *ps = '\0';
    if( (p - val_start) < val_len ) {     // value continues on: it shouldn't
        xx_line_err( err_inv_att_val, p );
        scan_start = scan_stop + 1;
        return( converterror );
    }
    s->su_whole = wh;
    s->su_dec   = wd;

    if( k == 0 ) {                      // no trailing unit
        pu = NULL;
    }
    if( pd != NULL ) {                  // dec point found
        if( pu == NULL ) {              // need trailing unit
            xx_line_err( err_inv_att_val, pd );
            scan_start = scan_stop + 1;
            return( converterror );
        }
    }

    s->su_inch = 0;
    s->su_mm   = 0;
    k = 1;
    if( pd1 != NULL ) {
        if( pdn - pd1 == 1 ) {
            k = 10;                 // only 0.1 digit
        }
    }
    switch( s->su_u ) {
    // the relative units are only stored, not converted
    case SU_chars_lines :
    case SU_ems :
    case SU_dv :
        break;
    case SU_inch :                      // inch, cm, mm valid with decimals
        s->su_mm   = (wh * 100L + wd * k) * 2540L;
        s->su_inch = (wh * 100L + wd * k) *  100L;
        break;
    case SU_cm :
        s->su_mm   = (wh * 100L + wd * k) * 1000L;
        s->su_inch = s->su_mm * 10L / 254L;
        break;
    case SU_mm :
        s->su_mm   = (wh * 100L + wd * k) *  100L;
        s->su_inch = s->su_mm * 10L / 254L;
        break;
    case SU_cicero :                    // cicero
        if( wd > 11 ) {
            div = ldiv( wd, 12L);
            wh += div.quot;
            wd = div.rem;
        }
        s->su_inch = wh * 10000L / 6L + wd * 10000L / 72L;
        s->su_inch = (int64_t)s->su_inch * 10656L / 10000L;
        s->su_mm = s->su_inch * 254L / 10L;
        break;
    case SU_pica :                      // pica
        if( wd > 11 ) {
            div = ldiv( wd, 12L);
            wh += div.quot;
            wd = div.rem;
        }
        s->su_inch = wh * 10000L / 6L + wd * 10000L / 72L;
        s->su_inch = (int64_t)s->su_inch * 9978L / 10000L;
        s->su_mm = s->su_inch * 254L / 10L;
        break;
    default:
        break;
    }
    if( sign == '-' ) {
        s->su_inch  = -s->su_inch;
        s->su_mm    = -s->su_mm;
        s->su_whole = -s->su_whole;
    }
    converterror = false;
    return( converterror );
}
Exemple #4
0
bool    to_internal_SU( char * * scanp, su * converted )
{
    bool        converterror = true;
    char    *   p;
    char    *   ps;
    ldiv_t      div;
    su      *   s;
    long        wh;
    long        wd;
    char    *   pp;                  // ptr to decimal point or embedded unit
    char    *   pu;                     // ptr to trailing unit
    char    *   pd1;                    // ptr to 0.1 decimal
    char    *   pdn;                    // ptr to last digit +1
    char        unit[4];
    char        quote;
    long        k;
    char        sign;

    unit[3] = '\0';
    unit[2] = '\0';
    unit[1] = '\0';
    unit[0] = '\0';
    s = converted;
    p = *scanp;
    ps = s->su_txt;
    *ps = '\0';
    wh = 0;
    wd = 0;
    pp = NULL;
    quote = '\0';

    s->su_u = SU_undefined;
    if( *p == '\'' || *p == '"' ) {     // ignore but remember quote
        quote = *p++;
    }
    if( *p == '+' || *p == '-' ) {
        sign = *p;
        *ps++ = *p++;
        s->su_relative = true;  // value is added / subtracted from old value
    } else {
        sign = '+';
        s->su_relative = false;         // value replaces old value
    }

    /***********************************************************************/
    /*  Special for layout :BANREGION                                      */
    /***********************************************************************/

    if( quote == '\0' && isalpha( *p ) ) {
        converterror = su_layout_special( scanp, converted );
        if( !converterror ) {
            return( converterror );     // layout special ok
        }
    }
    while( *p >= '0' && *p <= '9' ) {   // whole part
        wh = 10 * wh + *p - '0';
        *ps++ = *p++;
        if( ps >= s->su_txt + sizeof( s->su_txt ) ) {
            if( quote ) {
                p = skip_to_quote( p, quote );
            }
            *scanp = p;
            return( converterror );
        }
    }
    pp = p;
    k = 0;
    while( *p && isalpha( *p ) ) {
        unit[k++] = tolower( *p );      // save Unit
        *ps++ = *p++;
        if( ps >= s->su_txt + sizeof( s->su_txt ) || k > 2 ) {
            if( quote ) {
                p = skip_to_quote( p, quote );
            }
            *scanp = p;
            return( converterror );
        }
    }
    if( p > pp + 2 ) {
         if( quote ) {
             p = skip_to_quote( p, quote );
         }
         *scanp = p;
         return( converterror );        // no unit has more than 2 chars
    }
    pd1 = NULL;
    pdn = NULL;

    if( p == pp && *p == '.' ) {        // no unit found, try dec point
        *ps++ = *p++;
        pd1 = p;                        // remember start of decimals
        if( ps >= s->su_txt + sizeof( s->su_txt ) ) {
            if( quote ) {
                p = skip_to_quote( p, quote );
            }
            *scanp = p;
            return( converterror );
        }
        while( *p >= '0' && *p <= '9' ) {   // try decimal part
            wd = 10 * wd + *p - '0';
            *ps++ = *p++;
            if( ps >= s->su_txt + sizeof( s->su_txt ) ) {
                if( quote ) {
                    p = skip_to_quote( p, quote );
                }
                *scanp = p;
                return( converterror );
            }
            if( p > pd1 + 2 ) {         // more than two digits
                if( quote ) {
                    p = skip_to_quote( p, quote );
                }
                *scanp = p;
                return( converterror );
            }
        }
        pdn = p;
    } else {
        if( k ) {                       // unit found
            pd1 = p;
            if( ps >= s->su_txt + sizeof( s->su_txt ) ) {
                if( quote ) {
                    p = skip_to_quote( p, quote );
                }
                *scanp = p;
                return( converterror );
            }
            while( *p >= '0' && *p <= '9' ) {   // try decimal part
                wd = 10 * wd + *p - '0';
                *ps++ = *p++;
                if( ps >= s->su_txt + sizeof( s->su_txt ) ) {
                    if( quote ) {
                        p = skip_to_quote( p, quote );
                    }
                    *scanp = p;
                    return( converterror );
                }
                if( p > pd1 + 2 ) {     // more than two digits
                    if( quote ) {
                        p = skip_to_quote( p, quote );
                    }
                    *scanp = p;
                    return( converterror );
                }
            }
            pdn = p;
        }
    }
    k = 0;
    pu = p;
    if( *p ) {                          // not yet at end
        while( *p && isalpha( *p ) ) {  // try trailing unit
            unit[k++] = tolower( *p );
            *ps++ = *p++;
            if( ps >= s->su_txt + sizeof( s->su_txt ) || k > 2 ) {
                if( quote ) {
                    p = skip_to_quote( p, quote );
                }
                *scanp = p;
                return( converterror );
            }
        }
    }

    *ps = '\0';

    s->su_whole = wh;
    s->su_dec   = wd;

    if( (quote && *p != quote ) || (!quote && *p == '\'') ) {
        if( quote ) {
            p = skip_to_quote( p, quote );
        }
        *scanp = p;
        return( converterror );
    }
    if( quote ) {
        p++;                            // over quote
    }

    *scanp = p;                         // report back scan position

    if( k == 0 ) {                      // no trailing unit
        pu = NULL;
    } else {
        if( pu == pp ) {                // no decimals, no unit
            pu = NULL;
        }
    }
    if( *pp == '.' ) {                  // dec point found
        if( pu == NULL ) {              // need trailing unit
            return( converterror );
        }
    } else {                            // no decimals
        if( pu != NULL ) {              // but unit specified twice?
            return( converterror );
        }
    }

    /***********************************************************************/
    /*  check for valid unit                                               */
    /***********************************************************************/
    if( unit[1] == '\0' ) {           // single letter unit
        switch( unit[0] ) {
        case 'i' :
            s->su_u = SU_inch;
            break;
        case 'm' :
            s->su_u = SU_ems;
            break;
        case 'c' :
            s->su_u = SU_cicero;
            break;
        case 'p' :
            s->su_u = SU_pica;
            break;
        case '\0' :                     // no unit is characters or lines
            s->su_u = SU_chars_lines;
            break;
        default:
            return( converterror );
            break;
        }
    } else {                            // two letter unit
        if( unit[1] == 'm' ) {          // cm, mm ?
            if( unit[0] == 'c' ) {
                s->su_u = SU_cm;
            } else if( unit[0] == 'm' ) {
                s->su_u = SU_mm;
            } else {                    // invalid unit
                return( converterror );
            }
        } else if( unit[0] == 'd' ) {   // dv ?
            if( unit[1] == 'v' ) {
                s->su_u = SU_dv;
            }
        } else {                        // invalid unit
            return( converterror );
        }
    }

    s->su_inch = 0;
    s->su_mm   = 0;
    k = 1;
    if( pd1 != NULL ) {
        if( pdn - pd1 == 1 ) {
            k = 10;                 // only 0.1 digit
        }
    }
    switch( s->su_u ) {
    // the relative units are only stored, not converted
    case SU_chars_lines :
    case SU_ems :
        if( wd != 0 ) {                 // no decimals allowed
            return( converterror );
        }
        break;
    case SU_dv :                        // decimals are allowed for dv
        break;
    case SU_inch :                      // inch, cm, mm valid with decimals
        s->su_mm   = (wh * 100L + wd * k) * 2540L;
        s->su_inch = (wh * 100L + wd * k) *  100L;
        break;
    case SU_cm :
        s->su_mm   = (wh * 100L + wd * k) * 1000L;
        s->su_inch = s->su_mm * 10L / 254L;
        break;
    case SU_mm :
        s->su_mm   = (wh * 100L + wd * k) *  100L;
        s->su_inch = s->su_mm * 10L / 254L;
        break;
    case SU_cicero :                    // cicero
        if( wd > 11 ) {
            div = ldiv( wd, 12L);
            wh += div.quot;
            wd = div.rem;
        }
        s->su_inch = wh * 10000L / 6L + wd * 10000L / 72L;
        s->su_inch = (int64_t)s->su_inch * 10656L / 10000L;
        s->su_mm = s->su_inch * 254L / 10L;
        break;
    case SU_pica :                      // pica
        if( wd > 11 ) {
            div = ldiv( wd, 12L);
            wh += div.quot;
            wd = div.rem;
        }
        s->su_inch = wh * 10000L / 6L + wd * 10000L / 72L;
        s->su_inch = (int64_t)s->su_inch * 9978L / 10000L;
        s->su_mm = s->su_inch * 254L / 10L;
        break;
    default:
        break;
    }
    if( sign == '-' ) {
        s->su_inch  = -s->su_inch;
        s->su_mm    = -s->su_mm;
        s->su_whole = -s->su_whole;
    }
    converterror = false;
    return( converterror );
}