rtf.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 779 行 · 第 1/2 页

C
779
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  This file defines the RTF specific functions.
*
****************************************************************************/

#include "whpcvt.h"

#define MAX_LISTS       20

enum {
    LPREFIX_NONE                = 0x0,
    LPREFIX_S_LIST              = 0x1,
    LPREFIX_FIX_FI              = 0x2,
    LPREFIX_E_LIST              = 0x4,
    LPREFIX_PAR_RESET           = 0x8,
    LPREFIX_LEFTALIGN           = 0x10,
    LPREFIX_BOX_ON              = 0x20,
};
static unsigned long            Line_prefix=LPREFIX_NONE;
enum {
    LPOSTFIX_NONE,
    LPOSTFIX_TERM,
};
static int              Line_postfix=LPOSTFIX_NONE;

static char Reset_font_str[]="\\plain\\f2\\fs20";
static char Rtf_ctl_prefix[]="{\\footnote \\pard\\plain \\sl240 \\fs20 ";


enum {
    LIST_SPACE_COMPACT,
    LIST_SPACE_STANDARD,
};
enum {
    LIST_TYPE_NONE,
    LIST_TYPE_UNORDERED,
    LIST_TYPE_ORDERED,
    LIST_TYPE_SIMPLE,
    LIST_TYPE_DEFN
};
typedef struct {
    int                 type;
    int                 number;
    int                 prev_indent;
    int                 compact;
} list_def;

static list_def         Lists[MAX_LISTS]={
    { LIST_TYPE_NONE,   0,      0 },            // list base
};
static int              List_level=0;
static list_def         *Curr_list=&Lists[0];

static bool             Blank_line=FALSE;
static int              Curr_indent=0;
static bool             Eat_blanks=FALSE;

#define RTF_CHAR_SIZE   180

#define RTF_TRANS_LEN           50

static char *Trans_str=NULL;
static int Trans_len=0;

static void trans_add_tabs(
/*************************/

    section_def         *section,
    int                 *alloc_size
) {
    int                 tab;
    char                buf[30];

    trans_add_str( "\\pard ", section, alloc_size );
    for( tab = 1; tab <= NUM_TAB_STOPS; ++tab ) {
        sprintf( buf, "\\tx%d ", INDENT_INC * tab );
        trans_add_str( buf, section, alloc_size );
    }
    sprintf( buf, "\\li%d ", Curr_indent );
    trans_add_str( buf, section, alloc_size );
}

static void set_compact(
/**********************/

    char                *line
) {
    ++line;
    if( *line == 'c' ) {
        /* compact list */
        Curr_list->compact = LIST_SPACE_COMPACT;
    } else {
        Curr_list->compact = LIST_SPACE_STANDARD;
    }
}

static int translate_char_rtf(
/****************************/

    char                ch,
    char                *buf,
    int                 do_quotes
) {
    switch( ch ) {

    case '}':
        strcpy( buf,  "\\}" );
        break;

    case '{':
        strcpy( buf, "\\{" );
        break;

    case '\\':
        strcpy( buf, "\\\\" );
        break;

    case '"':
        if( do_quotes ) {
            strcpy( buf, "\\\"" );
            break;
        }
        /* fall into default case */

    default:
        buf[0] = ch;
        buf[1] = '\0';
        break;
    }

    return( strlen( buf ) );
}

static char *translate_str_rtf(
/*****************************/

    char                *str,
    int                 do_quotes
) {
    char                *t_str;
    int                 len;
    char                buf[RTF_TRANS_LEN];
    char                *ptr;

    len = 1;
    for( t_str = str; *t_str != '\0'; ++t_str ) {
        len += translate_char_rtf( *t_str, buf, do_quotes );
    }
    if( len > Trans_len ) {
        if( Trans_str != NULL ) {
            _free( Trans_str );
        }
        _new( Trans_str, len );
        Trans_len = len;
    }
    ptr = Trans_str;
    for( t_str = str; *t_str != '\0'; ++t_str ) {
        len = translate_char_rtf( *t_str, buf, do_quotes );
        strcpy( ptr, buf );
        ptr += len;
    }
    *ptr = '\0';

    return( Trans_str );
}

static int trans_add_char_rtf(
/****************************/

    char                ch,
    section_def         *section,
    int                 *alloc_size
) {
    char                buf[RTF_TRANS_LEN];

    translate_char_rtf( ch, buf, FALSE );
    return( trans_add_str( buf, section, alloc_size ) );
}

static void new_list(
/*******************/

    int                 type
) {
    ++List_level;
    if( List_level == MAX_LISTS ) {
        error( ERR_MAX_LISTS, TRUE );
    }
    Curr_list = &Lists[List_level];
    Curr_list->type = type;
    Curr_list->number = 1;
    Curr_list->prev_indent = Curr_indent;
    Curr_list->compact = LIST_SPACE_STANDARD;
}

