Back to index

texmacs  1.0.7.15
text_boxes.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : text.cpp
00004 * DESCRIPTION: text boxes
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 "boxes.hpp"
00013 #include "font.hpp"
00014 #include "Boxes/construct.hpp"
00015 #include "analyze.hpp"
00016 
00017 /******************************************************************************
00018 * Text boxes
00019 ******************************************************************************/
00020 
00021 struct text_box_rep: public box_rep {
00022   int       pos;
00023   string    str;
00024   font      fn;
00025   color     col;
00026 
00027   text_box_rep (path ip, int pos, string s, font fn, color col);
00028   operator tree () { return str; }
00029 
00030   void      display (renderer ren);
00031   double    left_slope ();
00032   double    right_slope ();
00033   SI        left_correction ();
00034   SI        right_correction ();
00035   SI        lsub_correction ();
00036   SI        lsup_correction ();
00037   SI        rsub_correction ();
00038   SI        rsup_correction ();
00039   SI        sub_lo_base (int level);
00040   SI        sub_hi_lim  (int level);
00041   SI        sup_lo_lim  (int level);
00042   SI        sup_lo_base (int level);
00043   SI        sup_hi_lim  (int level);
00044 
00045   path      find_box_path (SI x, SI y, SI delta, bool force);
00046   path      find_lip ();
00047   path      find_rip ();
00048   path      find_right_box_path ();
00049   path      find_box_path (path p, bool& found);
00050   path      find_tree_path (path bp);
00051   cursor    find_cursor (path bp);
00052   selection find_selection (path lbp, path rbp);
00053 
00054   int       get_leaf_left_pos ();
00055   int       get_leaf_right_pos ();
00056   string    get_leaf_string ();
00057   font      get_leaf_font ();
00058   color     get_leaf_color ();
00059   SI        get_leaf_offset (string search);
00060 };
00061 
00062 /******************************************************************************
00063 * Routines for text boxes
00064 ******************************************************************************/
00065 
00066 text_box_rep::text_box_rep (path ip, int pos2, string s, font fn2, color col2):
00067   box_rep (ip), pos (pos2), str (s), fn (fn2), col (col2)
00068 {
00069   metric ex;
00070   fn->get_extents (str, ex);
00071   x1= ex->x1; y1= ex->y1;
00072   x2= ex->x2; y2= ex->y2;
00073   x3= ex->x3; y3= ex->y3;
00074   x4= ex->x4; y4= ex->y4;
00075 }
00076 
00077 void
00078 text_box_rep::display (renderer ren) {
00079   ren->set_color (col);
00080   fn->draw (ren, str, 0, 0);
00081 }
00082 
00083 double text_box_rep::left_slope () {
00084   return fn->get_left_slope (str); }
00085 double text_box_rep::right_slope () {
00086   return fn->get_right_slope (str); }
00087 SI text_box_rep::left_correction () {
00088   return fn->get_left_correction (str); }
00089 SI text_box_rep::right_correction () {
00090   return fn->get_right_correction (str); }
00091 SI text_box_rep::lsub_correction () {
00092   return -left_correction (); }
00093 SI text_box_rep::lsup_correction () {
00094   return right_correction (); }
00095 SI text_box_rep::rsub_correction () {
00096   return 0; }
00097 SI text_box_rep::rsup_correction () {
00098   return right_correction (); }
00099 
00100 SI
00101 text_box_rep::sub_lo_base (int level) {
00102   if (level <= 0) return fn->ysub_lo_base;
00103   else return fn->ysub_lo_base + fn->yshift;
00104 }
00105 
00106 SI
00107 text_box_rep::sub_hi_lim  (int level) {
00108   (void) level;
00109   return fn->ysub_hi_lim;
00110 }
00111 
00112 SI
00113 text_box_rep::sup_lo_lim  (int level) {
00114   (void) level;
00115   return fn->ysup_lo_lim;
00116 }
00117 
00118 SI
00119 text_box_rep::sup_lo_base (int level) {
00120   if (level >= 0) return fn->ysup_lo_base;
00121   else return fn->ysup_lo_base - fn->yshift;
00122 }
00123 
00124 SI
00125 text_box_rep::sup_hi_lim  (int level) {
00126   (void) level;
00127   return fn->ysup_hi_lim;
00128 }
00129 
00130 /******************************************************************************
00131 * New routines concerning the cursor
00132 ******************************************************************************/
00133 
00134 path
00135 text_box_rep::find_box_path (SI x, SI y, SI delta, bool force) {
00136   (void) y;
00137   (void) force;
00138   STACK_NEW_ARRAY (xpos, SI, N(str)+1);
00139   fn->get_xpositions (str, xpos);
00140 
00141   int prev_i, prev_x=0, i=0;
00142   while (i<N(str)) {
00143     prev_i= i;
00144     if (str[i]=='<')
00145       while ((i<N(str)) && (str[i]!='>')) i++;
00146     i++;
00147 
00148     int m= (prev_x + xpos[i]) >> 1;
00149     if ((x<m) || ((x==m) && (delta<0))) {
00150       STACK_DELETE_ARRAY (xpos);
00151       return path (prev_i);
00152     }
00153     prev_x= xpos[i];
00154   }
00155   STACK_DELETE_ARRAY (xpos);
00156   return path (i);
00157 }
00158 
00159 path
00160 text_box_rep::find_lip () {
00161   if (is_accessible (ip)) return descend (ip, pos);
00162   return ip;
00163 }
00164 
00165 path
00166 text_box_rep::find_rip () {
00167   if (is_accessible (ip)) return descend (ip, pos+ N(str));
00168   else return ip;
00169 }
00170 
00171 path
00172 text_box_rep::find_right_box_path () {
00173   return path (N(str));
00174   /*
00175   if (is_accessible (ip)) return path (N(str));
00176   else return path (1);
00177   */
00178 }
00179 
00180 path
00181 text_box_rep::find_box_path (path p, bool& found) {
00182   // cout << "Find box path " << box (this) << ", " << p
00183   //      << "; " << reverse (ip)
00184   //      << ", " << reverse (find_lip ())
00185   //      << " -- " << reverse (find_rip ()) << "\n";
00186   found= (!is_nil(p)) && is_accessible (ip);
00187   if (found) {
00188     int i= last_item (p) - pos;
00189     if (i < 0) return path (0);
00190     else if (i > N(str)) return N(str);
00191     else return path (i);
00192   }
00193   else return path (0);
00194 }
00195 
00196 path
00197 text_box_rep::find_tree_path (path bp) {
00198   if (is_accessible (ip)) return reverse (descend (ip, pos+ bp->item));
00199   else return reverse (descend_decode (ip, bp->item <= N(str) ? 0 : 1));
00200 }
00201 
00202 cursor
00203 text_box_rep::find_cursor (path bp) {
00204   metric ex;
00205   cursor cu (0, 0);
00206   int l= min (bp->item, N(str));
00207   fn->get_extents (str (0, l), ex);
00208   cu->ox= ex->x2;
00209   if (l != 0) {
00210     int k= l;
00211     tm_char_backwards (str, k);
00212     fn->get_extents (str (k, l), ex);
00213   }
00214   cu->y1= min (ex->y1, 0);
00215   cu->y2= max (ex->y2, fn->yx);
00216   cu->slope= fn->get_right_slope (str);
00217   return cu;
00218 }
00219 
00220 selection
00221 text_box_rep::find_selection (path lbp, path rbp) {
00222   SI x1, y1, x2, y2;
00223   metric ex;
00224   fn->get_extents (str (0, lbp->item), ex);
00225   x1= ex->x2;
00226   fn->get_extents (str (0, rbp->item), ex);
00227   x2= ex->x2;
00228   fn->get_extents (str (lbp->item, rbp->item), ex);
00229   y1= ex->y1;
00230   y2= ex->y2;
00231   return selection (rectangle (x1, y1, x2, y2),
00232                   find_tree_path (lbp), find_tree_path (rbp));
00233 }
00234 
00235 /******************************************************************************
00236 * Getting information about box
00237 ******************************************************************************/
00238 
00239 int
00240 text_box_rep::get_leaf_left_pos () {
00241   return pos;
00242 }
00243 
00244 int
00245 text_box_rep::get_leaf_right_pos () {
00246   return pos+ N(str);
00247 }
00248 
00249 string
00250 text_box_rep::get_leaf_string () {
00251   return str;
00252 }
00253 
00254 font
00255 text_box_rep::get_leaf_font () {
00256   return fn;
00257 }
00258 
00259 color
00260 text_box_rep::get_leaf_color () {
00261   return col;
00262 }
00263 
00264 SI
00265 text_box_rep::get_leaf_offset (string search) {
00266   int pos= search_forwards (search, 0, str);
00267   if (pos == -1) return w();
00268   metric ex;
00269   fn->get_extents (str (0, pos), ex);
00270   return ex->x2- ex->x1;
00271 }
00272 
00273 /******************************************************************************
00274 * Computing right size for rubber characters
00275 ******************************************************************************/
00276 
00277 static string
00278 get_delimiter (string s, font fn, SI height) {
00279   ASSERT (N(s) >= 2 && s[0] == '<' && s[N(s)-1] == '>',
00280          "invalid rubber character");
00281   height -= PIXEL;
00282   string radical= s (0, N(s)-1) * "-";
00283   string first  = radical * "0>";
00284   metric ex;
00285   fn->get_extents (first, ex);
00286   if ((ex->y2- ex->y1) >= height) return first;
00287 
00288   string second  = radical * "1>";
00289   fn->get_extents (second, ex);
00290   SI h1= ex->y2- ex->y1;
00291   if (h1 >= (height-PIXEL)) return second;
00292 
00293   string third = radical * "2>";
00294   metric ey;
00295   fn->get_extents (third, ey);
00296   SI h2= ey->y2- ey->y1;
00297   if (h2 <= h1) return second;
00298   SI  d= h2- h1;
00299   int n= (height + (d-1) - h1) / d;
00300 
00301   while (true) {
00302     string test= radical * as_string (n+1) * ">";
00303     fn->get_extents (test, ey);
00304     if (ey->y2- ey->y1 >= height) return test;
00305     if ((ey->y2- ey->y1 <= h2) && (n>1)) return radical * as_string (n) * ">";
00306     h2= ey->y2- ey->y1;
00307     n++;
00308   }
00309 }
00310 
00311 static string
00312 get_wide (string s, font fn, SI width) {
00313   ASSERT (N(s) >= 2 && s[0] == '<' && s[N(s)-1] == '>',
00314          "invalid rubber character");
00315   string radical= s (0, N(s)-1) * "-";
00316   string first  = radical * "0>";
00317   metric ex;
00318   fn->get_extents (first, ex);
00319   if ((ex->x2- ex->x1) >= width) return first;
00320 
00321   string second = radical * "1>";
00322   metric ey;
00323   fn->get_extents (second, ey);
00324   SI w1= ex->x2- ex->x1;
00325   SI w2= ey->x2- ey->x1;
00326   if ((w2 <= w1) || (w2 > width)) return first;
00327   SI  d= w2- w1;
00328   int n= (width-w1) / (d+1);
00329 
00330   while (true) {
00331     string test= radical * as_string (n+1) * ">";
00332     fn->get_extents (test, ey);
00333     if (ey->x2- ey->x1 > width) return radical * as_string (n) * ">";
00334     n++;
00335   }
00336 }
00337 
00338 /******************************************************************************
00339 * Exported routines
00340 ******************************************************************************/
00341 
00342 box
00343 delimiter_box (path ip, string s, font fn, color col, SI bot, SI top) {
00344   SI h= top - bot;
00345   string r= get_delimiter (s, fn, h);
00346   metric ex;
00347   fn->get_extents (r, ex);
00348   SI x= -ex->x1;
00349   SI y= (top+ bot- ex->y1- ex->y2) >> 1;
00350   box mvb= move_box (ip, text_box (ip, 0, r, fn, col), x, y, false, true);
00351   return macro_box (ip, mvb, fn);
00352 }
00353 
00354 box
00355 big_operator_box (path ip, string s, font fn, color col, int n) {
00356   ASSERT (N(s) >= 2 && s[0] == '<' && s[N(s)-1] == '>',
00357          "invalid rubber character");
00358   string r= s (0, N(s)-1) * "-" * as_string (n) * ">";
00359   metric ex;
00360   fn->get_extents (r, ex);
00361   SI y= fn->yfrac - ((ex->y1 + ex->y2) >> 1);
00362   box mvb= move_box (ip, text_box (ip, 0, r, fn, col), 0, y, false, true);
00363   return macro_box (ip, mvb, fn);
00364 }
00365 
00366 box
00367 wide_box (path ip, string s, font fn, color col, SI width) {
00368   string r= get_wide (s, fn, width);
00369   metric ex;
00370   fn->get_extents (r, ex);
00371   box b= text_box (ip, 0, r, fn, col);
00372   return macro_box (ip, b, fn);
00373 }
00374 
00375 box
00376 text_box (path ip, int pos, string s, font fn, color col) {
00377   return tm_new<text_box_rep> (ip, pos, s, fn, col);
00378 }