Back to index

texmacs  1.0.7.15
cell.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : cell.cpp
00004 * DESCRIPTION: Cells of tables
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "Format/format.hpp"
00013 #include "Table/table.hpp"
00014 #include "Boxes/construct.hpp"
00015 
00016 /******************************************************************************
00017 * Cells
00018 ******************************************************************************/
00019 
00020 cell_rep::cell_rep (edit_env env2): var (""), env (env2) {}
00021 
00022 void
00023 cell_rep::typeset (tree fm, tree t, path iq) {
00024   ip= iq;
00025   format_cell (fm);
00026   if (is_func (t, CELL, 1)) {
00027     iq= descend (iq, 0);
00028     t = t[0];
00029   }
00030 
00031   if (is_func (t, SUBTABLE, 1)) {
00032     lsep= rsep= bsep= tsep= 0;
00033     T= table (env, 2);
00034     T->typeset (t[0], descend (iq, 0));
00035   }
00036   else {
00037     if (hyphen == "n") {
00038       b= typeset_as_concat (env, t, iq);
00039       if (vcorrect != "n") {
00040        SI y1= b->y1;
00041        SI y2= b->y2;
00042        if ((vcorrect == "a") || (vcorrect == "b")) y1= min (y1, env->fn->y1);
00043        if ((vcorrect == "a") || (vcorrect == "t")) y2= max (y2, env->fn->y2);
00044        b= resize_box (iq, b, b->x1, y1, b->x2, y2);
00045       }
00046     }
00047     else {
00048       b= empty_box (iq);
00049 
00050       tree len = env->as_tmlen ("1par");
00051       tree old1= env->local_begin (PAGE_MEDIUM, "papyrus");
00052       tree old2= env->local_begin (PAR_LEFT, "0tmpt");
00053       tree old3= env->local_begin (PAR_RIGHT, "0tmpt");
00054       tree old4= env->local_begin (PAR_MODE, "justify");
00055       tree old5= env->local_begin (PAR_NO_FIRST, "true");
00056       tree old6= env->local_begin (PAR_WIDTH, len);
00057 
00058       lz= make_lazy (env, t, iq);
00059       
00060       env->local_end (PAR_WIDTH, old6);
00061       env->local_end (PAR_NO_FIRST, old5);
00062       env->local_end (PAR_MODE, old4);
00063       env->local_end (PAR_RIGHT, old3);
00064       env->local_end (PAR_LEFT, old2);
00065       env->local_end (PAGE_MEDIUM, old1);
00066     }
00067   }
00068 
00069   if (decoration != "") {
00070     int i, j, or_row= -1, or_col= -1;
00071     tree dt= decoration;
00072     while (is_func (dt, TFORMAT)) dt= dt [N(dt)-1];
00073     for (i=0; i<N(dt); i++) {
00074       tree dr= dt[i];
00075       while (is_func (dr, TFORMAT)) dr= dr [N(dr)-1];
00076       for (j=0; j<N(dr); j++) {
00077        tree dc= dr[j];
00078        while (is_func (dc, TFORMAT)) dc= dc [N(dc)-1];
00079        if (dc == tree (TMARKER)) {
00080          or_row= i;
00081          or_col= j;
00082        }
00083       }
00084     }
00085 
00086     if (or_row != -1) {
00087       D= table (env, 1, or_row, or_col);
00088       D->typeset (attach_deco (decoration, iq));
00089     }
00090   }
00091 }
00092 
00093 /******************************************************************************
00094 * Formatting routines
00095 ******************************************************************************/
00096 
00097 void
00098 extract_format (tree fm, tree* r, int n) {
00099   int i;
00100   for (i=0; i<n; i++) r[i]= tree (TFORMAT);
00101   if (!is_func (fm, TFORMAT)) return;
00102   for (i=0; i<N(fm); i++)
00103     if (is_func (fm[i], CWITH))
00104       if ((N(fm[i]) >= 2) &&
00105          (is_int (fm[i][0])) &&
00106          (is_int (fm[i][1])))
00107        {
00108          int k;
00109          int k1= as_int (fm[i][0]);
00110          int k2= as_int (fm[i][1]);
00111          tree u= fm[i] (2, N (fm[i]));
00112          if (k1>=0) k1--; else k1+=n;
00113          if (k2> 0) k2--; else k2+=n;
00114          if ((k1 >= n) || (k2 < 0)) continue;
00115          k1= max (k1, 0);
00116          k2= min (k2, n-1);
00117          for (k=k1; k<=k2; k++) r[k] << u;
00118        }
00119 }
00120 
00121 void
00122 cell_rep::format_cell (tree fm) {
00123   int i, l= N(fm);
00124   for (i=0; i<l; i++)
00125     format_item (fm[i]);
00126 
00127   if (var->contains (CELL_DECORATION))
00128     decoration= env->exec (var[CELL_DECORATION]);
00129   else decoration= "";
00130   if (var->contains (CELL_BACKGROUND)) {
00131     bg= env->exec (var[CELL_BACKGROUND]);
00132     if (bg == "foreground") bg= env->get_string (COLOR);
00133   }
00134   else bg= "";
00135   if (var->contains (CELL_WIDTH)) {
00136     width= env->as_length (env->exec (var[CELL_WIDTH]));
00137     if (var->contains (CELL_HMODE))
00138       hmode= as_string (env->exec (var[CELL_HMODE]));
00139     else hmode= "exact";
00140   }
00141   else {
00142     width= 0;
00143     hmode= "auto";
00144   }
00145   if (var->contains (CELL_HEIGHT)) {
00146     height= env->as_length (env->exec (var[CELL_HEIGHT]));
00147     if (var->contains (CELL_VMODE))
00148       vmode= as_string (env->exec (var[CELL_VMODE]));
00149     else vmode= "exact";
00150   }
00151   else {
00152     height= 0;
00153     vmode = "auto";
00154   }
00155   if (var->contains (CELL_HPART))
00156     hpart= as_double (env->exec (var[CELL_HPART]));
00157   else hpart= 0.0;
00158   if (var->contains (CELL_VPART))
00159     vpart= as_double (env->exec (var[CELL_VPART]));
00160   else vpart= 0.0;
00161   if (var->contains (CELL_LSEP))
00162     lsep= env->as_length (env->exec (var[CELL_LSEP]));
00163   else lsep= env->fn->spc->def;
00164   if (var->contains (CELL_RSEP))
00165     rsep= env->as_length (env->exec (var[CELL_RSEP]));
00166   else rsep= env->fn->spc->def;
00167   if (var->contains (CELL_BSEP))
00168     bsep= env->as_length (env->exec (var[CELL_BSEP]));
00169   else bsep= env->fn->sep;
00170   if (var->contains (CELL_TSEP))
00171     tsep= env->as_length (env->exec (var[CELL_TSEP]));
00172   else tsep= env->fn->sep;
00173   if (var->contains (CELL_LBORDER))
00174     lborder= env->as_length (env->exec (var[CELL_LBORDER])) >> 1;
00175   else lborder= 0;
00176   if (var->contains (CELL_RBORDER))
00177     rborder= env->as_length (env->exec (var[CELL_RBORDER])) >> 1;
00178   else rborder= 0;
00179   if (var->contains (CELL_BBORDER))
00180     bborder= env->as_length (env->exec (var[CELL_BBORDER])) >> 1;
00181   else bborder= 0;
00182   if (var->contains (CELL_TBORDER))
00183     tborder= env->as_length (env->exec (var[CELL_TBORDER])) >> 1;
00184   else tborder= 0;
00185   if (var->contains (CELL_HALIGN))
00186     halign= as_string (env->exec (var[CELL_HALIGN]));
00187   else halign= "l";
00188   if (var->contains (CELL_VALIGN))
00189     valign= as_string (env->exec (var[CELL_VALIGN]));
00190   else valign= "B";
00191   if (var->contains (CELL_VCORRECT))
00192     vcorrect= as_string (env->exec (var[CELL_VCORRECT]));
00193   else vcorrect= "a";
00194   if (var->contains (CELL_HYPHEN))
00195     hyphen= as_string (env->exec (var[CELL_HYPHEN]));
00196   else hyphen= "n";
00197   if (var->contains (CELL_ROW_SPAN))
00198     row_span= as_int (env->exec (var[CELL_ROW_SPAN]));
00199   else row_span= 1;
00200   if (var->contains (CELL_COL_SPAN))
00201     col_span= as_int (env->exec (var[CELL_COL_SPAN]));
00202   else col_span= 1;
00203 }
00204 
00205 void
00206 cell_rep::format_item (tree with) {
00207   if (is_func (with, CWITH, 2))
00208     var (as_string (with[0]))= with[1];
00209 }
00210 
00211 /******************************************************************************
00212 * Positioning routines
00213 ******************************************************************************/
00214 
00215 void
00216 cell_rep::compute_width (SI& mw, SI& lw, SI& rw, bool large) {
00217   //cout << "  large= " << large << "\n";
00218   char align_c= '\0'; if (N (halign) != 0) align_c= halign[0];
00219   bool lr_flag= (align_c >= 'A' && align_c <= 'Z');
00220   if (!is_nil (T)) {
00221     if (N (T->halign) > 0) align_c= T->halign[0];
00222     else align_c= '\0';
00223     lr_flag= (align_c >= 'A' && align_c <= 'Z');
00224     T->compute_width (mw, lw, rw);
00225     if (lr_flag) {
00226       lw += lborder;
00227       rw += rborder;
00228     }
00229     else lw= rw= 0;
00230     mw += lborder + rborder;
00231   }
00232   else if (!is_nil (lz) && large) {
00233     lw= rw= 0;
00234     format fm= lz->query (LAZY_BOX, make_query_vstream_width (0, 0));
00235     format_width fw= (format_width) fm;
00236     mw= fw->width + lsep + rsep + lborder + rborder;
00237     if (lr_flag) {
00238       lw= lsep + lborder;
00239       rw= fw->width + rsep + rborder;
00240     }
00241   }
00242   else {
00243     //cout << "  b= " << b << "\n";
00244     lw= rw= mw= 0;
00245     if (lr_flag) {
00246       if (N (halign) == 1) {
00247        lw= -b->x1+ lsep + lborder;
00248        rw=  b->x2+ rsep + rborder;
00249        mw=  lw + rw;
00250       }
00251       else {
00252        SI offset= b->get_leaf_offset (halign (1, N (halign)));
00253        lw= offset+ lsep+ lborder;
00254        rw= b->w()- offset+ rsep+ rborder;
00255        mw= lw + rw;
00256       }
00257     }
00258     else mw= b->w() + lsep + rsep + lborder + rborder;
00259   }
00260 
00261   if (hmode == "exact") mw= width;
00262   else if (hmode == "max") mw= max (width, mw);
00263   else if (hmode == "min") mw= min (width, mw);
00264   if (mw < lw + rw) {
00265     SI d= lw + rw - mw;
00266     if (align_c == 'L' || align_c == 'O') rw -= d;
00267     else if (align_c == 'C') { lw -= (d >> 1); rw -= ((d+1) >> 1); }
00268     else lw -= d;
00269   }
00270 }
00271 
00272 void
00273 cell_rep::compute_height (SI& mh, SI& bh, SI& th) {
00274   char align_c= '\0'; if (N (valign) != 0) align_c= valign[0];
00275   if (is_nil (T)) {
00276     bh= th= mh= 0;
00277     if (align_c >= 'A' && align_c <= 'Z') {
00278       bh= -b->y1+ bsep + bborder;
00279       th=  b->y2+ tsep + tborder;
00280       mh=  bh + th;
00281     }
00282     else mh= b->h() + bsep + tsep + bborder + tborder;
00283   }
00284   else {
00285     if (N (T->valign) != 0) align_c= T->valign[0];
00286     T->compute_height (mh, bh, th);
00287     if (align_c >= 'A' && align_c <= 'Z') {
00288       bh += bborder;
00289       th += tborder;
00290     }
00291     else bh= th= 0;
00292     mh += bborder + tborder;
00293   }
00294 
00295   if (vmode == "exact") mh= height;
00296   else if (vmode == "max") mh= max (height, mh);
00297   else if (vmode == "min") mh= min (height, mh);
00298   if (mh < bh + th) {
00299     SI d= bh + th - mh;
00300     if (align_c == 'B' || align_c == 'O') th -= d;
00301     else if (align_c == 'C') { bh -= (d >> 1); th -= ((d+1) >> 1); }
00302     else bh -= d;
00303   }
00304 }
00305 
00306 void
00307 cell_rep::position_horizontally (SI offset, SI mw, SI lw, SI rw) {
00308   x1= offset;
00309   x2= offset + mw;
00310   if (is_nil (T)) {
00311     char align_c= '\0'; if (N (halign) != 0) align_c= halign[0];
00312     if (align_c == 'l') xoff= -b->x1 + (lsep + lborder);
00313     else if (align_c == 'c') xoff= (mw - b->x1 - b->x2) >> 1;
00314     else if (align_c == 'r') xoff= mw - b->x2 - (rsep + rborder);
00315     else if (align_c == 'L') xoff= lw;
00316     else if (align_c == 'C') xoff= (mw + lw - rw) >> 1;
00317     else if (align_c == 'R') xoff= mw - rw;
00318     else xoff= lw;
00319     if (N(halign) > 1) xoff -= b->get_leaf_offset (halign (1, N (halign)));
00320   }
00321   else xoff= -T->x1 + lborder;
00322 }
00323 
00324 void
00325 cell_rep::position_vertically (SI offset, SI mh, SI bh, SI th) {
00326   y1= offset - mh;
00327   y2= offset;
00328   if (is_nil (T)) {
00329     char align_c= '\0'; if (N (valign) != 0) align_c= valign[0];
00330     if (align_c == 'b') yoff= -b->y1 + (bsep + bborder);
00331     else if (align_c == 'c') yoff= (mh - b->y1 - b->y2) >> 1;
00332     else if (align_c == 't') yoff= mh - b->y2 - (tsep + tborder);
00333     else if (align_c == 'B') yoff= bh;
00334     else if (align_c == 'C') yoff= (mh + bh - th) >> 1;
00335     else if (align_c == 'T') yoff= mh - th;
00336     else yoff= bh;
00337   }
00338   else yoff= -T->y1 + bborder;
00339 }
00340 
00341 /******************************************************************************
00342 * Producing the final cell box
00343 ******************************************************************************/
00344 
00345 void
00346 cell_rep::finish_horizontal () {
00347   SI  w= width- lsep- lborder- rsep- rborder;
00348   int v= hyphen == "t"? 1: (hyphen == "c"? 0: -1);
00349   SI  d= ((vcorrect == "b") || (vcorrect == "a"))? -env->fn->y1: 0;
00350   SI  h= ((vcorrect == "t") || (vcorrect == "a"))?  env->fn->y2: 0;
00351   b= (box) lz->produce (LAZY_BOX, make_format_cell (w, v, d, h));
00352 }
00353 
00354 void
00355 cell_rep::finish () {
00356   if (!is_nil (T)) {
00357     T->finish ();
00358     b= T->b;
00359   }
00360 
00361   color fc= env->col;
00362 
00363   b= cell_box (ip, b, xoff, yoff, 0, 0, x2-x1, y2-y1,
00364               lborder, rborder, bborder, tborder,
00365                fc, bg, env->alpha);
00366 }