Back to index

texmacs  1.0.7.15
composite_boxes.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : composite.cpp
00004 * DESCRIPTION: Boxes with a list of child 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/composite.hpp"
00013 #include "Boxes/construct.hpp"
00014 
00015 /******************************************************************************
00016 * Setting up composite boxes
00017 ******************************************************************************/
00018 
00019 composite_box_rep::composite_box_rep (path ip): box_rep (ip) { }
00020 
00021 composite_box_rep::composite_box_rep (path ip, array<box> B): box_rep (ip) {
00022   bs= B;
00023   position ();
00024 }
00025 
00026 composite_box_rep::composite_box_rep (
00027   path ip, array<box> B, bool init_sx_sy):
00028     box_rep (ip)
00029 {
00030   bs= B;
00031   if (init_sx_sy) {
00032     int i, n= N(bs);
00033     for (i=0; i<n; i++) {
00034       sx(i)= 0;
00035       sy(i)= 0;
00036     }
00037   }
00038   position ();
00039 }
00040 
00041 composite_box_rep::composite_box_rep (
00042   path ip, array<box> B, array<SI> x, array<SI> y):
00043     box_rep (ip)
00044 {
00045   bs= B;
00046   int i, n= subnr();
00047   for (i=0; i<n; i++) {
00048     sx(i)= x[i];
00049     sy(i)= y[i];
00050   }
00051   position ();
00052 }
00053 
00054 composite_box_rep::~composite_box_rep () {}
00055 
00056 void
00057 composite_box_rep::insert (box b, SI x, SI y) {
00058   int n= N(bs);
00059   bs << b;
00060   sx(n)= x;
00061   sy(n)= y;
00062 }
00063 
00064 void
00065 composite_box_rep::position () {
00066   int i, n= subnr();
00067   if (n == 0) {
00068     x1= y1= x3= y3= 0;
00069     x2= y2= x4= y4= 0;
00070     FAILED ("empty composite box");
00071   }
00072   else {
00073     x1= y1= x3= y3= MAX_SI;
00074     x2= y2= x4= y4= -MAX_SI;
00075     for (i=0; i<n; i++) {
00076       x1= min (x1, sx1(i));
00077       y1= min (y1, sy1(i));
00078       x2= max (x2, sx2(i));
00079       y2= max (y2, sy2(i));
00080       x3= min (x3, sx3(i));
00081       y3= min (y3, sy3(i));
00082       x4= max (x4, sx4(i));
00083       y4= max (y4, sy4(i));
00084     }
00085   }
00086 }
00087 
00088 void
00089 composite_box_rep::left_justify () {
00090   int i, n= subnr();
00091   SI d= x1;
00092   x1-=d; x2-=d; x3-=d; x4-=d;
00093   for (i=0; i<n; i++) sx(i) -= d;
00094 }
00095 
00096 /******************************************************************************
00097 * Routines for composite boxes
00098 ******************************************************************************/
00099 
00100 void
00101 composite_box_rep::display (renderer ren) {
00102   (void) ren;
00103 }
00104 
00105 int
00106 composite_box_rep::subnr () {
00107   return N(bs);
00108 }
00109 
00110 box
00111 composite_box_rep::subbox (int i) {
00112   return bs[i];
00113 }
00114 
00115 tree
00116 composite_box_rep::action (tree t, SI x, SI y, SI delta) {
00117   int m= find_child (x, y, delta, true);
00118   if (m == -1) return "";
00119   else return bs[m]->action (t, x- sx(m), y- sy(m),
00120                           delta + get_delta (x, x1, x2));
00121 }
00122 
00123 void
00124 composite_box_rep::loci (SI x, SI y, SI delta,
00125                       list<string>& ids, rectangles& rs)
00126 {
00127   int m= find_child (x, y, delta, true);
00128   if (m == -1) box_rep::loci (x, y, delta, ids, rs);
00129   else {
00130     bs[m]->loci (x- sx(m), y- sy(m), delta + get_delta (x, x1, x2), ids, rs);
00131     rs= translate (rs, sx(m), sy(m));
00132   }
00133 }
00134 
00135 void
00136 composite_box_rep::collect_page_numbers (hashmap<string,tree>& h, tree page) {
00137   int i, n= N(bs);
00138   for (i=0; i<n; i++)
00139     bs[i]->collect_page_numbers (h, page);
00140 }
00141 
00142 path
00143 composite_box_rep::find_tag (string name) {
00144   int i, n= N(bs);
00145   for (i=0; i<n; i++) {
00146     path p= bs[i]->find_tag (name);
00147     if (!is_nil (p)) return p;
00148   }
00149   return path ();
00150 }
00151 
00152 bool
00153 composite_box_rep::access_allowed () {
00154   return true;
00155 }
00156 
00157 box
00158 composite_box_rep::transform (frame fr) {
00159   int i;
00160   array<box> bs;
00161   for (i= 0; i<subnr(); i++) {
00162     if (!is_nil (subbox (i))) {
00163       box sb= subbox (i)->transform (fr);
00164       if (!is_nil (sb)) bs << sb;
00165     }
00166   }
00167   return N (bs)==0?box ():composite_box (ip, bs);
00168 }
00169 
00170 /******************************************************************************
00171 * Cursor routines
00172 ******************************************************************************/
00173 
00174 void
00175 composite_box_rep::finalize () {
00176   int i, n= subnr ();
00177   lip= descend (ip, 0);
00178   rip= descend (ip, 1);
00179   for (i=0; i<n; i++) {
00180     path l= bs[i]->find_lip ();
00181     path r= bs[i]->find_rip ();
00182     /*
00183     cout << "  i  = " << i << "\n";
00184     cout << "  l  = " << l << "\n";
00185     cout << "  r  = " << r << "\n";
00186     */
00187     if (is_accessible (l) && is_accessible (r)) {
00188       if (is_decoration (lip) || path_less (reverse (l), reverse (lip)))
00189        lip= l;
00190       if (is_decoration (rip) || path_less (reverse (rip), reverse (r)))
00191        rip= r;
00192     }
00193   }
00194   /*
00195   cout << ((tree) (*((box_rep*) this))) << " " << ip << "\n";
00196   cout << "  lip= " << lip << "\n";
00197   cout << "  rip= " << rip << "\n";
00198   */
00199 }
00200 
00201 int
00202 composite_box_rep::find_child (SI x, SI y, SI delta, bool force) {
00203   if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
00204   int i, n= subnr(), d= MAX_SI, m= -1;
00205   for (i=0; i<n; i++)
00206     if (distance (i, x, y, delta)< d)
00207       if (bs[i]->accessible () || force) {
00208        d= distance (i, x, y, delta);
00209        m= i;
00210       }
00211   return m;
00212 }
00213 
00214 path
00215 composite_box_rep::find_box_path (SI x, SI y, SI delta, bool force) {
00216   int m= find_child (x, y, delta, force);
00217   if (m==-1) return box_rep::find_box_path (x, y, delta, force);
00218   else {
00219     SI xx= x- sx(m), yy= y- sy(m);
00220     SI dd= delta + get_delta (xx, bs[m]->x1, bs[m]->x2);
00221     return path (m, bs[m]->find_box_path (xx, yy, dd, force));
00222   }
00223 }
00224 
00225 path
00226 composite_box_rep::find_lip () {
00227   return lip;
00228 }
00229 
00230 path
00231 composite_box_rep::find_rip () {
00232   return rip;
00233 }
00234 
00235 path
00236 composite_box_rep::find_box_path (path p, bool& found) {
00237   // cout << "Find box path " << box (this) << ", " << p
00238   //      << "; " << reverse (ip)
00239   //      << ", " << reverse (find_lip ())
00240   //      << " -- " << reverse (find_rip ()) << "\n";
00241   int n= subnr();
00242   // cout << "Search cursor " << p << " among " << n
00243   //      << " at " << box (this) << " " << reverse (ip) << "\n";
00244   if (n == 0) return box_rep::find_box_path (p, found);
00245 
00246   int start= n>>1, acc= start, step= (start+1)>>1;
00247   while (step > 0) {
00248     path sr= bs[acc]->find_rip ();
00249     while (!is_accessible (sr)) {
00250       acc--;
00251       if (acc<0) break;
00252       sr= bs[acc]->find_rip ();
00253     }
00254     if (acc<0) {
00255       start= 0;
00256       break;
00257     }
00258     if (path_less (reverse (sr), p)) {
00259       int old_start= start, old_acc= acc;
00260       start= min (n-1, start+ step);
00261       acc  = start;
00262       while ((acc > old_start) &&
00263             (!is_accessible (bs[acc]->find_rip ()))) acc--;
00264       if (acc == old_start) acc= old_acc;
00265     }
00266     else {
00267       start= max (0, start- step);
00268       acc  = min (acc, start);
00269     }
00270     if (step <= 1) break;
00271     step= (step+1)>>1;
00272   }
00273 
00274   path bp;
00275   bool flag= false;
00276   int i= start;
00277   found= false;
00278   while (true) {
00279     path sl= bs[i]->find_lip ();
00280     path sr= bs[i]->find_rip ();
00281     // cout << "  " << i << ":\t" << reverse(sl) <<", "<< reverse(sr) << "\n";
00282     if (is_accessible (sl) && is_accessible (sr) &&
00283        path_less_eq (reverse (sl), p) && path_less_eq (p, reverse (sr)))
00284       {
00285        flag= true;
00286        bp= path (i, bs[i]->find_box_path (p, found));
00287        if (found) return bp;
00288       }
00289     i++;
00290     if (i==n) i=0;
00291     if (i==start) break;
00292   }
00293 
00294   if (is_accessible (ip) && (path_up (p) == reverse (ip)) && access_allowed ())
00295     return box_rep::find_box_path (p, found);
00296   if (flag) return bp;
00297   if (start > 0) {
00298     path sl= bs[start-1]->find_rip ();
00299     path sr= bs[start  ]->find_lip ();
00300     if (is_accessible (sl) && is_accessible (sr) &&
00301        path_less_eq (reverse (sl), p) && path_less_eq (p, reverse (sr)))
00302       {
00303        int c1= N (common (reverse (sl), p));
00304        int c2= N (common (reverse (sr), p));
00305        int i = (c1 >= c2? start-1: start);
00306        return path (i, bs[i]->find_box_path (p, found));
00307       }
00308   }
00309   return box_rep::find_box_path (p, flag);
00310 }
00311 
00312 path
00313 composite_box_rep::find_tree_path (path bp) {
00314   if (is_atom (bp)) return box_rep::find_tree_path (bp);
00315   return bs[bp->item]->find_tree_path (bp->next);
00316 }
00317 
00318 cursor
00319 composite_box_rep::find_cursor (path bp) {
00320   if (is_atom (bp)) return box_rep::find_cursor (bp);
00321   else {
00322     int i= bp->item;
00323     cursor cu= bs[i]->find_cursor (bp->next);
00324     cu->delta -= get_delta (cu->ox, bs[i]->x1, bs[i]->x2);
00325     cu->ox    += sx(i);
00326     cu->oy    += sy(i);
00327     return cu;
00328   }
00329 }
00330 
00331 selection
00332 composite_box_rep::find_selection (path lbp, path rbp) {
00333   if ((!is_atom (lbp)) && (!is_atom (rbp)) && (lbp->item == rbp->item)) {
00334     int i= lbp->item;
00335     selection sel= bs[i]->find_selection (lbp->next, rbp->next);
00336     return selection (translate (sel->rs, sx(i), sy(i)), sel->start, sel->end);
00337   }
00338   else return box_rep::find_selection (lbp, rbp);
00339 }
00340 
00341 gr_selections
00342 composite_box_rep::graphical_select (SI x, SI y, SI dist) {
00343   gr_selections res;
00344   if (graphical_distance (x, y) <= dist) {
00345     int i, n= subnr();
00346     for (i=n-1; i>=0; i--)
00347       res << bs[i]->graphical_select (x- sx(i), y- sy(i), dist);
00348   }
00349   return res;
00350 }
00351 
00352 gr_selections
00353 composite_box_rep::graphical_select (SI x1, SI y1, SI x2, SI y2) {
00354   gr_selections res;
00355   if (contains_rectangle (x1, y1, x2, y2)) {
00356     int i, n= subnr();
00357     for (i=n-1; i>=0; i--)
00358       res << bs[i]->graphical_select (x1- sx(i), y1- sy(i),
00359                                   x2- sx(i), y2- sy(i));
00360   }
00361   return res;
00362 }
00363 
00364 /******************************************************************************
00365 * Concrete composite box
00366 ******************************************************************************/
00367 
00368 int
00369 concrete_composite_box_rep::find_child (SI x, SI y, SI delta, bool force) {
00370   if (border_flag &&
00371       outside (x, delta, x1, x2) &&
00372       (is_accessible (ip) || force)) return -1;
00373   int i, n= subnr(), d= MAX_SI, m= -1;
00374   for (i=0; i<n; i++)
00375     if (distance (i, x, y, delta)< d)
00376       if (bs[i]->accessible () || force) {
00377        d= distance (i, x, y, delta);
00378        m= i;
00379       }
00380   return m;
00381 }
00382 
00383 /******************************************************************************
00384 * User interface
00385 ******************************************************************************/
00386 
00387 box
00388 composite_box (path ip, array<box> bs, bool bfl) {
00389   return tm_new<concrete_composite_box_rep> (ip, bs, bfl);
00390 }
00391 
00392 box
00393 composite_box (path ip, array<box> bs, array<SI> x, array<SI> y, bool bfl) {
00394   return tm_new<concrete_composite_box_rep> (ip, bs, x, y, bfl);
00395 }