Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. /*=============================================================================
  3.    GNU UnRTF, a command-line program to convert RTF documents to other formats.
  4.    Copyright (C) 2000,2001 Zachary Thayer Smith
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20.    The author is reachable by electronic mail at tuorfa@yahoo.com.
  21. =============================================================================*/
  22.  
  23.  
  24. /*----------------------------------------------------------------------
  25.  * Module name:    attr
  26.  * Author name:    Zach Smith
  27.  * Create date:    01 Aug 01
  28.  * Purpose:        Character attribute stack.
  29.  *----------------------------------------------------------------------
  30.  * Changes:
  31.  * 01 Aug 01, tuorfa@yahoo.com: moved code over from convert.c
  32.  * 06 Aug 01, tuorfa@yahoo.com: added several font attributes.
  33.  * 18 Sep 01, tuorfa@yahoo.com: added AttrStack (stack of stacks) paradigm
  34.  * 22 Sep 01, tuorfa@yahoo.com: added comment blocks
  35.  *--------------------------------------------------------------------*/
  36.  
  37.  
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include <stdlib.h>
  41.  
  42. #include "malloc.h"
  43. #include "defs.h"
  44. #include "error.h"
  45. #include "attr.h"
  46. #include "main.h"
  47.  
  48.  
  49. extern void starting_body();
  50. extern void starting_text();
  51.  
  52. extern int simulate_allcaps;
  53. extern int simulate_smallcaps;
  54.  
  55.  
  56. #define MAX_ATTRS (1000)
  57.  
  58.  
  59.  
  60. /* For each RTF text block (the text within braces) we must keep
  61.  * an AttrStack which is a stack of attributes and their optional
  62.  * parameter. Since RTF text blocks are nested, these make up a
  63.  * stack of stacks. And, since RTF text blocks inherit attributes
  64.  * from parent blocks, all new AttrStacks do the same from
  65.  * their parent AttrStack.
  66.  */
  67. typedef struct _stack {
  68.         unsigned char attr_stack [MAX_ATTRS];
  69.         char *attr_stack_params [MAX_ATTRS];
  70.         int tos;
  71.         struct _stack *next;
  72. }
  73. AttrStack;
  74.  
  75. static AttrStack *stack_of_stacks = NULL;
  76. static AttrStack *stack_of_stacks_top = NULL;
  77.  
  78.  
  79.  
  80.  
  81. /*========================================================================
  82.  * Name:        attr_express_begin
  83.  * Purpose:     Print the HTML for beginning an attribute.
  84.  * Args:        Attribute number, optional string parameter.
  85.  * Returns:     None.
  86.  *=======================================================================*/
  87.  
  88. void
  89. attr_express_begin (int attr, char* param) {
  90.         switch(attr)
  91.         {
  92.         case ATTR_BOLD:
  93.                 printf (op->bold_begin);
  94.                 break;
  95.         case ATTR_ITALIC:
  96.                 printf (op->italic_begin);
  97.                 break;
  98.  
  99.         /* Various underlines, they all resolve to HTML's <u> */
  100.         case ATTR_THICK_UL:
  101.         case ATTR_WAVE_UL:
  102.         case ATTR_DASH_UL:
  103.         case ATTR_DOT_UL:
  104.         case ATTR_DOT_DASH_UL:
  105.         case ATTR_2DOT_DASH_UL:
  106.         case ATTR_WORD_UL:
  107.         case ATTR_UNDERLINE:
  108.                 printf (op->underline_begin);
  109.                 break;
  110.  
  111.         case ATTR_DOUBLE_UL:
  112.                 printf (op->dbl_underline_begin);
  113.                 break;
  114.  
  115.         case ATTR_FONTSIZE:
  116.                 op_begin_std_fontsize (op, atoi (param));
  117.                 break;
  118.  
  119.         case ATTR_FONTFACE:
  120.                 printf (op->font_begin,param);
  121.                 break;
  122.  
  123.         case ATTR_FOREGROUND:
  124.                 printf (op->foreground_begin, param);
  125.                 break;
  126.  
  127.         case ATTR_BACKGROUND:
  128.                 if (!simple_mode)
  129.                   printf (op->foreground_begin,param);
  130.                 break;
  131.  
  132.         case ATTR_SUPER:
  133.                 printf (op->superscript_begin);
  134.                 break;
  135.         case ATTR_SUB:
  136.                 printf (op->subscript_begin);
  137.                 break;
  138.  
  139.         case ATTR_STRIKE:
  140.                 printf (op->strikethru_begin);
  141.                 break;
  142.  
  143.         case ATTR_DBL_STRIKE:
  144.                 printf (op->dbl_strikethru_begin);
  145.                 break;
  146.  
  147.         case ATTR_EXPAND:
  148.                 printf (op->expand_begin, param);
  149.                 break;
  150.  
  151.         case ATTR_OUTLINE:
  152.                 printf (op->outline_begin);
  153.                 break;
  154.         case ATTR_SHADOW:
  155.                 printf (op->shadow_begin);
  156.                 break;
  157.         case ATTR_EMBOSS:
  158.                 printf (op->emboss_begin);
  159.                 break;
  160.         case ATTR_ENGRAVE:
  161.                 printf (op->engrave_begin);
  162.                 break;
  163.  
  164.         case ATTR_CAPS:
  165.                 if (op->simulate_all_caps)
  166.                         simulate_allcaps = TRUE;
  167.                 break;
  168.  
  169.         case ATTR_SMALLCAPS:
  170.                 if (op->simulate_small_caps)
  171.                         simulate_smallcaps = TRUE;
  172.                 else {
  173.                         if (op->small_caps_begin)
  174.                                 printf (op->small_caps_begin);
  175.                 }
  176.                 break;
  177.         }
  178. }
  179.  
  180.  
  181. /*========================================================================
  182.  * Name:        attr_express_end
  183.  * Purpose:     Print HTML to complete an attribute.
  184.  * Args:        Attribute number.
  185.  * Returns:     None.
  186.  *=======================================================================*/
  187.  
  188. void
  189. attr_express_end (int attr, char *param)
  190. {
  191.         switch(attr)
  192.         {
  193.         case ATTR_BOLD:
  194.                 printf (op->bold_end);
  195.                 break;
  196.         case ATTR_ITALIC:
  197.                 printf (op->italic_end);
  198.                 break;
  199.  
  200.         /* Various underlines, they all resolve to HTML's </u> */
  201.         case ATTR_THICK_UL:
  202.         case ATTR_WAVE_UL:
  203.         case ATTR_DASH_UL:
  204.         case ATTR_DOT_UL:
  205.         case ATTR_DOT_DASH_UL:
  206.         case ATTR_2DOT_DASH_UL:
  207.         case ATTR_WORD_UL:
  208.         case ATTR_UNDERLINE:
  209.                 printf (op->underline_end);
  210.                 break;
  211.  
  212.         case ATTR_DOUBLE_UL:
  213.                 printf (op->dbl_underline_end);
  214.                 break;
  215.  
  216.         case ATTR_FONTSIZE:
  217.                 op_end_std_fontsize (op, atoi (param));
  218.                 break;
  219.  
  220.         case ATTR_FONTFACE:
  221.                 printf (op->font_end);
  222.                 break;
  223.  
  224.         case ATTR_FOREGROUND:
  225.                 printf (op->foreground_end);
  226.                 break;
  227.         case ATTR_BACKGROUND:
  228.                 if (!simple_mode)
  229.                   printf (op->background_end);
  230.                 break;
  231.  
  232.         case ATTR_SUPER:
  233.                 printf (op->superscript_end);
  234.                 break;
  235.         case ATTR_SUB:
  236.                 printf (op->subscript_end);
  237.                 break;
  238.  
  239.         case ATTR_STRIKE:
  240.                 printf (op->strikethru_end);
  241.                 break;
  242.  
  243.         case ATTR_DBL_STRIKE:
  244.                 printf (op->dbl_strikethru_end);
  245.                 break;
  246.  
  247.         case ATTR_OUTLINE:
  248.                 printf (op->outline_end);
  249.                 break;
  250.         case ATTR_SHADOW:
  251.                 printf (op->shadow_end);
  252.                 break;
  253.         case ATTR_EMBOSS:
  254.                 printf (op->emboss_end);
  255.                 break;
  256.         case ATTR_ENGRAVE:
  257.                 printf (op->engrave_end);
  258.                 break;
  259.  
  260.         case ATTR_EXPAND:
  261.                 printf (op->expand_end);
  262.                 break;
  263.  
  264.         case ATTR_CAPS:
  265.                 if (op->simulate_all_caps)
  266.                         simulate_allcaps = FALSE;
  267.                 break;
  268.  
  269.         case ATTR_SMALLCAPS:
  270.                 if (op->simulate_small_caps)
  271.                         simulate_smallcaps = FALSE;
  272.                 else {
  273.                         if (op->small_caps_end)
  274.                                 printf (op->small_caps_end);
  275.                 }
  276.                 break;
  277.         }
  278. }
  279.  
  280.  
  281.  
  282. /*========================================================================
  283.  * Name:        attr_push
  284.  * Purpose:     Pushes an attribute onto the current attribute stack.
  285.  * Args:        Attribute number, optional string parameter.
  286.  * Returns:     None.
  287.  *=======================================================================*/
  288.  
  289. void
  290. attr_push(int attr, char* param)
  291. {
  292.         AttrStack *stack = stack_of_stacks_top;
  293.         if (!stack) {
  294.                 warning_handler ("no stack to push attribute onto");
  295.                 return;
  296.         }
  297.  
  298.         if (stack->tos>=MAX_ATTRS) { fprintf (stderr,"Too many attributes!\n"); return; }
  299.  
  300.         /* Make sure it's understood we're in the <body> section. */
  301.         /* KLUDGE */
  302.         starting_body();
  303.         starting_text();
  304.  
  305.         ++stack->tos;
  306.         stack->attr_stack [stack->tos]=attr;
  307.         if (param)
  308.                 stack->attr_stack_params [stack->tos]=my_strdup(param);
  309.         else
  310.                 stack->attr_stack_params [stack->tos]=NULL;
  311.  
  312.         attr_express_begin (attr, param);
  313. }
  314.  
  315.  
  316. /*========================================================================
  317.  * Name:        attrstack_copy_all
  318.  * Purpose:     Routine to copy all attributes from one stack to another.
  319.  * Args:        Two stacks.
  320.  * Returns:     None.
  321.  *=======================================================================*/
  322.  
  323. void
  324. attrstack_copy_all (AttrStack *src, AttrStack *dest)
  325. {
  326.         int i;
  327.         int total;
  328.  
  329.         CHECK_PARAM_NOT_NULL(src);
  330.         CHECK_PARAM_NOT_NULL(dest);
  331.  
  332.         total = src->tos + 1;
  333.  
  334.         for (i=0; i<total; i++)
  335.         {
  336.                 int attr=src->attr_stack [i];
  337.                 char *param=src->attr_stack_params [i];
  338.  
  339.                 dest->attr_stack[i] = attr;
  340.                 if (param)
  341.                         dest->attr_stack_params[i] = my_strdup (param);
  342.                 else
  343.                         dest->attr_stack_params[i] = NULL;
  344.         }
  345.  
  346.         dest->tos = src->tos;
  347. }
  348.  
  349. /*========================================================================
  350.  * Name:        attrstack_unexpress_all
  351.  * Purpose:     Routine to un-express all attributes heretofore applied,
  352.  *              without removing any from the stack.
  353.  * Args:        Stack whost contents should be unexpressed.
  354.  * Returns:     None.
  355.  * Notes:       This is needed by attrstack_push, but also for \cell, which
  356.  *              often occurs within a brace group, yet HTML uses <td></td>
  357.  *              which clear attribute info within that block.
  358.  *=======================================================================*/
  359.  
  360. void
  361. attrstack_unexpress_all (AttrStack *stack)
  362. {
  363.         int i;
  364.  
  365.         CHECK_PARAM_NOT_NULL(stack);
  366.  
  367.         i=stack->tos;
  368.         while (i>=0)
  369.         {
  370.                 int attr=stack->attr_stack [i];
  371.                 char *param=stack->attr_stack_params [i];
  372.  
  373.                 attr_express_end (attr, param);
  374.                 i--;
  375.         }
  376. }
  377.  
  378.  
  379. /*========================================================================
  380.  * Name:        attrstack_push
  381.  * Purpose:     Creates a new attribute stack, pushes it onto the stack
  382.  *              of stacks, performs inheritance from previous stack.
  383.  * Args:        None.
  384.  * Returns:     None.
  385.  *=======================================================================*/
  386. void
  387. attrstack_push ()
  388. {
  389.         AttrStack *new_stack;
  390.         AttrStack *prev_stack;
  391.  
  392.         new_stack = (AttrStack*) my_malloc (sizeof (AttrStack));
  393.         bzero ((void*) new_stack, sizeof (AttrStack));
  394.  
  395.         prev_stack = stack_of_stacks_top;
  396.  
  397.         if (!stack_of_stacks) {
  398.                 stack_of_stacks = new_stack;
  399.         } else {
  400.                 stack_of_stacks_top->next = new_stack;
  401.         }
  402.         stack_of_stacks_top = new_stack;
  403.         new_stack->tos = -1;
  404.  
  405.         if (prev_stack) {
  406.                 attrstack_unexpress_all (prev_stack);
  407.                 attrstack_copy_all (prev_stack, new_stack);
  408.                 attrstack_express_all ();
  409.         }
  410. }
  411.  
  412.  
  413.  
  414. /*========================================================================
  415.  * Name:        attr_pop
  416.  * Purpose:     Removes and undoes the effect of the top attribute of
  417.  *              the current AttrStack.
  418.  * Args:        The top attribute's number, for verification.
  419.  * Returns:     Success/fail flag.
  420.  *=======================================================================*/
  421.  
  422. int
  423. attr_pop (int attr)
  424. {
  425.         AttrStack *stack = stack_of_stacks_top;
  426.  
  427.         if (!stack) {
  428.                 warning_handler ("no stack to pop attribute from");
  429.                 return FALSE;
  430.         }
  431.  
  432.         if(stack->tos>=0 && stack->attr_stack[stack->tos]==attr)
  433.         {
  434.                 char *param = stack->attr_stack_params [stack->tos];
  435.  
  436.                 attr_express_end (attr, param);
  437.  
  438.                 if (param) my_free(param);
  439.  
  440.                 stack->tos--;
  441.  
  442.                 return TRUE;
  443.         }
  444.         else
  445.                 return FALSE;
  446. }
  447.  
  448.  
  449.  
  450. /*========================================================================
  451.  * Name:        attr_read
  452.  * Purpose:     Reads but leaves in place the top attribute of the top
  453.  *              attribute stack.
  454.  * Args:        None.
  455.  * Returns:     Attribute number.
  456.  *=======================================================================*/
  457.  
  458. int
  459. attr_read() {
  460.         AttrStack *stack = stack_of_stacks_top;
  461.         if (!stack) {
  462.                 warning_handler ("no stack to read attribute from");
  463.                 return FALSE;
  464.         }
  465.  
  466.         if(stack->tos>=0)
  467.         {
  468.                 int attr = stack->attr_stack [stack->tos];
  469.                 return attr;
  470.         }
  471.         else
  472.                 return ATTR_NONE;
  473. }
  474.  
  475.  
  476. /*========================================================================
  477.  * Name:        attr_drop_all
  478.  * Purpose:     Undoes all attributes that an AttrStack contains.
  479.  * Args:        None.
  480.  * Returns:     None.
  481.  *=======================================================================*/
  482.  
  483. void
  484. attr_drop_all ()
  485. {
  486.         AttrStack *stack = stack_of_stacks_top;
  487.         if (!stack) {
  488.                 warning_handler ("no stack to drop all attributes from");
  489.                 return;
  490.         }
  491.  
  492.         while (stack->tos>=0)
  493.         {
  494.                 char *param=stack->attr_stack_params [stack->tos];
  495.                 if (param) my_free(param);
  496.                 stack->tos--;
  497.         }
  498. }
  499.  
  500.  
  501. /*========================================================================
  502.  * Name:        attrstack_drop
  503.  * Purpose:     Removes the top AttrStack from the stack of stacks, undoing
  504.  *              all attributes that it had in it.
  505.  * Args:        None.
  506.  * Returns:     None.
  507.  *=======================================================================*/
  508.  
  509. void
  510. attrstack_drop ()
  511. {
  512.         AttrStack *stack = stack_of_stacks_top;
  513.         AttrStack *prev_stack;
  514.         if (!stack) {
  515.                 warning_handler ("no attr-stack to drop");
  516.                 return;
  517.         }
  518.  
  519.         attr_pop_all ();
  520.  
  521.         prev_stack = stack_of_stacks;
  522.         while(prev_stack && prev_stack->next && prev_stack->next != stack)
  523.                 prev_stack = prev_stack->next;
  524.  
  525.         if (prev_stack) {
  526.                 stack_of_stacks_top = prev_stack;
  527.                 prev_stack->next = NULL;
  528.         } else {
  529.                 stack_of_stacks_top = NULL;
  530.                 stack_of_stacks = NULL;
  531.         }
  532.         my_free ((void*) stack);
  533.  
  534.         attrstack_express_all ();
  535. }
  536.  
  537. /*========================================================================
  538.  * Name:        attr_pop_all
  539.  * Purpose:     Routine to undo all attributes heretofore applied,
  540.  *              also reversing the order in which they were applied.
  541.  * Args:        None.
  542.  * Returns:     None.
  543.  *=======================================================================*/
  544.  
  545. void
  546. attr_pop_all()
  547. {
  548.         AttrStack *stack = stack_of_stacks_top;
  549.         if (!stack) {
  550.                 warning_handler ("no stack to pop from");
  551.                 return;
  552.         }
  553.  
  554.         while (stack->tos>=0) {
  555.                 int attr=stack->attr_stack [stack->tos];
  556.                 char *param=stack->attr_stack_params [stack->tos];
  557.                 attr_express_end (attr,param);
  558.                 if (param) my_free(param);
  559.                 stack->tos--;
  560.         }
  561. }
  562.  
  563.  
  564. /*========================================================================
  565.  * Name:        attrstack_express_all
  566.  * Purpose:     Routine to re-express all attributes heretofore applied.
  567.  * Args:        None.
  568.  * Returns:     None.
  569.  * Notes:       This is needed by attrstack_push, but also for \cell, which
  570.  *              often occurs within a brace group, yet HTML uses <td></td>
  571.  *              which clear attribute info within that block.
  572.  *=======================================================================*/
  573.  
  574. void
  575. attrstack_express_all() {
  576.         AttrStack *stack = stack_of_stacks_top;
  577.         int i;
  578.  
  579.         if (!stack) {
  580.                 warning_handler ("no stack to pop from");
  581.                 return;
  582.         }
  583.  
  584.         i=0;
  585.         while (i<=stack->tos)
  586.         {
  587.                 int attr=stack->attr_stack [i];
  588.                 char *param=stack->attr_stack_params [i];
  589.                 attr_express_begin (attr, param);
  590.                 i++;
  591.         }
  592. }
  593.  
  594.  
  595. /*========================================================================
  596.  * Name:        attr_pop_dump
  597.  * Purpose:     Routine to un-express all attributes heretofore applied.
  598.  * Args:        None.
  599.  * Returns:     None.
  600.  * Notes:       This is needed for \cell, which often occurs within a
  601.  *              brace group, yet HTML uses <td></td> which clear attribute
  602.  *              info within that block.
  603.  *=======================================================================*/
  604.  
  605. void
  606. attr_pop_dump() {
  607.         AttrStack *stack = stack_of_stacks_top;
  608.         int i;
  609.  
  610.         if (!stack) return;
  611.  
  612.         i=stack->tos;
  613.         while (i>=0)
  614.         {
  615.                 int attr=stack->attr_stack [i];
  616.                 attr_pop (attr);
  617.                 i--;
  618.         }
  619. }
  620.  
  621.