Exemplo n.º 1
0
static void finish_banners( void )
{
    banner_lay_tag  *   cur_ban;
    region_lay_tag  *   cur_reg;
    region_lay_tag  *   top_line_reg;
    font_number         s_font;
    uint32_t            ban_line;
    uint32_t            max_reg_depth;
    font_number         max_reg_font;
    uint32_t            min_top_line;

    s_font = g_curr_font;
    for( cur_ban = layout_work.banner; cur_ban != NULL; cur_ban = cur_ban->next ) {
        ban_line = 0;
        max_reg_depth = 0;
        max_reg_font = 0;
        min_top_line = UINT32_MAX;      // start at very large positive number
        top_line_reg = NULL;
        for( cur_reg = cur_ban->region; cur_reg != NULL; cur_reg = cur_reg->next ) {
            g_curr_font = s_font;   // horizontal attributes use default font
            cur_reg->reg_indent = conv_hor_unit( &cur_reg->indent );
            cur_reg->reg_hoffset = conv_hor_unit( &cur_reg->hoffset );
            cur_reg->reg_width = conv_hor_unit( &cur_reg->width );

            g_curr_font = cur_reg->font; // vertical attributes use the banregion font
            cur_reg->reg_voffset = conv_vert_unit( &cur_reg->voffset, 1 );
            cur_reg->reg_depth = conv_vert_unit( &cur_reg->depth, 1 );

            if( max_reg_depth < cur_reg->reg_voffset + cur_reg->reg_depth ) {
                max_reg_depth = cur_reg->reg_voffset + cur_reg->reg_depth;
            }
            if( ban_line < wgml_fonts[cur_reg->font].line_height ) {
                max_reg_font = cur_reg->font;
                ban_line = wgml_fonts[max_reg_font].line_height;
            }
            if( min_top_line > cur_reg->reg_voffset + cur_reg->reg_depth ) {
                min_top_line = cur_reg->reg_voffset + cur_reg->reg_depth;
                top_line_reg = cur_reg;
            }
        }
        g_curr_font = s_font;       // horizontal attributes use default font
        cur_ban->ban_left_adjust = conv_hor_unit( &cur_ban->left_adjust );
        cur_ban->ban_right_adjust = conv_hor_unit( &cur_ban->right_adjust );

        g_curr_font = max_reg_font; // vertical attribute uses the largest banregion font
        cur_ban->ban_depth = conv_vert_unit( &cur_ban->depth, 1 );

        cur_ban->top_line = top_line_reg;

        if( cur_ban->ban_depth < max_reg_depth ) {
            xx_err( err_banreg_too_deep );
            cur_ban->ban_depth = max_reg_depth;
        }
    }
    g_curr_font = s_font;
    return;
}
Exemplo n.º 2
0
void insert_page_width( doc_element * a_element )
{
    uint32_t    depth;

    /* depth is used to update t_page.cur_depth and so must be kept separate */

    if( !ProcFlags.page_started ) {
        depth = a_element->top_skip;
        ProcFlags.page_started = true;
    } else {
        depth = a_element->subs_skip;
    }
    depth += a_element->depth;

    /****************************************************************/
    /*  Does the first line minimum apply here? If so, it needs to  */
    /*  be implemented. Note that cur_el->depth does not reflect it */
    /*  because there is no way to tell if it will apply when the   */
    /*  is computed.                                                */
    /****************************************************************/

    switch( a_element->type ) {
    // TOP FIG processing goes here
    case el_text :                      // section heading: must go on t_page
        if( (depth + t_page.cur_depth) <= t_page.max_depth ) {
            if( t_page.page_width == NULL ) {   // must be empty
                t_page.page_width = a_element;
                t_page.last_col_main = t_page.page_width;
                t_page.cur_depth += depth;
                if( bin_driver->y_positive == 0 ) {
                    t_page.main_top -= depth;
                } else {
                    t_page.main_top += depth;
                }
            } else {        // discard second section heading
                g_err( err_intern, __FILE__, __LINE__ );
            }        
        } else {
            xx_err( err_heading_too_deep );
            g_suicide();    // it won't fit on any page if not on this
        }
        break;
    default:
        g_err( err_intern, __FILE__, __LINE__ );
    }

    return;
}
Exemplo n.º 3
0
static bool check_att_value( gaentry * ga )
{
    gavalentry  *   gaval;
    char        *   valp;
    long            attval;
    bool            msg_done;
    int             rc;

    scan_err = true;
    msg_done = false;
    for( gaval = ga->vals; gaval != NULL; gaval = gaval->next ) {
        if( gaval->valflags & val_any ) {
            scan_err = false;           // any value is allowed
            break;
        }

        valp = NULL;
        if( gaval->valflags & val_value ) {
            valp = gaval->a.value;
        } else {
            if( gaval->valflags & val_valptr ) {
                valp = gaval->a.valptr;
            }
        }
        if( valp != NULL ) {
            if( !strcmp( token_buf, valp ) ) {
                scan_err = false;       // value is allowed
                break;
            }
        } else {
            if( gaval->valflags & val_range ) {
                attval = strtol( token_buf, NULL, 10 );
                if( attval < gaval->a.range[0] ||
                    attval > gaval->a.range[1]  ) {
                    xx_err( ERR_ATT_RANGE_INV );// value outside range
                    msg_done = true;
                    break;
                }
            } else {
                if( gaval->valflags & val_length ) {
                    if( strlen( token_buf ) > gaval->a.length ) {
                        xx_err( err_att_len_inv );  // value too long
                        msg_done = true;
                    } else {
                        scan_err = false;
                    }
                    break;
                }
            }
        }
    }
    if( !scan_err ) {
        rc = add_symvar( &loc_dict, ga->name, token_buf,
                         no_subscript, local_var );
    } else {
        if( !msg_done ) {
            att_val_err( ga->name );
        }
    }
    return( scan_err );
}
Exemplo n.º 4
0
void    gml_binclude( gml_tag gtag )
{
    bool            depth_found             = false;
    bool            file_found              = false;
    bool            has_rec_type            = false;
    bool            reposition;
    bool            reposition_found        = false;
    char            file[FILENAME_MAX];
    char            rt_buff[MAX_FILE_ATTR];
    char        *   p;
    doc_element *   cur_el;
    su              depth_su;
    uint32_t        depth;
    size_t          len;

    if( (ProcFlags.doc_sect < doc_sect_gdoc) ) {
        if( (ProcFlags.doc_sect_nxt < doc_sect_gdoc) ) {
            xx_tag_err( err_tag_before_gdoc, gml_tagname( gtag ) );
            scan_start = scan_stop;
            return;
        }
    }
    len = 0;
    file[0] = '\0';
    rt_buff[0] = '\0';
    p = scan_start;
    for( ;; ) {
        while( *p == ' ' ) {            // over WS to attribute
            p++;
        }
        if( *p == '\0' ) {              // end of line: get new line
            if( !(input_cbs->fmflags & II_eof) ) {
                if( get_line( true ) ) {      // next line for missing attribute
                    process_line();
                    if( (*scan_start == SCR_char) ||    // cw found: end-of-tag
                        (*scan_start == GML_char) ) {   // tag found: end-of-tag
                        ProcFlags.tag_end_found = true;
                        break;
                    } else {
                        p = scan_start; // new line is part of current tag
                        continue;
                    }
                }
            }
        }
        if( !strnicmp( "file", p, 4 ) ) {
            p += 4;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            file_found = true;
            len = val_len;
            if( len >= FILENAME_MAX )
                len = FILENAME_MAX - 1;
            memcpy( file, val_start, len );
            file[len] = '\0';
            split_attr_file( file, rt_buff, MAX_FILE_ATTR );
            if( (rt_buff[0] != '\0') ) {
                has_rec_type = true;
                if( rt_buff[0] != 't' ) {
                    xx_warn( wng_rec_type_binclude );
                }
            }
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else if( !strnicmp( "depth", p, 5 ) ) {
            p += 5;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            depth_found = true;
            if( att_val_to_su( &depth_su, true ) ) {
                return;
            }
            depth = conv_vert_unit( &depth_su, g_spacing_ln );
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else if( !strnicmp( "reposition", p, 10 ) ) {
            p += 10;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            reposition_found = true;
            if( !strnicmp( "start", val_start, 5 ) ) {
                reposition = true;  // moving following text down by depth
            } else if( !strnicmp( "end", val_start, 3 ) ) {
                reposition = false; // device at proper position after insertion
            } else {
                xx_line_err( err_inv_att_val, val_start );
                scan_start = scan_stop;
                return;
            }
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else {    // no match = end-of-tag in wgml 4.0
            ProcFlags.tag_end_found = true;
            break;
        }
    }
    // detect missing required attributes
    if( !depth_found || !file_found || !reposition_found ) {
        xx_err( err_att_missing );
        scan_start = scan_stop;
        return;
    }

    scr_process_break();                // flush existing text
    start_doc_sect();                   // if not already done

    cur_el = alloc_doc_el(  el_binc );
    if( reposition && depth ) {
        cur_el->depth = depth;          // otherwise, it will be "0"
    }
    if( depth > 0 ) {
        set_skip_vars( NULL, NULL, NULL, 1, g_curr_font );
        cur_el->blank_lines = g_blank_lines;
        g_blank_lines = 0;
        cur_el->subs_skip = g_subs_skip;
        cur_el->top_skip = g_top_skip;
    }
    cur_el->element.binc.depth = depth;
    cur_el->element.binc.cur_left = g_cur_h_start;
    cur_el->element.binc.has_rec_type = has_rec_type;
    ProcFlags.skips_valid = false;
    memcpy( cur_el->element.binc.file, file, len + 1 );
    insert_col_main( cur_el );

    scan_start = scan_stop;         // skip following text
}
Exemplo n.º 5
0
void    scr_gt( void )
{
    char        *   p;
    char        *   pn;
    char            savetag;
    int             k;
    int             len;
    char            macname[MAC_NAME_LENGTH + 1];
    condcode        cc;
    gtentry     *   wk;
    gtflags         tag_flags;
    enum {
        f_add       = 1,
        f_change,
        f_delete,
        f_off,
        f_on,
        f_print
    } function;

    garginit();                         // find end of CW

    /***********************************************************************/
    /*  isolate tagname   or use previous if tagname *                     */
    /***********************************************************************/

    cc = getarg();                      // Tagname

    if( cc == omit ) {
        // no operands
        tag_name_missing_err();
        return;
    }

    p = tok_start;

    if( *p == '*' ) {                   // single * as tagname
        if( arg_flen > 1 ) {
            xx_err( err_tag_name_inv );
            return;
        }
        savetag = '*';         // remember for possible global delete / print
        if( GlobalFlags.firstpass && input_cbs->fmflags & II_research ) {
            if( tag_entry != NULL ) {
                out_msg("  using tagname %s %s\n", tagname, tag_entry->name );
            }
        }
    } else {
        savetag = ' ';               // no global function for delete / print

        init_tag_att();            // forget previous values for quick access
        attname[0] = '*';

        pn      = tagname;
        len     = 0;

        while( *p && is_macro_char( *p ) ) {
            if( len < TAG_NAME_LENGTH ) {
                *pn++ = tolower( *p++ );// copy lowercase tagname
                *pn   = '\0';
            } else {
                break;
            }
            len++;
        }
        for( k = len; k < TAG_NAME_LENGTH; k++ ) {
            tagname[k] = '\0';
        }
        tagname[TAG_NAME_LENGTH] = '\0';

        if( len < arg_flen ) {
            xx_err( err_tag_name_inv );
            return;
        }
    }


    /***********************************************************************/
    /* get function operand  add, change, ...                              */
    /***********************************************************************/

    cc = getarg();

    if( cc == omit ) {
        xx_err( err_tag_func_inv );
        return;
    }

    p = tok_start;
    function = 0;
    switch( tolower( *p ) ) {
    case   'a':
        if( !strnicmp( "ADD ", p, 4 ) ) {

            function = f_add;
        }
        break;
    case 'c' :
        if( (arg_flen > 2) && (arg_flen < 7)
            && !strnicmp( "CHANGE", p, arg_flen ) ) {

            function = f_change;
        }
        break;
    case 'o' :
        if( !strnicmp( "OFF", p, 3 ) ) {

            function = f_off;
        } else {
            if( !strnicmp( "ON", p, 2 ) ) {

                function = f_on;
            }
        }
        break;
    case 'd' :
        if( (arg_flen > 2) && (arg_flen < 7)
            && !strnicmp( "DELETE", p, arg_flen ) ) {

            function = f_delete;
        }
        break;
    case 'p' :
        if( (arg_flen > 1) && (arg_flen < 6)
            && !strnicmp( "PRINT", p, arg_flen ) ) {

            function = f_print;
        }
        break;
    default:
        // nothing
        break;
    }
    if( function == 0 ) {               // no valid function specified
        xx_err( err_tag_func_inv );
        return;
    }

    cc = getarg();                      // get possible next parm

    /***********************************************************************/
    /*  for add and change    get macroname                                */
    /***********************************************************************/

    if( function == f_add || function == f_change ) {   // need macroname
        if( cc == omit ) {
            xx_err( err_tag_mac_name );
            return;
        }
        p = tok_start;

        pn      = macname;
        len     = 0;

        while( *p && is_macro_char( *p ) ) {
            if( len < MAC_NAME_LENGTH ) {
                *pn++ = tolower( *p++ );    // copy lowercase macroname
                *pn   = '\0';
            } else {
                break;
            }
            len++;
        }
        for( k = len; k < MAC_NAME_LENGTH; k++ ) {
            macname[k] = '\0';
        }
        macname[MAC_NAME_LENGTH] = '\0';

        tag_flags = 0;

        if( function == f_add ) {       // collect tag options
            cc = scan_tag_options( &tag_flags );
            if( cc != omit ) {          // not all processed error
               xx_err( err_tag_opt_inv );
            }
            tag_entry = add_tag( &tag_dict, tagname, macname, tag_flags );  // add to dictionary
            // if tag_entry is now NULL, error (+ msg) was output in add_tag
        } else {                        // is function change
            tag_entry = change_tag( &tag_dict, tagname, macname );
        }
    } else {

    /***********************************************************************/
    /*  after delete, off, on, print nothing allowed                       */
    /***********************************************************************/

        if( cc != omit ) {
            xx_err( err_tag_toomany );  // nothing more allowed
        }

        switch( function ) {
        case f_print :
            if( savetag == '*' ) {
                print_tag_dict( tag_dict );
            } else {
                print_tag_entry( find_tag( &tag_dict, tagname ) );
            }
            break;
        case f_delete :
            if( savetag == '*' ) {
                free_tag_dict( &tag_dict );
            } else {
                free_tag( &tag_dict, find_tag( &tag_dict, tagname ) );
            }
            break;
        case f_off :
            if( savetag == '*' && tag_entry != NULL ) {// off for last defined
                tag_entry->tagflags |= tag_off;
            } else {
                wk = find_tag( &tag_dict, tagname );
                if( wk != NULL ) {
                    wk->tagflags |= tag_off;
                }
            }
            break;
        case f_on :
            if( savetag == '*' && tag_entry != NULL ) {// on for last defined
                tag_entry->tagflags |= tag_off;
            } else {
                wk = find_tag( &tag_dict, tagname );
                if( wk != NULL ) {
                    wk->tagflags &= ~tag_off;
                }
            }
            break;
        default:
            break;
        }
    }
    scan_restart = scan_stop +1;
    return;
}
Exemplo n.º 6
0
void    init_page_geometry( void )
{
    int         k;
    uint32_t    page_depth_org;
    uint32_t    net_top_margin;
    uint32_t    net_y_start;
    uint32_t    rm_test;
    uint32_t    top_margin;
    uint32_t    y_start_correction;
#if 0                                   // activate for multi column TBD
    uint32_t    offset;
#endif


    g_resh = bin_device->horizontal_base_units; // hor resolution  &sysresh
    g_resv = bin_device->vertical_base_units;   // vert resolution &sysresv

    spacing = layout_work.defaults.spacing;

    g_cur_threshold = layout_work.widow.threshold;

    g_max_char_width = 0;
    g_max_line_height = 0;
    for( k = 0; k < wgml_font_cnt; k++ ) {
        if( g_max_char_width < wgml_fonts[k].default_width )
            g_max_char_width = wgml_fonts[k].default_width;
        if( g_max_line_height < wgml_fonts[k].line_height )
            g_max_line_height = wgml_fonts[k].line_height;
    }
    g_curr_font = layout_work.defaults.font;

    lm = conv_hor_unit( &layout_work.page.left_margin )
         - bin_device->x_offset;        // left margin &syspagelm
    if( lm < 0 ) {                      // wgml 4.0 limits value
        lm = 0;
    }

    rm = conv_hor_unit( &layout_work.page.right_margin )
         - bin_device->x_offset;        // right margin &syspagerm

    rm_test = bin_device->horizontal_base_units / 4;
    if( (bin_device->horizontal_base_units % 4) > 0 ) {
        rm_test++;                          // round up if any remainder
    }
    if( rm < rm_test ) {                    // wgml 4.0 limits value
        xx_err( err_right_margin_2_small ); // candidate Severe Error
        g_suicide();                        // no recovery possible
    }

    g_page_left_org = lm + bin_device->x_start;
    if( g_page_left_org < bin_device->x_start )
        g_page_left_org = bin_device->x_start;
    g_page_left = g_page_left_org;
    g_cur_left = g_page_left;               // set initial value

    g_page_right_org = rm + bin_device->x_start;
    if( g_page_right_org > bin_device->page_width )
        g_page_right_org = bin_device->page_width;
    g_page_right = g_page_right_org;

    if( g_page_right > bin_device->page_width ) {// output must appear on page
        xx_err( err_margins_inverted );     // candidate Severe Error
        g_suicide();                        // no recovery possible
    }

    if( g_page_left >= g_page_right ) {     // margins cannot be inverted
        xx_err( err_margins_inverted );     // candidate Severe Error
        g_suicide();                        // no recovery possible
    }

    g_net_page_width = rm - lm;
    g_ll = g_net_page_width * CPI / bin_device->horizontal_base_units; // &sysll

    top_margin = conv_vert_unit( &layout_work.page.top_margin, 1 );

    page_depth_org = conv_vert_unit( &layout_work.page.depth, 1 );
    if( bin_device->y_offset > page_depth_org ) {
        xx_err( err_page_depth_too_small ); // candidate Severe Error
        g_suicide();                        // no recovery possible
    } else {
        g_page_depth = page_depth_org - bin_device->y_offset;  // &syspaged
    }
    if( bin_device->y_offset < top_margin ) {
        net_top_margin = top_margin - bin_device->y_offset;
    } else {
        net_top_margin = 0;
    }
    if( bin_driver->y_positive == 0 ) {
        g_page_top = bin_device->y_start - net_top_margin;
        if( g_page_depth > bin_device->y_start ) {
            /* see Wiki for discussion, wgml 4.0 differs here */
            xx_err( err_page_depth_too_big );   // candidate Severe Error
            g_suicide();                        // no recovery possible
        } else {
            g_page_bottom = bin_device->y_start - g_page_depth;// end of text area
        }
        g_net_page_depth = g_page_top - g_page_bottom;

        lcmax = 1 + (g_net_page_depth + bin_device->y_offset)
                 / wgml_fonts[g_curr_font].line_height;   // usable no of lines
    } else {
        net_y_start = bin_device->y_start;
        if( net_y_start < net_top_margin )
            net_y_start = net_top_margin;
        if( bin_device->y_start > net_top_margin ) {
            y_start_correction = bin_device->y_start - net_top_margin;
            if( y_start_correction > wgml_fonts[g_curr_font].line_height ) {
                y_start_correction = wgml_fonts[g_curr_font].line_height;
            }
        } else {
            y_start_correction = 0;
        }
        g_page_top = net_y_start - y_start_correction;
        g_page_bottom = g_page_top + g_page_depth;

        g_net_page_depth = g_page_bottom - g_page_top;
        lcmax = g_net_page_depth;
    }

    g_page_bottom_org = g_page_bottom;// save for possible bot banner calculation
    g_page_top_org = g_page_top;// save top for possible bot banner calculation

    g_cd = layout_work.defaults.columns;// no of columns   &syscd
    g_gutter = conv_hor_unit( &layout_work.defaults.gutter );   // &sysgutter

#if 0                                   // activate for multi column TBD
    if( g_cd > 1 ) {                    // multi column layout
        if( g_cd > 9 ) {
                                        // no more than 9 columns
            g_cd = 9;                   // this limit is found in script_tso.txt
                                        // for .cd control word
        }
        g_cl = (g_net_page_width - (g_cd - 1) * g_gutter )
                / (g_cd - 1);           // column length
        offset = g_page_left;
        for( k = 0; k < g_cd; ++k ) {
            g_offset[k] = offset;       // start of each column
            offset += g_cl + g_gutter;
        }
        for( ; k < 9; ++k ) {
            g_offset[k] = 0;            // dummy start of undefined columns
        }
    } else {
        g_cl = g_ll;
    }
#else
    g_cl = g_ll;                        // column length &syscl
                // This is what wgml 4 does, even if in multi column mode TBD
#endif

//  if( GlobalFlags.firstpass && GlobalFlags.research ) {  // show values TBD
    if( GlobalFlags.firstpass                         ) {
        out_msg( "\ntm:%d lm:%d rm:%d top margin:%d depth:%d\n\n", tm, lm, rm,
                 top_margin, g_page_depth );

        out_msg( "dev:%s page_w:%d page_d:%d hor_u:%d ver_u:%d x_s:%d y_s:%d"
                 " x_o:%d y_o:%d\n\n",
                 bin_device->driver_name,
                 bin_device->page_width,
                 bin_device->page_depth,
                 bin_device->horizontal_base_units,
                 bin_device->vertical_base_units,
                 bin_device->x_start,
                 bin_device->y_start,
                 bin_device->x_offset,
                 bin_device->y_offset
               );
        out_msg( "default font number:%d font_count:%d\n", g_curr_font,
                 wgml_font_cnt );
        for( k = 0; k < wgml_font_cnt; ++k ) {
            out_msg( "font:%d def_width:%d em:%d font_h:%d font_s:%d"
                     " line_h:%d line_s:%d spc_w:%d\n",
                     k,
                     wgml_fonts[k].default_width,
                     wgml_fonts[k].em_base,
                     wgml_fonts[k].font_height,
                     wgml_fonts[k].font_space,
                     wgml_fonts[k].line_height,
                     wgml_fonts[k].line_space,
                     wgml_fonts[k].spc_width
                   );
        }
        out_msg( "\npage top:%d bottom:%d left:%d right:%d lines:%d\n",
                 g_page_top, g_page_bottom, g_page_left, g_page_right, lcmax );
        out_msg(
           "page net depth:%d width:%d line height:%d char width:%d\n\n",
                  g_net_page_depth, g_net_page_width, g_max_line_height,
                  g_max_char_width );
    }
    g_indent = 0;
    g_indentr = 0;

    init_nest_cb();
}
Exemplo n.º 7
0
void insert_col_main( doc_element * a_element )
{
    bool        page_full;
    bool        splittable;
    uint32_t    cur_skip;
    uint32_t    depth;

    /****************************************************************/
    /*  alternate procesing: accumulate elements for later          */
    /*  submission                                                  */
    /*  used currenlty by ADDRESS/eADDRESS                          */
    /****************************************************************/

    if( ProcFlags.group_elements ) {
        if( t_doc_el_group.first == NULL ) {
            t_doc_el_group.first = a_element;
            t_doc_el_group.last = t_doc_el_group.first;
        } else {
            t_doc_el_group.last->next = a_element;
            t_doc_el_group.last = t_doc_el_group.last->next;
        }
        t_doc_el_group.depth += a_element->depth;
        return;
    }

    /****************************************************************/
    /*  test version until things get a bit more clear              */
    /*  the theory here is that only one processing step should be  */
    /*      here, the rest being done in update_t_page()            */
    /****************************************************************/

    page_full = false;

    /****************************************************************/
    /*  this section sets page_full to "true" if any of the skips   */
    /*  or blank_lines finishes the page, alone or in various       */
    /*  combinations                                                */
    /*  element field values are adjusted as needed                 */
    /****************************************************************/
        
    if( a_element->blank_lines > 0 ) {
        if( (t_page.cur_depth + a_element->blank_lines) >= t_page.max_depth ) {
            a_element->blank_lines -= (t_page.max_depth - t_page.cur_depth);
            page_full = true;
        } else if( !ProcFlags.page_started && ((t_page.cur_depth +
                    a_element->blank_lines + a_element->top_skip) >=
                    t_page.max_depth) ) {
            a_element->top_skip -= (t_page.max_depth - t_page.cur_depth);
            a_element->top_skip += a_element->blank_lines;
            a_element->blank_lines = 0;
            page_full = true;
        } else if( (t_page.cur_depth + a_element->blank_lines +
                     a_element->subs_skip) >= t_page.max_depth ) {
            a_element->blank_lines = 0;
            page_full = true;
        }
    } else if( !ProcFlags.page_started ) {
        if( a_element->top_skip >= t_page.max_depth ) {
            a_element->top_skip -= t_page.max_depth;
            page_full = true;
        }
    }

    if( !page_full ) {

        /****************************************************************/
        /*  this test is done separately because an element may fail to */
        /*  set page_full to "true" above but the skip actually used    */
        /*  may still fill the page                                     */
        /****************************************************************/

        if( !ProcFlags.page_started ) {
            if( a_element->blank_lines > 0 ) {
                cur_skip = a_element->blank_lines + a_element->subs_skip;
            } else {
                cur_skip = a_element->top_skip;
            }
            ProcFlags.page_started = true;
        } else {
            cur_skip = a_element->blank_lines + a_element->subs_skip;
        }

        if( (cur_skip + t_page.cur_depth) > t_page.max_depth ) {
            page_full = true;
        }
    }

    if( !page_full ) {

        /****************************************************************/
        /*  at least part of the element should fit on the page         */
        /*  Does the first line minimum apply here? If so, it needs to  */
        /*  be implemented. Note that cur_el->depth does not reflect it */
        /*  because there is no way to tell if it will apply when the   */
        /*  is computed.                                                */
        /****************************************************************/

        depth = cur_skip + a_element->depth;
        if( (depth + t_page.cur_depth) > t_page.max_depth ) {   // a_element fills the page
            splittable = split_element( a_element, t_page.max_depth -
                                        t_page.cur_depth - cur_skip );
            if( a_element->next != NULL ) { // a_element was split
                if( t_page.main == NULL ) {
                    t_page.main = alloc_doc_col();
                }
                if( t_page.main->main == NULL ) {
                    t_page.main->main = a_element;
                    t_page.last_col_main = t_page.main->main;
                } else {
                    t_page.last_col_main->next = a_element;
                    t_page.last_col_main = t_page.last_col_main->next;
                }
                t_page.cur_depth += depth;
                a_element = a_element->next;
                t_page.last_col_main->next = NULL;
                page_full = true;
            } else {                        // a_element could not be split
                if( t_page.main == NULL ) { // adapt when FIG/FN done
                    xx_err( err_text_line_too_deep );
                    g_suicide();    // no line will fit on any page
                }
                if( t_page.main->main == NULL ) { // adapt when FIG/FN done
                    xx_err( err_text_line_too_deep );
                    g_suicide();    // no line will fit on any page
                }
                page_full = true;
            }
        } else {    // the entire element fits on the current page
            if( t_page.main == NULL ) {
                    t_page.main = alloc_doc_col();
                }
            if( t_page.main->main == NULL ) {
                t_page.main->main = a_element;
                t_page.last_col_main = t_page.main->main;
            } else {
                t_page.last_col_main->next = a_element;
                t_page.last_col_main = t_page.last_col_main->next;
            }
            t_page.cur_depth += depth;
        }
    }

    if( page_full ) {

        /****************************************************************/
        /*  if page_full is true then a_element goes to n_page and      */
        /*  t_page must be output                                       */
        /****************************************************************/

        if( n_page.last_col_main == NULL ) {
            n_page.col_main = a_element;
            n_page.last_col_main = n_page.col_main;
        } else {
            n_page.last_col_main->next = a_element;
            n_page.last_col_main = n_page.last_col_main->next;
        }
        text_page_out();
    } 
    return;
}
Exemplo n.º 8
0
static void update_t_page( void )
{
    bool            fig_placed;
    bool            splittable;
    doc_element *   cur_el;
    uint32_t        depth;

    reset_t_page();

    /*  some section headings are placed in t_page.page_width when          */
    /*  processed. One FIG in n_page.col_top goes into t_page.page_width    */
    /*  if it is empty                                                      */
    /*  t_page.page_width can only hold one doc_element                     */
    /*  This is preliminary and may be changed as needed.                   */

    depth = t_page.cur_depth;
    fig_placed = false;
    if( t_page.page_width == NULL ) {       // skip if section full
        if( n_page.col_top != NULL ) {   // at most one item can be placed
            switch( n_page.col_top->type ) {
            // add code for FIG when needed
            case el_text :  // all elements should be FIGs
            default :
                internal_err( __FILE__, __LINE__ );
            }
        }
    }

    /*  one FIG in n_page.col_top goes into t_page.main->top_fig if none    */
    /*  was placed in t_page.page_width                                     */
    /*  this is preliminary and may be changed as needed                    */
    /*  Note: t_page.main is NULL at this point, initialize if needed       */
    
    if( !fig_placed ) {
        if( n_page.col_top != NULL ) {   // at most one item can be placed
            switch( n_page.col_top->type ) {
            // add code for FIG when needed
            case el_text :  // all elements should be FIGs
            default :
                internal_err( __FILE__, __LINE__ );
            }
        } 
    }

    /***********************************************************************/
    /*  The order here is not clear.                                       */
    /*  That shown is based on filling the t_page.main->bot_fig and the    */
    /*  t_page.main->footnote parts before filling t_page.main->main, thus */
    /*  having a firm depth for t_page.main->main to start with.           */
    /*  However, if there is no top_fig, then the first doc_element in     */
    /*  t_page.main->main must set its pre_skip to 0, and then what        */
    /*  happens if there is no room for anything to be placed there?       */
    /*  So this may need to be rethought when FN and FIG are implemented.  */
    /***********************************************************************/

    /*  one FIG in n_page.col_bot goes into t_page.main->bot_fig            */
    /*  entrained footnotes need to be moved to n_page.col_fn               */
    /*  this is preliminary and may be changed as needed                    */
    /*  Note: t_page.main may be NULL at this point, initialize if needed   */

    if( n_page.col_bot != NULL ) {   // at most one item can be placed
        switch( n_page.col_bot->type ) {
        // add code for FIG & entrained footnotes when needed
        case el_text :  // all elements should be FIGs or footnotes
        default :
            internal_err( __FILE__, __LINE__ );
        }
    }

    /*  all footnotes in n_page.col_fn go into t_page.main->footnote        */
    /*  this is preliminary and may be changed as needed                    */
    /*  Note: t_page.main may be NULL at this point, initialize if needed   */

    if( n_page.col_fn != NULL ) {   // at most one item can be placed
        switch( n_page.col_fn->type ) {
        // add code for footnotes when needed
        case el_text :  // all elements should be footnotes
        default :
            internal_err( __FILE__, __LINE__ );
        }
    }

    /*  t_page.main->main is used for the bulk of the elements              */
    /*  it is filled last because the other deferred items are believed to  */
    /*  have priority; this may change as the situation is clarified.       */
    /*  unless the section is ended, there must be at least on element left */
    /*  in n_page.col_main for the page to be full                          */
    /*  Note: when FIG/FN processing is implemented, t_page.main may not be */
    /*  NULL at this point                                                  */

    /****************************************************************/
    /*  test version until things get a bit more clear              */
    /*  the theory here is that only one processing step should be  */
    /*      here, and then the function calling update_t_page()     */
    /*      should be relied on to output the page                  */
    /****************************************************************/
    
    while( n_page.col_main != NULL ) {
        cur_el = n_page.col_main;
        n_page.col_main = n_page.col_main->next;
        if( n_page.col_main == NULL ) {
            n_page.last_col_main = NULL;
        }

        /****************************************************************/
        /*  this section identifies skips and blank lines that finish   */
        /*  the current page and then exits the loop after adjusting    */
        /*  the element field values as needed                          */
        /****************************************************************/
        
        if( cur_el->blank_lines > 0 ) {
            if( (t_page.cur_depth + cur_el->blank_lines) >= t_page.max_depth ) {
                cur_el->blank_lines -= (t_page.max_depth - t_page.cur_depth);
                break;
            } else if( !ProcFlags.page_started && ((t_page.cur_depth +
                        cur_el->blank_lines + cur_el->top_skip) >=
                        t_page.max_depth) ) {
                cur_el->top_skip -= (t_page.max_depth - t_page.cur_depth);
                cur_el->top_skip += cur_el->blank_lines;
                cur_el->blank_lines = 0;
                break;
            } else if( (t_page.cur_depth + cur_el->blank_lines +
                         cur_el->subs_skip) >= t_page.max_depth ) {
                cur_el->blank_lines = 0;
                break;
            }
        }

        if( !ProcFlags.page_started ) {
            if( cur_el->blank_lines > 0 ) {
                depth += cur_el->blank_lines + cur_el->subs_skip;
            } else {
                depth += cur_el->top_skip;
            }
            ProcFlags.page_started = true;
        } else {
            depth += cur_el->blank_lines + cur_el->subs_skip;
        }

        if( depth >= t_page.max_depth ) {    // skip fills page
            break;
        }

        /****************************************************************/
        /*  Does the first line minimum apply here? If so, it needs to  */
        /*  be implemented. Note that cur_el->depth does not reflect it */
        /*  because there is no way to tell if it will apply when the   */
        /*  cur_el->depth is computed.                                  */
        /****************************************************************/

        if( (depth + cur_el->depth) > t_page.max_depth ) {    // cur_el will fill the page
            splittable = split_element( cur_el, t_page.max_depth -
                                                t_page.cur_depth - depth );
            if( splittable ) {
                if( cur_el->next != NULL ) {    // cur_el was split
                    n_page.col_main = cur_el->next;
                    if( n_page.last_col_main == NULL ) {
                        n_page.last_col_main = n_page.col_main;
                    }
                    cur_el->next = NULL;
                }
                if( t_page.main == NULL ) {
                    t_page.main = alloc_doc_col();
                }
                if( t_page.main->main == NULL ) {
                    t_page.main->main = cur_el;
                    t_page.last_col_main = t_page.main->main;
                } else {
                    t_page.last_col_main->next = cur_el;
                    t_page.last_col_main = t_page.last_col_main->next;
                }
                t_page.last_col_main->next = NULL;
                t_page.cur_depth += cur_el->depth;
            } else {
                if( (t_page.main == NULL) || (t_page.main->main == NULL) ) { // adapt when FIG/FN done
                    xx_err( err_text_line_too_deep );
                    g_suicide();    // no line will fit on any page
                }
                n_page.col_main = cur_el->next;
                if( n_page.last_col_main == NULL ) {
                    n_page.last_col_main = n_page.col_main;
                }
                cur_el->next = NULL;
            }
        } else {                                    // cur_el fits as-is
            if( t_page.main == NULL ) {
                t_page.main = alloc_doc_col();
            }
            if( t_page.main->main == NULL ) {
                t_page.main->main = cur_el;
                t_page.last_col_main = t_page.main->main;
            } else {
                t_page.last_col_main->next = cur_el;
                t_page.last_col_main = t_page.last_col_main->next;
            }
            t_page.last_col_main->next = NULL;
            t_page.cur_depth += cur_el->depth;
        }
    }
    return;
}
Exemplo n.º 9
0
void    gml_graphic( gml_tag gtag )
{
    bool            depth_found             = false;
    bool            file_found              = false;
    char            file[FILENAME_MAX];
    char            rt_buff[MAX_FILE_ATTR];
    char        *   p;
    char        *   pa;
    doc_element *   cur_el;
    su              cur_su;
    uint32_t        depth;
    uint32_t        scale                   = 100;
    // the initial value of width is only correct for one-column pages.
    uint32_t        width                   = g_net_page_width;
    int32_t         xoff                    = 0;
    int32_t         yoff                    = 0;
    size_t          len;

    if( (ProcFlags.doc_sect < doc_sect_gdoc) ) {
        if( (ProcFlags.doc_sect_nxt < doc_sect_gdoc) ) {
            xx_tag_err( err_tag_before_gdoc, gml_tagname( gtag ) );
            scan_start = scan_stop;
            return;
        }
    }
    len = 0;
    file[0] = '\0';
    rt_buff[0] = '\0';
    p = scan_start;
    for( ;; ) {
        while( *p == ' ' ) {            // over WS to attribute
            p++;
        }
        if( *p == '\0' ) {              // end of line: get new line
            if( !(input_cbs->fmflags & II_eof) ) {
                if( get_line( true ) ) {      // next line for missing attribute
                    process_line();
                    if( (*scan_start == SCR_char) ||    // cw found: end-of-tag
                        (*scan_start == GML_char) ) {   // tag found: end-of-tag
                        ProcFlags.tag_end_found = true;
                        break;
                    } else {
                        p = scan_start; // new line is part of current tag
                        continue;
                    }
                }
            }
        }
        if( !strnicmp( "file", p, 4 ) ) {
            p += 4;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            file_found = true;
            len = val_len;
            if( len >= FILENAME_MAX )
                len = FILENAME_MAX - 1;
            memcpy( file, val_start, len );
            file[len] = '\0';
            split_attr_file( file, rt_buff, sizeof( rt_buff ) );
            if( (rt_buff[0] != '\0') ) {
                xx_warn( wng_rec_type_graphic );
            }
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else if( !strnicmp( "depth", p, 5 ) ) {
            p += 5;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            depth_found = true;
            pa = val_start;
            if( att_val_to_su( &cur_su, true ) ) {
                return;
            }
            depth = conv_vert_unit( &cur_su, g_spacing_ln );
            if( depth == 0 ) {
                xx_line_err( err_inv_depth_graphic, pa );
                scan_start = scan_stop;
                return;
            }
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else if( !strnicmp( "width", p, 5 ) ) {
            p += 5;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            if( !strnicmp( "page", val_start, 4 ) ) {
                // default value is the correct value to use
            } else if( !strnicmp( "column", val_start, 6 ) ) {
                // default value is the correct value to use
            } else {    // value actually specifies the width
                pa = val_start;
                if( att_val_to_su( &cur_su, true ) ) {
                    return;
                }
                width = conv_hor_unit( &cur_su );
                if( width == 0 ) {
                    xx_line_err( err_inv_width_graphic, pa );
                    scan_start = scan_stop;
                    return;
                }
                /* there should be a check somewhere for width > page width */
            }
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else if( !strnicmp( "scale", p, 5 ) ) {
            p += 5;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            pa = val_start;
            if( (*pa == '+') || (*pa == '-') ) {  // signs not allowed
                xx_line_err( err_num_too_large, pa );
                scan_start = scan_stop;
                return;
            }
            scale = 0;
            while( (*pa >= '0') && (*pa <= '9') ) { // convert to number
                scale = (10 * scale) + (*pa - '0');
                pa++;
                if( (pa - val_start) > val_len ) {  // value end reached
                    break;
                }
            }
            if( scale > 0x7fffffff ) {              // wgml 4.0 limit
                xx_line_err( err_num_too_large, val_start );
                scan_start = scan_stop;
                return;
            }
            if( (pa - val_start) < val_len ) {      // value continues on
                xx_line_err( err_num_too_large, val_start );
                scan_start = scan_stop;
                return;
            }
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else if( !strnicmp( "xoff", p, 4 ) ) {
            p += 4;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            if( att_val_to_su( &cur_su, false ) ) {
                return;
            }
            xoff = conv_hor_unit( &cur_su );
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else if( !strnicmp( "yoff", p, 4 ) ) {
            p += 4;
            p = get_att_value( p );
            if( val_start == NULL ) {
                break;
            }
            if( att_val_to_su( &cur_su, false ) ) {
                return;
            }
            yoff = conv_vert_unit( &cur_su, g_spacing_ln );
            if( ProcFlags.tag_end_found ) {
                break;
            }
        } else {    // no match = end-of-tag in wgml 4.0
            ProcFlags.tag_end_found = true;
            break;
        }
    }
    if( !depth_found || !file_found ) { // detect missing required attributes
        xx_err( err_att_missing );
        scan_start = scan_stop;
        return;
    }

    scr_process_break();                // flush existing text
    start_doc_sect();                   // if not already done

    cur_el = alloc_doc_el( el_graph );
    cur_el->depth = depth;              // always used with GRAPHIC
    if( !ProcFlags.ps_device ) {        // character devices ignore SK & post_skip
        g_skip = 0;
        g_post_skip = 0;
    }
    set_skip_vars( NULL, NULL, NULL, 1, g_curr_font );
    cur_el->blank_lines = g_blank_lines;
    g_blank_lines = 0;
    cur_el->subs_skip = g_subs_skip;
    g_subs_skip = 0;
    cur_el->top_skip = g_top_skip;
    g_top_skip = 0;
    cur_el->element.graph.cur_left = g_cur_h_start;
    cur_el->element.graph.depth = depth;
    cur_el->element.graph.scale = scale;
    cur_el->element.graph.width = width;
    cur_el->element.graph.xoff = xoff;
    cur_el->element.graph.yoff = yoff;
    ProcFlags.skips_valid = false;
    memcpy( cur_el->element.graph.file, file, len + 1 );
    insert_col_main( cur_el );

    if( *p == '.' ) {
        p++;
    }
    scan_start = p;                 // process following text
}
Exemplo n.º 10
0
void    scr_ga( void )
{
    char        *   p;
    char        *   pn;
    char            savetag;
    char            saveatt;
    int             k;
    int             len;
    condcode        cc;
    gaflags         att_flags;
    gavalflags      val_flags;
    gavalentry  *   gaval;
    gaentry     *   gawk;


    savetag = ' ';
    saveatt = ' ';
    att_flags = 0;
    val_flags = 0;
    garginit();                         // find end of CW

    cc = getarg();                      // Tagname or *

    if( cc == omit || (*tok_start == '*' && tag_entry == NULL) ) {
        // no operands or tagname * and no previous definition
        tag_name_missing_err();
    }
    if( tag_entry == NULL ) {           // error during previous .gt

        scan_restart = scan_stop + 1;   // ignore .ga
        return;
    }


    /***********************************************************************/
    /*  isolate tagname  use previous if tagname *                         */
    /***********************************************************************/

    p = tok_start;

    if( *p == '*' ) {                   // single * as tagname
        if( arg_flen > 1 ) {
            xx_err( err_tag_name_inv );
            return;
        }
        savetag = '*';                  // remember for possible quick access
        if( GlobalFlags.firstpass && input_cbs->fmflags & II_research ) {
            out_msg("  using tagname %s\n", tagname );
        }
    } else {
        savetag = ' ';                  // no quick access

        init_tag_att();            // forget previous values for quick access

        pn      = tagname;
        len     = 0;

        while( *p && is_macro_char( *p ) ) {
            if( len < TAG_NAME_LENGTH ) {
                *pn++ = tolower( *p++ );// copy lowercase tagname
                *pn   = '\0';
            } else {
                break;
            }
            len++;
        }
        for( k = len; k < TAG_NAME_LENGTH; k++ ) {
            tagname[k] = '\0';
        }
        tagname[TAG_NAME_LENGTH] = '\0';

        if( len < arg_flen ) {
            xx_err( err_tag_name_inv );// name contains invalid or too many chars
            return;
        }
        tag_entry = find_tag( &tag_dict, tagname );
        if( tag_entry == NULL ) {
            nottag_err();               // tagname not defined
            return;
        }
    }

    /***********************************************************************/
    /* isolate attname  use previous if attname *                          */
    /***********************************************************************/

    cc = getarg();                      // Attribute  name or *

    if( cc == omit || (*tok_start == '*' && att_entry == NULL) ) {
        // no operands or attname * and no previous definition
        xx_err( err_att_name_inv );
        return;
    }

    p = tok_start;

    if( *p == '*' ) {                   // single * as attname
        if( arg_flen > 1 ) {
            xx_err( err_att_name_inv );
            return;
        }
        saveatt = '*';                  // remember for possible quick access
        if( GlobalFlags.firstpass && input_cbs->fmflags & II_research ) {
            out_msg("  using attname %s\n", attname );
        }
        att_flags = att_entry->attflags;
    } else {
        saveatt = ' ';                  // no quick access
        att_entry = NULL;
        pn      = attname;
        len     = 0;

        while( *p && is_macro_char( *p ) ) {
            if( len < ATT_NAME_LENGTH ) {
                *pn++ = tolower( *p++ );// copy lowercase tagname
                *pn   = '\0';
            } else {
                break;
            }
            len++;
        }
        for( k = len; k < ATT_NAME_LENGTH; k++ ) {
            attname[k] = '\0';
        }
        attname[ATT_NAME_LENGTH] = '\0';

        if( len < arg_flen ) {
            xx_err( err_att_name_inv );// attname with invalid or too many chars
            cc = neg;
            return;
        }
    }


    /***********************************************************************/
    /*   process options A and options B                                   */
    /***********************************************************************/

    if( cc != omit ) {
        if( saveatt != '*' ) {          // no quickaccess for attribute
            gawk = NULL;
            for( gawk = tag_entry->attribs; gawk != NULL;
                 gawk = gawk->next ) {

                if( !stricmp( attname, gawk->name ) ) {
                    att_flags = gawk->attflags; // get possible uppercase option
                    break;
                }
            }
        } else {
            att_flags = att_entry->attflags;
        }
        cc = scan_att_optionsA( &att_flags );   // process options A

        if( cc != omit ) {

            cc = scan_att_optionsB( &val_flags, cc, &att_flags );// process option B
            if( cc != omit ) {
                xx_err( err_tag_toomany );  // excess parameters
                return;
            }
        }
    }

    /***********************************************************************/
    /*  scanning complete     add/modify attribute in dictionary           */
    /***********************************************************************/
    if( saveatt != '*' ) {              // no quickaccess for attribute
        for( att_entry = tag_entry->attribs; att_entry != NULL;
             att_entry = att_entry->next ) {

            if( !stricmp( attname, att_entry->name ) ) {
                break;
            }
        }
    }
    if( att_entry == NULL ) {           // new attribute
        att_entry = mem_alloc( sizeof( gaentry ) );

        att_entry->next = tag_entry->attribs;
        tag_entry->attribs = att_entry;

        att_entry->vals = NULL;
        att_entry->attflags = att_flags;
        strcpy( att_entry->name, attname );
    } else {
        att_entry->attflags = att_flags;// update flags
    }

    gaval = mem_alloc( sizeof (gavalentry ) );

    if( att_entry->vals == NULL ) {
        att_entry->vals = gaval;
    } else {
        gavalentry  *   valwk;

        for( valwk = att_entry->vals;  valwk != NULL;
                                       valwk = valwk->next ) {
            if( valwk->next == NULL ) {
                break;                      // last entry found
            }
        }
        valwk->next = gaval;
    }
    gaval->next = NULL;

    gaval->valflags = val_flags;
    if( val_flags & val_length ) {
        gaval->a.length = ranges[0];
    } else if( val_flags & val_range ) {
        for( k = 0; k < 4; k++ ) {
            gaval->a.range[k] = ranges[k];
        }
    } else if( val_flags & val_value ) {
        strcpy_s( gaval->a.value, sizeof( gaval->a.value ), stringval );
    } else if( val_flags & val_valptr ) {
        gaval->a.valptr = valptr;
    }
    scan_restart = scan_stop + 1;
    return;
}
Exemplo n.º 11
0
static  condcode    scan_att_optionsB( gavalflags * val_flags, condcode cca,
                                       gaflags * att_flags )
{
    condcode        cc;
    getnum_block    gn;
    int             k;

    if( cca == omit ) {
        return( cca );                  // no more parms
    }

    stringval[0] = '\0';
    cc = pos;

    switch( tolower( *tok_start ) ) {
    case   'a' :
        if( !strnicmp( "ANY", tok_start, arg_flen ) ) {

            *val_flags |= val_any;
            *att_flags |= att_any;
        } else {
            if( (arg_flen > 3) && (arg_flen < 10)
                && !strnicmp( "AUTOmatic", tok_start, arg_flen ) ) {

                *val_flags |= val_auto;
                *att_flags |= att_auto;
            } else {
                xx_err( err_att_val_inv );
                cc = neg;
            }
        }

        if( cc != neg ) {               // any or auto found now scan string
            cc = getarg();
            if( cc == quotes || cc == pos || cc == quotes0) {
                if( arg_flen < sizeof( stringval ) ) {
                    strncpy_s( stringval, sizeof( stringval), tok_start,
                               arg_flen );
                    *val_flags |= val_value;
                } else {
                    valptr = mem_alloc( arg_flen + 1 );
                    strncpy_s( valptr, arg_flen + 1, tok_start, arg_flen );
                    *val_flags |= val_valptr;
                }
                if( *att_flags & att_any ) { // default for any specified
                    *val_flags |= val_def;
                    *att_flags |= att_def;
                }
            }
        }
        break;
    case   'r' :
        if( (arg_flen > 2) && (arg_flen < 6)
            && !strnicmp( "RANge", tok_start, arg_flen ) ) {

            *val_flags |= val_range;
            *att_flags |= att_range;

            gn.argstart = scan_start;
            gn.argstop  = scan_stop;
            gn.ignore_blanks = false;
            ranges[2] = LONG_MIN;
            ranges[3] = LONG_MIN;
            for( k = 0; k < 4; k++ ) {  // scan max 4 numbers

                cc = getnum( &gn );
                if(  cc == omit ) {
                    break;
                }
                if( cc == notnum ) {
                    xx_err( err_att_val_inv );
                    cc = neg;
                    return( cc );
                }
                ranges[k] = gn.result;
            }
            scan_start = gn.argstart;
            if( (k < 2) || (ranges[0] > ranges[1]) ) {// need 2 or more values
                xx_err( err_att_range_inv );// ... second <= first
                cc = neg;
                return( cc );
            }
            if( k == 3 ) {
                ranges[3] = ranges[2];  // only 1 default specified
            }
            if( k > 2 ) {               // default specified
                if( (ranges[0] > ranges[2]) // default less min
                    || (ranges[1] < ranges[2])  // default gt max
                    || (ranges[0] > ranges[3])  // default2 less min
                    || (ranges[1] < ranges[3]) ) {  // default2 gt max
                    xx_err( err_att_default );
                    cc = neg;
                    return( cc );
                }
            }
            if( ranges[2] > LONG_MIN ) {
                *val_flags |= val_def;  // we have default
                *att_flags |= att_def;  // we have default
            }
        } else {
            if( (arg_flen == 5)
                && !strnicmp( "RESET", tok_start, arg_flen ) ) {

                *val_flags |= val_reset;
                /* no further processing */
            } else {
                cc = neg;
            }
        }
        break;
    case   'l' :
        if( (arg_flen > 2) && (arg_flen < 7)
            && !strnicmp( "LENgth", tok_start, arg_flen ) ) {

            *val_flags |= val_length;
            gn.argstart = scan_start;
            gn.argstop  = scan_stop;
            gn.ignore_blanks = false;
            cc = getnum( &gn );
            if( cc == notnum || cc == omit ) {
                xx_err( err_att_val_inv );
                cc = neg;
                return( cc );
            } else {
                scan_start = gn.argstart;
                ranges [0] = gn.result;
            }
        } else {
            cc = neg;
        }
        break;
    case   'v' :
        if( (arg_flen > 2) && (arg_flen < 6)
            && !strnicmp( "VALue", tok_start, arg_flen ) ) {

            cc = getarg();
            if( (cc == pos) || (cc == quotes) || (cc == quotes0) ) {
                 if( arg_flen <= VAL_LENGTH ) {
                    *val_flags |= val_value;
                    strncpy_s( stringval, VAL_LENGTH + 1, tok_start,
                               arg_flen );
                    if( *att_flags & att_upper ) {
                        strupr( stringval );
                    }
                 } else {
#if 1
                    xx_err( err_att_val_inv );  // only short string allowed
                    cc = neg;           // this is a restriction from wgml 4.0
                    break;              // can be removed if neccessary
#else
                    *val_flags |= val_valptr;
                    valptr = mem_alloc( arg_flen + 1 );
                    strncpy_s( valptr, arg_flen + 1, tok_start, arg_flen );
                    if( *att_flags & att_upper ) {
                        strupr( valptr );
                    }
#endif
                 }
            } else {
                xx_err( err_att_val_inv );
                cc = neg;
                break;
            }
            cc = getarg();
            if( cc == omit ) {          // nothing more
                break;
            }
            if( cc == pos && (arg_flen > 2) && (arg_flen < 8)
                && !strnicmp( "DEFault", tok_start, arg_flen ) ) {

                *val_flags |= val_def;
                *att_flags |= att_def;
            } else {
                xx_err( err_att_val_inv );
                cc = neg;
                break;
            }
        } else {
            cc = neg;
        }
        break;
    default:
        cc = neg;                   // invalid option
        break;
    }
    if( cc == omit || cc == neg ) {
       ; /* empty pass thru cc */
    } else {
        cc = getarg();                  // set new cc omit is expected
    }
    return( cc );
}