home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / powervww / pvtable.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-05  |  24.9 KB  |  1,087 lines

  1. //  ____________________________________________________
  2. // |                                                    |
  3. // |  Project:     POWER VIEW INTERFACE                 |
  4. // |  File:        PVTABLE.CPP                          |
  5. // |  Compiler:    WPP386 (10.6)                        |
  6. // |                                                    |
  7. // |  Subject:     Tables support implementation        |
  8. // |                                                    |
  9. // |  Author:      Emil Dotchevski                      |
  10. // |____________________________________________________|
  11. //
  12. // E-mail: zajo@geocities.com
  13. // URL:    http://www.geocities.com/SiliconValley/Bay/3577
  14.  
  15. #define uses_stdio
  16. #define uses_string
  17. #define uses_icons
  18. #define uses_check
  19. #define uses_dc
  20. #define uses_desk
  21. #define uses_dialog
  22. #define uses_label
  23. #define uses_list
  24. #define uses_system
  25. #define uses_stddlg
  26. #define uses_table
  27. #define uses_win
  28.  
  29. #define DECLARE_PVTABLE_H
  30. #include "PVuses.h"
  31. #undef  DECLARE_PVTABLE_H
  32.  
  33. #define cmTABLE_UPDATE    cmUSER99
  34.  
  35. static Ttable_data *data_ptr;
  36. static boolean dialog_table_fl = 0;
  37.  
  38.  
  39. //Ttable_iterator publics:
  40.  
  41. Ttable_iterator::Ttable_iterator( int _xl, int _yl ):
  42.   Titem( _xl, _yl ),
  43.   h_beg_print( _h_beg_print ),
  44.   h_size( _h_size ),
  45.   h_count( _h_count ),
  46.   h_current( _h_current ),
  47.   v_beg_print( _v_beg_print ),
  48.   v_count( _v_count ),
  49.   v_current( _v_current )
  50. {
  51.   grow_mode = gmGROW_BOTH;
  52.   h_beg_print=h_count=h_size=h_current=v_beg_print=v_count=v_current=hsel_org=vsel_org=0;
  53. #ifndef NOMOUSE
  54.   set_events_mask( evMOUSE_REP, 1 );
  55. #endif
  56.   set_flags( tfDOUBLE_CLICK_OK|tfWHOLE_LINES, 1 );
  57. }
  58.  
  59. Ttable_iterator::Ttable_iterator( int _xl, int _yl,
  60.                                   uint &hsize,
  61.                                   uint &hbeg_print, uint &hcount, uint &hcurrent,
  62.                                   uint &vbeg_print, uint &vcount, uint &vcurrent ):
  63.   Titem( _xl, _yl ),
  64.   h_beg_print( hbeg_print ),
  65.   h_size( hsize ),
  66.   h_count( hcount ),
  67.   h_current( hcurrent ),
  68.   v_beg_print( vbeg_print ),
  69.   v_count( vcount ),
  70.   v_current( vcurrent )
  71. {
  72.   grow_mode = gmGROW_BOTH;
  73.   h_beg_print=h_count=h_size=h_current=v_beg_print=v_count=v_current=hsel_org=vsel_org=0;
  74. #ifndef NOMOUSE
  75.   set_events_mask( evMOUSE_REP, 1 );
  76. #endif
  77.   set_flags( tfDOUBLE_CLICK_OK|tfWHOLE_LINES, 1 );
  78. }
  79.  
  80. void Ttable_iterator::redraw( void )
  81. {
  82.   Titem::redraw();
  83.   if( owner != NULL ) owner->redraw();
  84. }
  85.  
  86. void Ttable_iterator::set_title( char *title )
  87. {
  88.   if( ( owner == NULL ) || ( owner->owner == NULL ) ) return;
  89.   ((Twindow *) owner->owner)->set_title( title );
  90. #ifdef TABLEINFO
  91.   if( !owner->flags(tfDIALOG) && current_table==owner )
  92.     ((Twindow *) table_info->owner)->set_title( title );
  93. #endif
  94. }
  95.  
  96. void Ttable_iterator::left( void )
  97. {
  98.   if( !h_current ) return;
  99.   h_current--;
  100.   uint n=0,w=0;
  101.   for( Ttable_data *d=data;
  102.        d!=NULL && n<h_current && w<h_beg_print;
  103.        n++,w+=d->width+1,d=d->nextc );
  104.   if( w<h_beg_print ) h_beg_print -= h_beg_print-w;
  105. }
  106.  
  107. void Ttable_iterator::right( void )
  108. {
  109.   if( h_current>=h_count-1 ) return;
  110.   h_current++;
  111.   int n=0,w=0;
  112.   for( Ttable_data *d=data;
  113.        d!=NULL && n<=h_current;
  114.        n++,w+=d->width+1,d=d->nextc );
  115.   w -= xl+1;
  116.   if( w<0 ) return;
  117.   if( h_beg_print<w ) h_beg_print += w-h_beg_print;
  118. }
  119.  
  120. void Ttable_iterator::up( void )
  121. {
  122.   cursor_up_left( v_current, v_beg_print, yl, 2 );
  123. }
  124.  
  125. void Ttable_iterator::down( void )
  126. {
  127.   cursor_down_right( v_current, v_beg_print, yl, v_count, 2 );
  128. }
  129.  
  130. void Ttable_iterator::top( void )
  131. {
  132.   cursor_top_home( v_current, v_beg_print );
  133. }
  134.  
  135. void Ttable_iterator::bottom( void )
  136. {
  137.   cursor_bottom_end( v_current, v_beg_print, yl, v_count );
  138. }
  139.  
  140. void Ttable_iterator::at( uint i )
  141. {
  142.   cursor_at( i, v_current, v_beg_print, yl, v_count );
  143. }
  144.  
  145. void Ttable_iterator::update_commands( void )
  146. {
  147. }
  148.  
  149. void Ttable_iterator::pgup( void )
  150. {
  151.   for( uint i = 1; i < yl; i++ ) up();
  152. }
  153.  
  154. void Ttable_iterator::pgdn( void )
  155. {
  156.   for( uint i = 1; i < yl; i++ ) down();
  157. }
  158.  
  159. //Ttable_iterator protected:
  160.  
  161. void Ttable_iterator::draw( void )
  162. {
  163.   uint row, col;
  164.   char buf[256];
  165.   Ttable_data *c;
  166.   char ta;
  167.   int l, i, j, rx, ry, rxl, ryl;
  168.   get_clip_rect( rx, ry, rxl, ryl );
  169.   int end=min(yl,ry+ryl);
  170.   rxl+=rx;
  171.   for( i=max(0,ry),row=v_beg_print+i; i<end; i++,row++ )
  172.   {
  173.     c = data;
  174.     col = 0;
  175.     j = -h_beg_print-1;
  176.     while( c != NULL )
  177.     {
  178.       if( j>rxl ) break;
  179.       if( c->where == whTABLE )
  180.       {
  181.         goto_xy( j, i ); j += c->width + 1;
  182.         if( j>=rx )
  183.         {
  184.           txtf( "%c", frame_standard[3] );
  185.           ta = text_attr;
  186.           *buf = 0;
  187.           if( row < v_count )
  188.             fetch( buf, row, col, c->width );
  189.           buf[c->width] = 0;
  190.           if( ( l = c->width - strlen( buf ) ) < 0 ) l = 0;
  191.           if( c->align == atRIGHT ) txtf( "|r%c ", l );
  192.           direct_txt( buf );
  193.           if( c->align == atLEFT ) txtf( "|r%c ", l );
  194.           text_attr = ta;
  195.         }
  196.       }
  197.       c = c->nextc; col++;
  198.     }
  199.     goto_xy( j, i ); txtf( "%c", frame_standard[3] );
  200.   }
  201. }
  202.  
  203. void Ttable_iterator::get_focused( void )
  204. {
  205.   Titem::get_focused();
  206.   update_commands();
  207. }
  208.  
  209. void Ttable_iterator::event_handler( Tevent &ev )
  210. {
  211.   uint vc=v_current, hc=h_current;
  212.   Titem::event_handler( ev );
  213.   if( state( isFOCUSED ) )
  214.     switch( ev.code )
  215.     {
  216.       case evKEY_PRESS:
  217.         switch( ev.ASCII )
  218.         {
  219.           case kUP: case kSHIFT_UP:
  220.             up(); break;
  221.           case kDOWN: case kSHIFT_DOWN:
  222.             down(); break;
  223.           case kPG_UP: case kSHIFT_PG_UP:
  224.             pgup(); break;
  225.           case kPG_DN: case kSHIFT_PG_DN:
  226.             pgdn(); break;
  227.           case kHOME: case kSHIFT_HOME:
  228.             top(); break;
  229.           case kEND: case kSHIFT_END:
  230.             bottom(); break;
  231.           default:
  232.             if( flags(tfWHOLE_LINES) )
  233.               goto not_handled;
  234.             else
  235.               switch( ev.ASCII )
  236.               {
  237.                 case kLEFT: case kSHIFT_LEFT:
  238.                   left(); break;
  239.                 case kRIGHT: case kSHIFT_RIGHT:
  240.                   right(); break;
  241.                 default:
  242.                   goto not_handled;
  243.               }
  244.         }
  245.         if( (hc!=h_current || vc!=v_current) && !(get_shifts()&smSHIFT) )
  246.           hsel_org=h_current, vsel_org=v_current;
  247.         handled( ev ); redraw();
  248.         item_acted = this;
  249.       not_handled:
  250.         break;
  251. #ifndef NOMOUSE
  252.       case evMOUSE_DOWN:
  253.         if( ev.INSIDE )
  254.         {
  255.           uint i, j=(uint) -1;
  256.           uint ih, jh=(uint) -1;
  257.           do
  258.           {
  259.             boolean vinside = (ev.LOCAL_Y>=0 && ev.LOCAL_Y<yl);
  260.             if( vinside || ev.code==evMOUSE_REP )
  261.             {
  262.               if( ev.LOCAL_Y >= 0 ) i = ev.LOCAL_Y; else i = 0;
  263.               i = v_beg_print + i;
  264.               if( !vinside )
  265.               {
  266.                 if( i > v_current ) down(); else up();
  267.                 i = v_current;
  268.               }
  269.               if( i >= v_count ) i = v_count - 1;
  270.               if( j != i )
  271.               {
  272.                 v_current = i;
  273.                 if( ev.code==evMOUSE_DOWN ) vsel_org = v_current;
  274.                 redraw();
  275.               }
  276.               j = v_current;
  277.             }
  278.             if( !flags(tfWHOLE_LINES) )
  279.             {
  280.               boolean hinside = (ev.LOCAL_X>=0 && ev.LOCAL_X<xl);
  281.               if( hinside || ev.code==evMOUSE_REP )
  282.               {
  283.                 if( ev.LOCAL_X >= 0 ) ih = ev.LOCAL_X; else ih = 0;
  284.                 ih = h_beg_print + ih;
  285.                 int xx=0, n=0;
  286.                 for( Ttable_data *d=data; d!=NULL; xx+=d->width+1,d=d->nextc,n++ )
  287.                   if( xx+d->width>ih ) break;
  288.                 ih = n;
  289.                 if( !hinside )
  290.                 {
  291.                   if( ih > h_current ) right(); else left();
  292.                   ih = h_current;
  293.                 }
  294.                 if( ih >= h_count ) ih = h_count - 1;
  295.                 if( jh != ih )
  296.                 {
  297.                   h_current = ih;
  298.                   if( ev.code==evMOUSE_DOWN ) hsel_org = h_current;
  299.                   redraw();
  300.                 }
  301.                 jh = h_current;
  302.               }
  303.             }
  304.             if( ev.CLICKS && flags(tfDOUBLE_CLICK_OK) && ev.INSIDE &&
  305.                 (v_beg_print+ev.LOCAL_Y <= v_count) )
  306.             {
  307.               put_command( NULL, cmOK );
  308.               break;
  309.             }
  310.           }
  311.           while( get_mouse( ev, evMOUSE_REP|evMOUSE_DRAG ) );
  312.           item_acted = this;
  313.           handled( ev );
  314.         }
  315. #endif
  316.     }
  317. }
  318.  
  319. void Ttable_iterator::drop( void *data )
  320. {
  321.   if( owner != NULL ) owner->drop( data );
  322. }
  323.  
  324.  
  325. //Tlist_iterator publics:
  326.  
  327. Tlist_iterator::Tlist_iterator( int _xl, int _yl ):
  328.   Ttable_iterator( _xl, _yl,
  329.                    _hsize,
  330.                    _hbeg_print, _h_count, _h_current,
  331.                    _vbeg_print, _vcount, _vcurrent ),
  332.   Tlb_list( _vcount, _vcurrent, _vbeg_print, yl,
  333.             _hsize, _hbeg_print, xl )
  334. {
  335. }
  336.  
  337. Tlist_iterator::Tlist_iterator( int _xl, int _yl, Tlb_list *_list ):
  338.   Ttable_iterator( _xl, _yl,
  339.                    _list->_hsize, _list->_hbeg_print,
  340.                    _h_count, _h_current,
  341.                    _list->_vbeg_print, _list->_vcount, _list->_vcurrent ),
  342.   Tlb_list( _list )
  343. {
  344. }
  345.  
  346.  
  347. //Ttable
  348.  
  349. static void dispose_table_data( Ttable_data *t )
  350. {
  351.   if( t == NULL ) return;
  352.   if( t->nested != NULL ) dispose_table_data( t->nested );
  353.   dispose_table_data( t->next );
  354.   FREE( t->title );
  355.   FREE( t );
  356. }
  357.  
  358. static void transfer( Ttable_data *t )
  359. {
  360.   if( t == NULL ) return;
  361.   t->where = t->parent->where;
  362.   if( t->nested != NULL ) transfer( t->nested );
  363.   transfer( t->next );
  364. }
  365.  
  366. static void fix_parent( Ttable_data *t )
  367. {
  368.   Ttable_data *p;
  369.   boolean table_ok = 0;
  370. #ifdef TABLEINFO
  371.   boolean info_ok = 0;
  372. #endif
  373.  
  374.   t = t->parent->nested;
  375.   p = t;
  376.   while( p != NULL )
  377.   {
  378.     if( p->where == whTABLE ) table_ok = 1;
  379. #ifdef TABLEINFO
  380.     if( p->where == whINFO  ) info_ok = 1;
  381. #endif
  382.     p = p->next;
  383.   }
  384.   t = t->parent;
  385.   if( t->parent == NULL ) return;
  386.   if( table_ok )
  387.     if( t->where == whTABLE )
  388.       return;
  389.     else
  390.       t->where = whTABLE;
  391. #ifdef TABLEINFO
  392.   else
  393.     if( info_ok )
  394.       t->where = whINFO;
  395.     else
  396.       t->where = whMUTE;
  397. #endif
  398.   fix_parent( t );
  399. }
  400.  
  401. static void move_info( Ttable_data *t, int where  )
  402. {
  403.   t->where = where;
  404.   if( t->nested != NULL ) transfer( t->nested );
  405.   fix_parent( t );
  406. }
  407.  
  408. static void get_item( Ttable_data *t, char *s )
  409. {
  410.   if( t->parent->parent != NULL )
  411.   {
  412.     get_item( t->parent, s );
  413.     strcat( s, "/" );
  414.   }
  415.   strcat( s, t->title );
  416. }
  417.  
  418. void full_title( Ttable_data *t, char *result )
  419. {
  420.   *result = 0;
  421.   get_item( t, result );
  422. }
  423.  
  424. static void calc_depth( Ttable_data *t )
  425. {
  426.   Ttable_data *p;
  427.  
  428.   while( t != NULL )
  429.   {
  430.     t->depth = 1;
  431.     if( t->nested != NULL ) calc_depth( t->nested );
  432.     p = t->parent;
  433.     if( t->depth >= p->depth ) p->depth = t->depth + 1;
  434.     t = t->next;
  435.   }
  436. }
  437.  
  438.  
  439. //Ttable publics:
  440.  
  441. #ifdef TABLEINFO
  442. static int open_tables_num=0;
  443. #endif
  444.  
  445. Ttable::Ttable( Ttable_data *_data, Ttable_iterator *_iterator ):
  446.   Titem( _iterator->xl, 1 )
  447. {
  448.   Tfile_window *win;
  449.   Ttable_data *t;
  450.   uint width;
  451.  
  452.   set_flags( tfDIALOG, dialog_table_fl );
  453. #ifdef TABLEINFO
  454.   if( !flags(tfDIALOG) && !open_tables_num++ && table_info!=NULL )
  455.     table_info->owner->set_state( isHIDDEN, 0 );
  456. #endif
  457.   data = _data;
  458.   iterator = _iterator;
  459.   title_vtab = 0;
  460.   calc_depth( data->nested );
  461.   first_col = data;
  462.   while( first_col->nested != NULL ) first_col = first_col->nested;
  463.   iterator->data = first_col;
  464.   title_cols = 0;
  465.   width = (uint) -1;
  466.   t = first_col;
  467.   while( t != NULL )
  468.   {
  469.     title_cols++;
  470.     width += t->width;
  471.     t = t->nextc;
  472.   }
  473.   width += title_cols;
  474.   title_rows = data->depth - 1;
  475.   drop_id = (long) this;
  476. #ifndef NOMOUSE
  477.   set_events_mask( evMOUSE_REP, 1 );
  478. #endif
  479.   grow_mode = flags(tfDIALOG)? gmDONT_GROW : gmGROW_BOTH;
  480.   if( __pure_table() )
  481.   {
  482.     iterator->set_state( isON_TOP, 1 );
  483.     resize( iterator->xl, title_rows+iterator->yl );
  484.     vbar = NEW( Tvscroll_bar( yl, iterator->v_count, iterator->v_beg_print ) );
  485.       vbar->set_flags( sfHIDEABLE, 1 );
  486.       vbar->set_flags( sfHANDLE_KEYBOARD, 0 );
  487.       vbar->delta = -title_rows;
  488.       vbar->set_state( isHIDDEN, 0 );
  489.       put_in( vbar, xl, 0 );
  490.     hbar = NEW( Thscroll_bar( xl, iterator->h_size, iterator->h_beg_print ) );
  491.       hbar->set_flags( sfHIDEABLE+sfHANDLE_KEYBOARD, 1 );
  492.       put_in( hbar, 0, yl );
  493.   }
  494.   else
  495.   {
  496.     iterator->resize( iterator->xl - i_sb_up_len - 1,
  497.                       iterator->yl - 2 - title_rows );
  498.     resize( iterator->xl, title_rows+iterator->yl );
  499.     win = NEW( Tfile_window( iterator->h_beg_print, iterator->h_size,
  500.                             iterator->v_beg_print, iterator->v_count,
  501.                             0,
  502.                             data->title, this ) );
  503.     win->vbar->delta = -title_rows;
  504.     win->hbar->set_flags( sfHANDLE_KEYBOARD, 1 );
  505.     win->drop_id = (long) this;
  506.     vbar = win->vbar;
  507.     hbar = win->hbar;
  508.   }
  509.   put_in( iterator, 0, title_rows );
  510.   iterator->drop_id = (long) this;
  511. }
  512.  
  513. Ttable::~Ttable( void )
  514. {
  515.   dispose_table_data( data );
  516. #ifdef TABLEINFO
  517.   if( !flags(tfDIALOG) )
  518.   {
  519.     current_table = NULL;
  520.     if( !--open_tables_num && table_info!=NULL )
  521.       table_info->owner->set_state( isHIDDEN, 1 );
  522.   }
  523. #endif
  524. }
  525.  
  526. void Ttable::resize( int _xl, int _yl )
  527. {
  528.   Ttable_data *t;
  529.   int w, h, rh, rw, tmp;
  530.  
  531.   Titem::resize( _xl, _yl );
  532.   w = 0; h = -1; iterator->h_count = 0;
  533.   for( t=first_col; t!=NULL && ++iterator->h_count; t=t->nextc )
  534.     if( t->where == whTABLE )
  535.     {
  536.       if( t->max_width > t->min_width )
  537.         w += t->max_width;
  538.       else
  539.         h += t->width;
  540.       h++;
  541.     }
  542.   iterator->h_size = h;
  543.   if( w == 0 ) return;
  544.   rh = xl - h;
  545.   rw = w;
  546.   iterator->h_size = (uint) -1;
  547.   for( t=first_col; t!=NULL; t=t->nextc )
  548.     if( t->where == whTABLE )
  549.     {
  550.       w = t->max_width; h = t->min_width;
  551.       tmp = ( w*rh ) / rw;
  552.       if( tmp<h ) tmp = h;
  553.       if( tmp>w ) tmp = w;
  554.       t->width = tmp;
  555.       iterator->h_size += tmp+1;
  556.     }
  557. }
  558.  
  559. #ifdef TABLEINFO
  560. void Ttable::redraw( void )
  561. {
  562.   Ttable_data *c;
  563.  
  564.   Titem::redraw();
  565.   if( !flags(tfDIALOG) )
  566.   {
  567.     c = first_col;
  568.     while( c != NULL )
  569.     {
  570.       if( c->where == whINFO )
  571.       {
  572.         table_info->redraw();
  573.         return;
  574.       }
  575.       c = c->nextc;
  576.     }
  577.   }
  578. }
  579. #endif
  580.  
  581. uint Ttable::col_width( Ttable_data *t )
  582. {
  583.   uint n, width;
  584.  
  585.   if( t->nested == NULL )
  586.     return t->width;
  587.   else
  588.   {
  589.     width = 0; n = (uint)-1;
  590.     t = t->nested;
  591.     while( t != NULL )
  592.     {
  593.       if( t->where == whTABLE )
  594.       {
  595.         width += col_width( t );
  596.         n++;
  597.       }
  598.       t = t->next;
  599.     }
  600.     return width + n;
  601.   }
  602. }
  603.  
  604. void Ttable::get_title( uint col, uint row, char *r )
  605. {
  606.   char s[256];
  607.   Ttable_data *p, *t;
  608.   int i, j;
  609.   int rw;
  610.   boolean fl;
  611.  
  612.   *r = 0; data_ptr = NULL;
  613.   t = first_col;
  614.   for( i = 2; i <= col; i++ ) t = t->nextc;
  615.   rw = title_rows - row;
  616.   i = 0; fl = 1;
  617.   for( ;; )
  618.   {
  619.     i++;
  620.     p = t->parent;
  621.     rw -= ( p->depth - 1 - t->depth );
  622.     if( i > rw ) break;
  623.     if( p->nested != t ) fl = 0;
  624.     t = p;
  625.   }
  626.   if( fl )
  627.   {
  628.     data_ptr = t;
  629.     if( t->where != whTABLE ) return;
  630.     p = t; while( p->parent != NULL ) p = p->parent;
  631.     if( ( row != p->depth - t->depth ) ) *s = 0; else strcpy( s, t->title );
  632.     i = col_width( t );
  633.     if( strlen( s ) > i ) s[i] = 0;
  634.     i -= strlen( s );
  635.     j = i/2; i -= j;
  636.     sprintf( r, "|b|r%c %s|r%c |1%c", j, s, i, frame_standard[3] );
  637.   }
  638. }
  639.  
  640. void Ttable::set_title_vtab( int _title_vtab )
  641. {
  642.   int delta;
  643.  
  644.   delta = title_vtab - _title_vtab;
  645.   title_vtab = _title_vtab;
  646.   vbar->delta = -( title_rows + title_vtab );
  647.   if( iterator == NULL ) return;
  648.   iterator->resize( iterator->xl, iterator->yl + delta );
  649.   iterator->drag( iterator->x, iterator->y - delta );
  650. }
  651.  
  652.  
  653. //Ttable protected:
  654.  
  655. #ifdef TABLEINFO
  656. void Ttable::get_focused( void )
  657. {
  658.   Titem::get_focused();
  659.   if( !flags(tfDIALOG) )
  660.   {
  661.     current_table = this;
  662.     ((Twindow *) table_info->owner)->set_title( ((Twindow *) owner)->title );
  663.     table_info->owner->set_state( isHIDDEN, 0 );
  664.   }
  665. }
  666.  
  667. boolean Ttable::release_focus( void )
  668. {
  669.   if( Titem::release_focus() )
  670.   {
  671.     if( !flags(tfDIALOG) && state(isHIDDEN) )
  672.     {
  673.       table_info->owner->set_state( isHIDDEN, 1 );
  674.       current_table=NULL;
  675.     }
  676.     return 1;
  677.   }
  678.   return 0;
  679. }
  680. #endif
  681.  
  682. void Ttable::draw( void )
  683. {
  684.   int row, col;
  685.   char buf[256];
  686.  
  687.   for( row = 1; row <= title_rows; row++ )
  688.   {
  689.     goto_xy( -iterator->h_beg_print, ( row - 1 ) + title_vtab );
  690.     for( col = 1; col <= title_cols; col++ )
  691.     {
  692.       get_title( col, row, buf );
  693.       txt( buf );
  694.     }
  695.   }
  696. }
  697.  
  698. #ifdef TABLEINFO
  699. static char *drag_text;
  700. static void Ttable_drag_draw( void )
  701. {
  702.   direct_txt( drag_text );
  703. }
  704. #endif
  705.  
  706. void Ttable::event_handler( Tevent &ev )
  707. {
  708.   Titem::event_handler( ev );
  709.   switch( ev.code )
  710.   {
  711. #ifdef TABLEINFO
  712.     case evCOMMAND:
  713.       if( ev.CMD_CODE == cmTABLE_UPDATE )
  714.       {
  715.         handled( ev );
  716.         resize( xl, yl );
  717.       }
  718.       break;
  719. #endif
  720. #if !defined( NOMOUSE ) && defined( TABLEINFO )
  721.     case evMOUSE_DOWN:
  722.       if( !flags(tfDIALOG) && ev.INSIDE && ev.LOCAL_Y<title_rows )
  723.       {
  724.         uint c;
  725.         int n;
  726.         Ttable_data *p;
  727.         char s[256];
  728.  
  729.         c = 0; n = -iterator->h_beg_print;
  730.         p = first_col;
  731.         do
  732.         {
  733.           if( p == NULL ) return;
  734.           c++;
  735.           if( p->where == whTABLE )
  736.           {
  737.             n += p->width;
  738.             n++;
  739.           }
  740.           p = p->nextc;
  741.         }
  742.         while( n <= ev.LOCAL_X );
  743.         n = ev.LOCAL_Y + 1 + title_vtab;
  744.         if( n < 1 ) return;
  745.         *s = 0;
  746.         while( *s == 0 )
  747.         {
  748.           get_title( c, n, s );
  749.           c--;
  750.         }
  751.         if( dont_touch( data_ptr ) ) return;
  752.         drag_text = data_ptr->title;
  753.         _drag_draw( strlen( drag_text ), 1, Ttable_drag_draw );
  754.         pick_up( ev.GLOBAL_X, ev.GLOBAL_Y, (long) table_info, data_ptr );
  755.         handled( ev );
  756.       }
  757. #endif
  758.   }
  759. }
  760.  
  761. #ifdef TABLEINFO
  762. void Ttable::drop( void *_data )
  763. {
  764.   move_info( (Ttable_data *) _data, whTABLE );
  765.   resize( xl, yl );
  766.   redraw();
  767.   table_info->redraw();
  768. }
  769.  
  770. //Ttable private:
  771.  
  772. boolean Ttable::dont_touch( Ttable_data *t )
  773. {
  774.   char n;
  775.   Ttable_data *p;
  776.  
  777.   t = t->parent;
  778.   if( t == NULL ) return 1;
  779.   n = 0;
  780.   p = t->nested;
  781.   while( p != NULL )
  782.   {
  783.     if( p->where == whTABLE ) n++;
  784.       p = p->next;
  785.   }
  786.   if( n > 1 )
  787.     return 0;
  788.   else
  789.     return dont_touch( t );
  790. }
  791. #endif
  792.  
  793.  
  794. //Ttable_info
  795.  
  796.  
  797. //Ttable_info publics:
  798.  
  799. #ifdef TABLEINFO
  800. Ttable_info::Ttable_info( void ):
  801.   Titem( desktop->xl-i_sb_up_len-1, 5 )
  802. {
  803.   Tfile_window *win;
  804.  
  805.   drop_id = (long) this;
  806.   hbeg_print = 0;
  807.   vbeg_print = 0;
  808.   grow_mode = gmGROW_BOTH;
  809.   win = NEW( Tfile_window( hbeg_print, hcount,
  810.                            vbeg_print, vcount,
  811.                            0,
  812.                            NULL, this ) );
  813.   win->set_flags( ifSELECTABLE+ifTILEABLE+ifCLOSEABLE, 0 );
  814.   win->drop_id = (long) this;
  815.   win->palette = wpTOOL;
  816.   win->set_state( isHIDDEN, 1 );
  817.   desktop->put_in( win, desktop->xl-win->xl, desktop->yl-win->yl );
  818. }
  819.  
  820. Ttable_info::~Ttable_info( void )
  821. {
  822.   table_info=NULL;
  823. }
  824.  
  825. //Ttable_info protected:
  826.  
  827. void Ttable_info::draw( void )
  828. {
  829.   Ttable_data *t;
  830.   int row, col;
  831.   uint hmax;
  832.   char buf[256], at;
  833.  
  834.   if( current_table == NULL ) return;
  835.   hcount = 0; vcount = 0;
  836.   row = 0;
  837.   hmax = 0;
  838.   t = current_table->first_col;
  839.   while( t != NULL )
  840.   {
  841.     if( t->where == whINFO )
  842.     {
  843.       vcount++;
  844.       goto_xy( -hbeg_print, row++ - vbeg_print );
  845.       draw_item( t );
  846.       direct_txt( ": " );
  847.       hcount += 2;
  848.       if( hcount > hmax ) hmax = hcount;
  849.       hcount = 0;
  850.     }
  851.     t = t->nextc;
  852.   }
  853.   if( current_table->iterator->v_current >=
  854.       current_table->iterator->v_count ) return;
  855.   hcount = hmax;
  856.   row = col = 0;
  857.   hmax = 0;
  858.   t = current_table->first_col;
  859.   while( t != NULL )
  860.   {
  861.     if( t->where == whINFO )
  862.     {
  863.       goto_xy( hcount - hbeg_print, row++ - vbeg_print );
  864.       at = text_attr;
  865.       current_table->iterator->fetch( buf, current_table->iterator->v_current, col, t->width );
  866.       text_attr = at;
  867.       if( strlen( buf ) > hmax ) hmax = strlen( buf );
  868.       direct_txt( buf );
  869.     }
  870.     t = t->nextc; col++;
  871.   }
  872.   hcount += hmax;
  873. }
  874.  
  875. static void get_depth( Ttable_data *p, int &x )
  876. {
  877.   if( p->parent->parent != NULL ) get_depth( p->parent, x );
  878.   if( x < 0 ) return;
  879.   if( x <= strlen( p->title ) ) data_ptr = p;
  880.   x -= strlen( p->title ); x--;
  881. }
  882.  
  883. void Ttable_info::event_handler( Tevent &ev )
  884. {
  885.   Ttable_data *t;
  886.   int xx, yy;
  887.  
  888.   Titem::event_handler( ev );
  889.   if( current_table == NULL ) return;
  890.   switch( ev.code )
  891.   {
  892.     case evMOUSE_DOWN:
  893.       if( ev.INSIDE )
  894.       {
  895.         t = current_table->first_col;
  896.         yy = -vbeg_print;
  897.         while( t != NULL )
  898.         {
  899.           if( t->where == whINFO )
  900.           {
  901.             if( yy == ev.LOCAL_Y )
  902.             {
  903.               xx = ev.LOCAL_X + hbeg_print;
  904.               data_ptr = t; get_depth( t, xx );
  905.               drag_text = data_ptr->title;
  906.               _drag_draw( strlen( drag_text ), 1, Ttable_drag_draw );
  907.               pick_up( ev.GLOBAL_X, ev.GLOBAL_Y, (long) current_table, data_ptr );
  908.               break;
  909.             }
  910.             yy++;
  911.           }
  912.           t = t->nextc;
  913.         }
  914.         handled( ev );
  915.       }
  916.   }
  917. }
  918.  
  919. void Ttable_info::drop( void *data )
  920. {
  921.   move_info( (Ttable_data *) data, whINFO );
  922.   redraw();
  923.   message( current_table, cmTABLE_UPDATE );
  924. }
  925.  
  926. void Ttable_info::draw_item( Ttable_data *t )
  927. {
  928.   if( t->parent->parent != NULL )
  929.   {
  930.     draw_item( t->parent );
  931.     direct_txt( "/" );
  932.     hcount++;
  933.   }
  934.   txtf( "|b%s", t->title );
  935.   hcount += strlen( t->title );
  936. }
  937. #endif
  938.  
  939.  
  940. //Ttable_data interface functions
  941.  
  942. static char *current_title;
  943. static Ttable_data *previous_data;
  944. static Ttable_data *current_item;
  945. static Ttable_data *current_parent;
  946. static Ttable_iterator *table_iterator;
  947.  
  948. static Ttable_data *new_item( void )
  949. {
  950.   Ttable_data *p;
  951.  
  952.   p = NEW( Ttable_data );
  953.   if( current_item != NULL )
  954.     current_item->next = p;
  955.   else
  956.     if( current_parent != NULL ) current_parent->nested = p;
  957.   current_item = p;
  958.   current_item->next = NULL;
  959.   current_item->parent = current_parent;
  960.   current_item->where = whTABLE;
  961.   current_item->nested = NULL;
  962.   return p;
  963. }
  964.  
  965. void construct_table( char *title, Ttable_iterator *iterator )
  966. {
  967.   table_iterator = iterator;
  968.   current_title = title;
  969.   previous_data = NULL;
  970.   current_item = NULL;
  971.   current_parent = NULL;
  972.   subdata( title );
  973.   dialog_table_fl = 0;
  974. }
  975.  
  976. void dialog_table( char *title, Ttable_iterator *iterator )
  977. {
  978.   construct_table( title, iterator );
  979.   dialog_table_fl = 1;
  980.   _pure_table();
  981. }
  982.  
  983. void subdata( char *t )
  984. {
  985.   Ttable_data *data;
  986.  
  987.   data = new_item();
  988.   data->title = STRDUP( t );
  989.   data->width = 0;
  990.   data->depth = 0;
  991.   data->min_width = 0;
  992.   data->max_width = 0;
  993.   data->nextc = NULL;
  994.   data->old_parent = current_parent;
  995.   data->old_item = current_item;
  996.   current_parent = data;
  997.   current_item = NULL;
  998. }
  999.  
  1000. Ttable *endt( void )
  1001. {
  1002.   Ttable_data *p;
  1003.   Ttable *t;
  1004.   Tbox *b;
  1005.  
  1006.   p = current_parent;
  1007.   current_item = current_parent->old_item;
  1008.   current_parent = current_parent->old_parent;
  1009.   if( current_parent != NULL ) return NULL;
  1010.   t = NEW( Ttable( p, table_iterator ) );
  1011.   if( dialog_table_fl )
  1012.   {
  1013.     t->vbar->set_state(isHIDDEN,0);
  1014.     b = NEW( Tbox( current_title, t ) );
  1015.     b->resize( b->xl-1, b->yl );
  1016.     t->put_in( b, -1, -1 );
  1017.     hspace(); vspace();
  1018.     put_item( t, b->xl, b->yl-1 );
  1019.     hspaces( -1 );
  1020.   }
  1021.   return t;
  1022. }
  1023.  
  1024. Ttable_data *tdata( char *t, uint _min, uint _max )
  1025. {
  1026.   Ttable_data *d;
  1027.  
  1028.   d = new_item();
  1029.   d->title = STRDUP( t );
  1030.   d->width = _max;
  1031.   d->min_width = _min;
  1032.   d->max_width = _max;
  1033.   d->align = atLEFT; if( __tright() ) d->align = atRIGHT;
  1034.   d->nextc = NULL;
  1035.   if( previous_data != NULL ) previous_data->nextc = d;
  1036.   previous_data = d;
  1037.   return d;
  1038. }
  1039.  
  1040. void move_table_data( Ttable *table, Ttable_data *data, char where )
  1041. {
  1042.   move_info( data, where );
  1043. #ifdef TABLEINFO
  1044.   table_info->redraw();
  1045. #endif
  1046.   message( table, cmTABLE_UPDATE );
  1047. }
  1048.  
  1049.  
  1050. //prefixes
  1051.  
  1052. static boolean pure_ = 0;
  1053. static boolean tright_ = 0;
  1054.  
  1055. void _pure_table( void )
  1056. {
  1057.   pure_ = 1;
  1058. }
  1059.  
  1060. boolean __pure_table( void )
  1061. {
  1062.   boolean result = pure_;
  1063.   pure_ = 0;
  1064.   return result;
  1065. }
  1066.  
  1067. void _tright( void )
  1068. {
  1069.   tright_ = 1;
  1070. }
  1071.  
  1072. boolean __tright( void )
  1073. {
  1074.   boolean result = tright_;
  1075.   tright_ = 0;
  1076.   return result;
  1077. }
  1078.  
  1079. //Initialization
  1080.  
  1081. void __init_tables( void )
  1082. {
  1083. #ifdef TABLEINFO
  1084.   table_info = NEW( Ttable_info );
  1085. #endif
  1086. }
  1087.