401 lines
10 KiB
C
401 lines
10 KiB
C
|
|
||
|
/*=============================================================================
|
||
|
GNU UnRTF, a command-line program to convert RTF documents to other formats.
|
||
|
Copyright (C) 2000,2001 Zachary Thayer Smith
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
||
|
The author is reachable by electronic mail at tuorfa@yahoo.com.
|
||
|
=============================================================================*/
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
* Module name: output
|
||
|
* Author name: Zach Smith
|
||
|
* Create date: 18 Sep 01
|
||
|
* Purpose: Generalized output module
|
||
|
*----------------------------------------------------------------------
|
||
|
* Changes:
|
||
|
* 22 Sep 01, tuorfa@yahoo.com: addition of functions to change font size
|
||
|
* 22 Sep 01, tuorfa@yahoo.com: added function-level comment blocks
|
||
|
*--------------------------------------------------------------------*/
|
||
|
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include "malloc.h"
|
||
|
#include "defs.h"
|
||
|
#include "error.h"
|
||
|
#include "output.h"
|
||
|
#include "main.h"
|
||
|
#include "convert.h"
|
||
|
|
||
|
|
||
|
/*========================================================================
|
||
|
* Name: op_create
|
||
|
* Purpose: Creates a blank output personality.
|
||
|
* Args: None.
|
||
|
* Returns: Output personality struct.
|
||
|
*=======================================================================*/
|
||
|
|
||
|
OutputPersonality*
|
||
|
op_create ()
|
||
|
{
|
||
|
OutputPersonality* new_op;
|
||
|
|
||
|
new_op = (OutputPersonality*) my_malloc (sizeof(OutputPersonality));
|
||
|
if (!new_op)
|
||
|
error_handler ("cannot allocate output personality");
|
||
|
|
||
|
bzero ((void*) new_op, sizeof (OutputPersonality));
|
||
|
return new_op;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*========================================================================
|
||
|
* Name: op_free
|
||
|
* Purpose: Deallocates an output personality, but none of the strings
|
||
|
* it points to since they are usually constants.
|
||
|
* Args: OutputPersonality.
|
||
|
* Returns: None.
|
||
|
*=======================================================================*/
|
||
|
|
||
|
void
|
||
|
op_free (OutputPersonality *op)
|
||
|
{
|
||
|
CHECK_PARAM_NOT_NULL(op);
|
||
|
|
||
|
my_free ((void*) op);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*========================================================================
|
||
|
* Name: op_translate_char
|
||
|
* Purpose: Performs a translation of a character in the context of
|
||
|
* a given output personality.
|
||
|
* Args: OutputPersonality, character set#, character.
|
||
|
* Returns: String.
|
||
|
*=======================================================================*/
|
||
|
|
||
|
char *
|
||
|
op_translate_char (OutputPersonality *op, int charset, int ch)
|
||
|
{
|
||
|
short start;
|
||
|
char *result=NULL;
|
||
|
|
||
|
CHECK_PARAM_NOT_NULL(op);
|
||
|
|
||
|
if (ch >= 0x20 && ch < 0x80) {
|
||
|
result = op->ascii_translation_table [ch - 0x20];
|
||
|
}
|
||
|
else
|
||
|
if (charset != CHARSET_ANSI &&
|
||
|
charset != CHARSET_MAC &&
|
||
|
charset != CHARSET_CP437 &&
|
||
|
charset != CHARSET_CP850)
|
||
|
error_handler ("invalid character set value, cannot translate character");
|
||
|
else
|
||
|
switch (charset) {
|
||
|
case CHARSET_ANSI:
|
||
|
start = op->ansi_first_char;
|
||
|
if (ch >= start &&
|
||
|
ch <= op->ansi_last_char)
|
||
|
result = op->ansi_translation_table [ch-start];
|
||
|
break;
|
||
|
case CHARSET_MAC:
|
||
|
start = op->mac_first_char;
|
||
|
if (ch >= start &&
|
||
|
ch <= op->mac_last_char)
|
||
|
result = op->mac_translation_table [ch-start];
|
||
|
break;
|
||
|
case CHARSET_CP437:
|
||
|
start = op->cp437_first_char;
|
||
|
if (ch >= start &&
|
||
|
ch <= op->cp437_last_char)
|
||
|
result = op->cp437_translation_table [ch-start];
|
||
|
break;
|
||
|
case CHARSET_CP850:
|
||
|
start = op->cp850_first_char;
|
||
|
if (ch >= start &&
|
||
|
ch <= op->cp850_last_char)
|
||
|
result = op->cp850_translation_table [ch-start];
|
||
|
break;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*========================================================================
|
||
|
* Name: op_begin_std_fontsize
|
||
|
* Purpose: Prints whatever is necessary to perform a change in the
|
||
|
* current font size.
|
||
|
* Args: OutputPersonality, desired size.
|
||
|
* Returns: None.
|
||
|
*=======================================================================*/
|
||
|
|
||
|
void
|
||
|
op_begin_std_fontsize (OutputPersonality *op, int size)
|
||
|
{
|
||
|
int found_std_expr = FALSE;
|
||
|
|
||
|
CHECK_PARAM_NOT_NULL(op);
|
||
|
|
||
|
/* Look for an exact match with a standard point size.
|
||
|
*/
|
||
|
switch (size) {
|
||
|
case 8:
|
||
|
if (op->fontsize8_begin) {
|
||
|
printf (op->fontsize8_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 10:
|
||
|
if (op->fontsize10_begin) {
|
||
|
printf (op->fontsize10_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 12:
|
||
|
if (op->fontsize12_begin) {
|
||
|
printf (op->fontsize12_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 14:
|
||
|
if (op->fontsize14_begin) {
|
||
|
printf (op->fontsize14_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 18:
|
||
|
if (op->fontsize18_begin) {
|
||
|
printf (op->fontsize18_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 24:
|
||
|
if (op->fontsize24_begin) {
|
||
|
printf (op->fontsize24_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 36:
|
||
|
if (op->fontsize36_begin) {
|
||
|
printf (op->fontsize36_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 48:
|
||
|
if (op->fontsize48_begin) {
|
||
|
printf (op->fontsize48_begin);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* If no exact match, try to write out a change to the
|
||
|
* exact point size.
|
||
|
*/
|
||
|
if (!found_std_expr) {
|
||
|
if (op->fontsize_begin) {
|
||
|
char expr[16];
|
||
|
sprintf (expr, "%d", size);
|
||
|
printf (op->fontsize_begin, expr);
|
||
|
} else {
|
||
|
/* If we cannot write out a change for the exact
|
||
|
* point size, we must approximate to a standard
|
||
|
* size.
|
||
|
*/
|
||
|
if (size<9 && op->fontsize8_begin) {
|
||
|
printf (op->fontsize8_begin);
|
||
|
} else
|
||
|
if (size<11 && op->fontsize10_begin) {
|
||
|
printf (op->fontsize10_begin);
|
||
|
} else
|
||
|
if (size<13 && op->fontsize12_begin) {
|
||
|
printf (op->fontsize12_begin);
|
||
|
} else
|
||
|
if (size<16 && op->fontsize14_begin) {
|
||
|
printf (op->fontsize14_begin);
|
||
|
} else
|
||
|
if (size<21 && op->fontsize18_begin) {
|
||
|
printf (op->fontsize18_begin);
|
||
|
} else
|
||
|
if (size<30 && op->fontsize24_begin) {
|
||
|
printf (op->fontsize24_begin);
|
||
|
} else
|
||
|
if (size<42 && op->fontsize36_begin) {
|
||
|
printf (op->fontsize36_begin);
|
||
|
} else
|
||
|
if (size>40 && op->fontsize48_begin) {
|
||
|
printf (op->fontsize48_begin);
|
||
|
} else
|
||
|
/* If we can't even produce a good approximation,
|
||
|
* just try to get a font size near 12 point.
|
||
|
*/
|
||
|
if (op->fontsize12_begin)
|
||
|
printf (op->fontsize12_begin);
|
||
|
else
|
||
|
if (op->fontsize14_begin)
|
||
|
printf (op->fontsize14_begin);
|
||
|
else
|
||
|
if (op->fontsize10_begin)
|
||
|
printf (op->fontsize10_begin);
|
||
|
else
|
||
|
if (op->fontsize18_begin)
|
||
|
printf (op->fontsize18_begin);
|
||
|
else
|
||
|
if (op->fontsize8_begin)
|
||
|
printf (op->fontsize8_begin);
|
||
|
else
|
||
|
error_handler ("output personality lacks sufficient font size change capability");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*========================================================================
|
||
|
* Name: op_end_std_fontsize
|
||
|
* Purpose: Prints whatever is necessary to perform a change in the
|
||
|
* current font size.
|
||
|
* Args: OutputPersonality, desired size.
|
||
|
* Returns: None.
|
||
|
*=======================================================================*/
|
||
|
|
||
|
void
|
||
|
op_end_std_fontsize (OutputPersonality *op, int size)
|
||
|
{
|
||
|
int found_std_expr = FALSE;
|
||
|
|
||
|
CHECK_PARAM_NOT_NULL(op);
|
||
|
|
||
|
/* Look for an exact match with a standard point size.
|
||
|
*/
|
||
|
switch (size) {
|
||
|
case 8:
|
||
|
if (op->fontsize8_end) {
|
||
|
printf (op->fontsize8_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 10:
|
||
|
if (op->fontsize10_end) {
|
||
|
printf (op->fontsize10_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 12:
|
||
|
if (op->fontsize12_end) {
|
||
|
printf (op->fontsize12_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 14:
|
||
|
if (op->fontsize14_end) {
|
||
|
printf (op->fontsize14_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 18:
|
||
|
if (op->fontsize18_end) {
|
||
|
printf (op->fontsize18_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 24:
|
||
|
if (op->fontsize24_end) {
|
||
|
printf (op->fontsize24_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 36:
|
||
|
if (op->fontsize36_end) {
|
||
|
printf (op->fontsize36_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case 48:
|
||
|
if (op->fontsize48_end) {
|
||
|
printf (op->fontsize48_end);
|
||
|
found_std_expr = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* If no exact match, try to write out a change to the
|
||
|
* exact point size.
|
||
|
*/
|
||
|
if (!found_std_expr) {
|
||
|
if (op->fontsize_end) {
|
||
|
char expr[16];
|
||
|
sprintf (expr, "%d", size);
|
||
|
printf (op->fontsize_end, expr);
|
||
|
} else {
|
||
|
/* If we cannot write out a change for the exact
|
||
|
* point size, we must approximate to a standard
|
||
|
* size.
|
||
|
*/
|
||
|
if (size<9 && op->fontsize8_end) {
|
||
|
printf (op->fontsize8_end);
|
||
|
} else
|
||
|
if (size<11 && op->fontsize10_end) {
|
||
|
printf (op->fontsize10_end);
|
||
|
} else
|
||
|
if (size<13 && op->fontsize12_end) {
|
||
|
printf (op->fontsize12_end);
|
||
|
} else
|
||
|
if (size<16 && op->fontsize14_end) {
|
||
|
printf (op->fontsize14_end);
|
||
|
} else
|
||
|
if (size<21 && op->fontsize18_end) {
|
||
|
printf (op->fontsize18_end);
|
||
|
} else
|
||
|
if (size<30 && op->fontsize24_end) {
|
||
|
printf (op->fontsize24_end);
|
||
|
} else
|
||
|
if (size<42 && op->fontsize36_end) {
|
||
|
printf (op->fontsize36_end);
|
||
|
} else
|
||
|
if (size>40 && op->fontsize48_end) {
|
||
|
printf (op->fontsize48_end);
|
||
|
} else
|
||
|
/* If we can't even produce a good approximation,
|
||
|
* just try to get a font size near 12 point.
|
||
|
*/
|
||
|
if (op->fontsize12_end)
|
||
|
printf (op->fontsize12_end);
|
||
|
else
|
||
|
if (op->fontsize14_end)
|
||
|
printf (op->fontsize14_end);
|
||
|
else
|
||
|
if (op->fontsize10_end)
|
||
|
printf (op->fontsize10_end);
|
||
|
else
|
||
|
if (op->fontsize18_end)
|
||
|
printf (op->fontsize18_end);
|
||
|
else
|
||
|
if (op->fontsize8_end)
|
||
|
printf (op->fontsize8_end);
|
||
|
else
|
||
|
error_handler ("output personality lacks sufficient font size change capability");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|