static void pop_list( void )
/**************************/
{
    Curr_indent = Curr_list->prev_indent;
    --List_level;
    Curr_list = &Lists[List_level];
}

static void add_tabxmp(
/*********************/

    char                *tab_line,
    section_def         *section,
    int                 *alloc_size
) {
    char                *ptr;
    char                buf[50];
    int                 tabcol;

    trans_add_str( "\\pard ", section, alloc_size );
    Tab_xmp_char = *tab_line;
    ptr = strtok( tab_line + 1, " " );
    for( tabcol = 0 ; ptr != NULL; ptr = strtok( NULL, " " ) ) {
        if( *ptr == '+' ) {
            tabcol += atoi( ptr + 1 );
        } else {
            tabcol = atoi( ptr );
        }
        sprintf( buf, "\\tx%d ", RTF_CHAR_SIZE * tabcol );
        trans_add_str( buf, section, alloc_size );
    }
    trans_add_char( '\n', section, alloc_size );
}

void rtf_topic_init( void )
/*************************/
{
    Line_prefix = LPREFIX_NONE;
}

int rtf_trans_line(
/*****************/

    section_def         *section,
    int                 alloc_size
) {
    char                *ptr;
    char                *end;
    char                ch;
    char                *ctx_name;
    char                *ctx_text;
    char                buf[100];
    int                 indent;
    char                *file_name;

    /* check for special pre-processing stuff first */
    ptr = Line_buf;
    ch = *ptr;

    if( Blank_line && ( ch != CH_LIST_ITEM ||
                        Curr_list->compact != LIST_SPACE_COMPACT ) ) {
        Blank_line = FALSE;
    }
    switch( ch ) {

    case CH_TABXMP:
        if( *skip_blank( ptr + 1 ) == '\0' ) {
            Line_prefix |= LPREFIX_PAR_RESET;
            Tab_xmp = FALSE;
        } else {
            add_tabxmp( ptr + 1, section, &alloc_size );
            Tab_xmp = TRUE;
        }
        return( alloc_size );

    case CH_BOX_ON:
        Line_prefix |= LPREFIX_BOX_ON;
        return( alloc_size );

    case CH_BOX_OFF:
        Line_prefix |= LPREFIX_PAR_RESET;
        return( alloc_size );

    case CH_OLIST_START:
        new_list( LIST_TYPE_ORDERED );
        set_compact( ptr );
        Line_prefix |= LPREFIX_S_LIST;
        Curr_indent += INDENT_INC + Start_inc_ol;
        return( alloc_size );

    case CH_LIST_START:
    case CH_DLIST_START:
        new_list( ( ch == CH_LIST_START ) ? LIST_TYPE_UNORDERED :
                                                        LIST_TYPE_DEFN );
        set_compact( ptr );
        Line_prefix |= LPREFIX_S_LIST;
        Curr_indent += INDENT_INC +
                        ((ch == CH_LIST_START) ? Start_inc_ul : Start_inc_dl);
        if( ch == CH_DLIST_START ) {
            ptr = skip_blank( ptr +1 );
            if( *ptr != '\0' ) {
                /* due to a weakness in GML, the definition term must be
                   allowed on the same line as the definition tag. So
                   if its there, continue */
                break;
            }
        }
        return( alloc_size );

    case CH_SLIST_START:
        indent = Start_inc_sl;
        if( indent == 0 && Curr_list->type == LIST_TYPE_SIMPLE ) {
            /* nested simple lists, with no pre-indent. Force an
               indent */
            indent = INDENT_INC;
        }

        new_list( LIST_TYPE_SIMPLE );
        set_compact( ptr );
        Curr_indent += indent;
        if( indent != 0 ) {
            Line_prefix |= LPREFIX_S_LIST;
        }
        return( alloc_size );

    case CH_SLIST_END:
        if( Curr_list->prev_indent != Curr_indent ) {
            Line_prefix |= LPREFIX_E_LIST;
        }
        pop_list();
        return( alloc_size );

    case CH_OLIST_END:
        pop_list();
        Line_prefix |= LPREFIX_E_LIST;
        return( alloc_size );

    case CH_LIST_END:
        pop_list();
        Line_prefix |= LPREFIX_E_LIST;
        return( alloc_size );

    case CH_DLIST_END:
        pop_list();
        Line_prefix |= LPREFIX_E_LIST;
        return( alloc_size );

    case CH_DLIST_DESC:
        if( *skip_blank( ptr + 1 ) == '\0' ) {
            /* no description on this line. Ignore it so that no
               blank line gets generated */
            return( alloc_size );
        }
        break;

    case CH_CTX_KW:
        ptr = whole_keyword_line( ptr );
        if( ptr == NULL ) {
            return( alloc_size );
        }
        break;
    }

    if( *skip_blank( ptr ) == '\0' && Curr_ctx->empty ) {
        /* skip preceding blank lines */
        return( alloc_size );
    }

    if( Blank_line ) {
        /* remove '\n' on the end */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?