[BACK]Return to eqn_html.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/eqn_html.c between version 1.7 and 1.8

version 1.7, 2014/09/28 20:14:20 version 1.8, 2014/10/10 08:44:24
Line 27 
Line 27 
 #include "out.h"  #include "out.h"
 #include "html.h"  #include "html.h"
   
 static  const enum htmltag fontmap[EQNFONT__MAX] = {  static void
         TAG_SPAN, /* EQNFONT_NONE */  eqn_box(struct html *p, const struct eqn_box *bp)
         TAG_SPAN, /* EQNFONT_ROMAN */  
         TAG_B, /* EQNFONT_BOLD */  
         TAG_B, /* EQNFONT_FAT */  
         TAG_I /* EQNFONT_ITALIC */  
 };  
   
 static const struct eqn_box *  
         eqn_box(struct html *, const struct eqn_box *, int);  
   
   
 void  
 print_eqn(struct html *p, const struct eqn *ep)  
 {  {
         struct htmlpair  tag;          struct tag      *post, *row, *cell, *t;
         struct tag      *t;  
   
         PAIR_CLASS_INIT(&tag, "eqn");  
         t = print_otag(p, TAG_MATH, 1, &tag);  
   
         p->flags |= HTML_NONOSPACE;  
         eqn_box(p, ep->root, 1);  
         p->flags &= ~HTML_NONOSPACE;  
   
         print_tagq(p, t);  
 }  
   
 /*  
  * This function is fairly brittle.  
  * This is because the eqn syntax doesn't play so nicely with recusive  
  * formats, e.g.,  
  *     foo sub bar sub baz  
  * ...needs to resolve into  
  *     <msub> foo <msub> bar, baz </msub> </msub>  
  * In other words, we need to embed some recursive work.  
  * FIXME: this does NOT handle right-left associativity or precedence!  
  */  
 static const struct eqn_box *  
 eqn_box(struct html *p, const struct eqn_box *bp, int next)  
 {  
         struct tag      *post, *pilet, *tmp;  
         struct htmlpair  tag[2];          struct htmlpair  tag[2];
         int              skiptwo;          const struct eqn_box *child, *parent;
           size_t           i, j, rows;
   
         if (NULL == bp)          if (NULL == bp)
                 return(NULL);                  return;
   
         post = pilet = NULL;          post = NULL;
         skiptwo = 0;  
   
         /*          /*
          * If we're a "row" under a pile, then open up the piling           * Special handling for a matrix, which is presented to us in
          * context here.           * column order, but must be printed in row-order.
          * We do this first because the pile surrounds the content of  
          * the contained expression.  
          */           */
         if (NULL != bp->parent && bp->parent->pile != EQNPILE_NONE) {          if (EQN_MATRIX == bp->type) {
                 pilet = print_otag(p, TAG_MTR, 0, NULL);                  if (NULL == bp->first)
                 print_otag(p, TAG_MTD, 0, NULL);                          goto out;
                   assert(EQN_LIST == bp->first->type);
                   if (NULL == (parent = bp->first->first))
                           goto out;
                   assert(EQN_PILE == parent->type);
                   /* Estimate the number of rows, first. */
                   if (NULL == (child = parent->first))
                           goto out;
                   for (rows = 0; NULL != child; rows++)
                           child = child->next;
                   /* Print row-by-row. */
                   post = print_otag(p, TAG_MTABLE, 0, NULL);
                   for (i = 0; i < rows; i++) {
                           parent = bp->first->first;
                           row = print_otag(p, TAG_MTR, 0, NULL);
                           while (NULL != parent) {
                                   child = parent->first;
                                   for (j = 0; j < i; j++) {
                                           if (NULL == child)
                                                   break;
                                           child = child->next;
                                   }
                                   cell = print_otag
                                           (p, TAG_MTD, 0, NULL);
                                   /*
                                    * If we have no data for this
                                    * particular cell, then print a
                                    * placeholder and continue--don't puke.
                                    */
                                   if (NULL != child)
                                           eqn_box(p, child->first);
                                   print_tagq(p, cell);
                                   parent = parent->next;
                           }
                           print_tagq(p, row);
                   }
                   goto out;
         }          }
         if (NULL != bp->parent && bp->parent->type == EQN_MATRIX) {  
                 pilet = print_otag(p, TAG_MTABLE, 0, NULL);  
                 print_otag(p, TAG_MTR, 0, NULL);  
                 print_otag(p, TAG_MTD, 0, NULL);  
         }  
   
         /*  
          * If we're establishing a pile, start the table mode now.  
          * If we've already in a pile row, then don't override "pilet",  
          * because we'll be closed out anyway.  
          */  
         if (bp->pile != EQNPILE_NONE) {  
                 tmp = print_otag(p, TAG_MTABLE, 0, NULL);  
                 pilet = (NULL == pilet) ? tmp : pilet;  
         }  
   
         /*  
          * Positioning.  
          * This is the most complicated part, and actually doesn't quite  
          * work (FIXME) because it doesn't account for associativity.  
          * Setting "post" will mean that we're only going to process a  
          * single or double following expression.  
          */  
         switch (bp->pos) {          switch (bp->pos) {
         case (EQNPOS_TO):          case (EQNPOS_TO):
                 post = print_otag(p, TAG_MOVER, 0, NULL);                  post = print_otag(p, TAG_MOVER, 0, NULL);
Line 129  eqn_box(struct html *p, const struct eqn_box *bp, int 
Line 103  eqn_box(struct html *p, const struct eqn_box *bp, int 
                 break;                  break;
         case (EQNPOS_FROMTO):          case (EQNPOS_FROMTO):
                 post = print_otag(p, TAG_MUNDEROVER, 0, NULL);                  post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
                 skiptwo = 1;  
                 break;                  break;
         case (EQNPOS_SUBSUP):          case (EQNPOS_SUBSUP):
                 post = print_otag(p, TAG_MSUBSUP, 0, NULL);                  post = print_otag(p, TAG_MSUBSUP, 0, NULL);
                 skiptwo = 1;  
                 break;                  break;
           case (EQNPOS_SQRT):
                   post = print_otag(p, TAG_MSQRT, 0, NULL);
                   break;
         default:          default:
                 break;                  break;
         }          }
   
         /*t = EQNFONT_NONE == bp->font ? NULL :          if (bp->top || bp->bottom) {
             print_otag(p, fontmap[(int)bp->font], 0, NULL);*/                  assert(NULL == post);
                   if (bp->top && NULL == bp->bottom)
                           post = print_otag(p, TAG_MOVER, 0, NULL);
                   else if (bp->top && bp->bottom)
                           post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
                   else if (bp->bottom)
                           post = print_otag(p, TAG_MUNDER, 0, NULL);
           }
   
           if (EQN_PILE == bp->type) {
                   assert(NULL == post);
                   post = print_otag(p, TAG_MTABLE, 0, NULL);
           } else if (bp->parent && EQN_PILE == bp->parent->type) {
                   assert(NULL == post);
                   post = print_otag(p, TAG_MTR, 0, NULL);
                   print_otag(p, TAG_MTD, 0, NULL);
           }
   
         if (NULL != bp->text) {          if (NULL != bp->text) {
                 assert(NULL == bp->first);                  assert(NULL == post);
                 /*                  post = print_otag(p, TAG_MI, 0, NULL);
                  * We have text.                  print_text(p, bp->text);
                  * This can be a number, a function, a variable, or          } else if (NULL == post) {
                  * pretty much anything else.  
                  * First, check for some known functions.  
                  * If we're going to create a structural node (e.g.,  
                  * sqrt), then set the "post" variable only if it's not  
                  * already set.  
                  */  
                 if (0 == strcmp(bp->text, "sqrt")) {  
                         tmp = print_otag(p, TAG_MSQRT, 0, NULL);  
                         post = (NULL == post) ? tmp : post;  
                 } else if (0 == strcmp(bp->text, "+") ||  
                            0 == strcmp(bp->text, "-") ||  
                            0 == strcmp(bp->text, "=") ||  
                            0 == strcmp(bp->text, "(") ||  
                            0 == strcmp(bp->text, ")") ||  
                            0 == strcmp(bp->text, "/")) {  
                         tmp = print_otag(p, TAG_MO, 0, NULL);  
                         print_text(p, bp->text);  
                         print_tagq(p, tmp);  
                 } else {  
                         tmp = print_otag(p, TAG_MI, 0, NULL);  
                         print_text(p, bp->text);  
                         print_tagq(p, tmp);  
                 }  
         } else if (NULL != bp->first) {  
                 assert(NULL == bp->text);  
                 /*  
                  * If we're a "fenced" component (i.e., having  
                  * brackets), then process those brackets now.  
                  * Otherwise, introduce a dummy row (if we're not  
                  * already in a table context).  
                  */  
                 tmp = NULL;  
                 if (NULL != bp->left || NULL != bp->right) {                  if (NULL != bp->left || NULL != bp->right) {
                         PAIR_INIT(&tag[0], ATTR_OPEN,                          PAIR_INIT(&tag[0], ATTR_OPEN,
                                 NULL != bp->left ? bp->left : "");                                  NULL == bp->left ? "" : bp->left);
                         PAIR_INIT(&tag[1], ATTR_CLOSE,                          PAIR_INIT(&tag[1], ATTR_CLOSE,
                                 NULL != bp->right ? bp->right : "");                                  NULL == bp->right ? "" : bp->right);
                         tmp = print_otag(p, TAG_MFENCED, 2, tag);                          post = print_otag(p, TAG_MFENCED, 2, tag);
                   }
                   if (NULL == post)
                           post = print_otag(p, TAG_MROW, 0, NULL);
                   else
                         print_otag(p, TAG_MROW, 0, NULL);                          print_otag(p, TAG_MROW, 0, NULL);
                 } else if (NULL == pilet)  
                         tmp = print_otag(p, TAG_MROW, 0, NULL);  
                 eqn_box(p, bp->first, 1);  
                 if (NULL != tmp)  
                         print_tagq(p, tmp);  
         }          }
   
         /*          eqn_box(p, bp->first);
          * If a positional context, invoke the "next" context.  
          * This is recursive and will return the end of the recursive  out:
          * chain of "next" contexts.          if (NULL != bp->bottom) {
          */                  t = print_otag(p, TAG_MO, 0, NULL);
         if (NULL != post) {                  print_text(p, bp->bottom);
                 bp = eqn_box(p, bp->next, 0);                  print_tagq(p, t);
                 if (skiptwo)          }
                         bp = eqn_box(p, bp->next, 0);          if (NULL != bp->top) {
                 print_tagq(p, post);                  t = print_otag(p, TAG_MO, 0, NULL);
                   print_text(p, bp->top);
                   print_tagq(p, t);
         }          }
   
         /*          if (NULL != post)
          * If we're being piled (either directly, in the table, or                  print_tagq(p, post);
          * indirectly in a table row), then close that out.  
          */  
         if (NULL != pilet)  
                 print_tagq(p, pilet);  
   
         /*          eqn_box(p, bp->next);
          * If we're normally processing, then grab the next node.  }
          * If we're in a recursive context, then don't seek to the next  
          * node; further recursion has already been handled.  void
          */  print_eqn(struct html *p, const struct eqn *ep)
         return(next ? eqn_box(p, bp->next, 1) : bp);  {
           struct htmlpair  tag;
           struct tag      *t;
   
           PAIR_CLASS_INIT(&tag, "eqn");
           t = print_otag(p, TAG_MATH, 1, &tag);
   
           p->flags |= HTML_NONOSPACE;
           eqn_box(p, ep->root);
           p->flags &= ~HTML_NONOSPACE;
   
           print_tagq(p, t);
 }  }

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8

CVSweb