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

  1. //  ____________________________________________________
  2. // |                                                    |
  3. // |  Project:     POWER VIEW INTERFACE                 |
  4. // |  File:        PVLBOX.CPP                           |
  5. // |  Compiler:    WPP386 (10.6)                        |
  6. // |                                                    |
  7. // |  Subject:     List box 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_string
  16. #define uses_dc
  17. #define uses_dialog
  18. #define uses_icons
  19. #define uses_label
  20. #define uses_lbox
  21. #define uses_system
  22.  
  23. #include "PVuses.h"
  24.  
  25. #define SCROLL_AHEAD 1
  26.  
  27. static uint ___data_size;
  28. static Tlb_item_comparator ___comparator;
  29.  
  30. //cmp functions
  31.  
  32. static int cmp_function( const Tlb_item *a, const Tlb_item *b )
  33. {
  34.   return
  35.     strcmp(
  36.       a->data + ___data_size,
  37.       b->data + ___data_size
  38.     );
  39. }
  40.  
  41. static int _cmp_function( const Tlb_item *a, const Tlb_item *b )
  42. {
  43.   return ___comparator( a, b );
  44. }
  45.  
  46. //sort functions
  47.  
  48. static int sort_function( const void *a, const void *b )
  49. {
  50.   return
  51.     strcmp(
  52.       ( *( (Tlb_item **) a ) )->data + ___data_size,
  53.       ( *( (Tlb_item **) b ) )->data + ___data_size
  54.     );
  55. }
  56.  
  57. static int _sort_function( const void *a, const void *b )
  58. {
  59.   return ___comparator( *( (Tlb_item **) a ), *( (Tlb_item **) b ) );
  60. }
  61.  
  62. //search functions
  63.  
  64. static int search_function( const void *a, const void *b )
  65. {
  66.   return
  67.     strcmp(
  68.       ( (Tlb_item *) a )->data + ___data_size,
  69.       ( *( (Tlb_item **) b ) )->data + ___data_size
  70.     );
  71. }
  72.  
  73. static int _search_function( const void *a, const void *b )
  74. {
  75.   return ___comparator( (Tlb_item *) a, *( (Tlb_item **) b ) );
  76. }
  77.  
  78.  
  79. //Tlb_list publics:
  80.  
  81. Tlb_list::Tlb_list( void ):
  82.   Tlist(),
  83.   hsize( _hsize ),
  84.   hbeg_print( _hbeg_print ),
  85.   hmax_print( _hmax_print ),
  86.   hmax_size( _hmax_size ),
  87.   changed( _changed ),
  88.   overflow( _overflow )
  89. {
  90.   items_ptr = (Tlb_arr *) MALLOC( 0x100 * sizeof( Tlb_item * ) );
  91.   scroll_ahead = SCROLL_AHEAD;
  92.   hsize = 0;
  93.   hmax_size = 0;
  94.   hbeg_print = 0;
  95.   data_size = __lsize();
  96.   overflow = 0;
  97.   changed = 1;
  98.   lb_item_killer = __litem_killer();
  99.   lb_item_comparator = __litem_comparator();
  100. }
  101.  
  102. Tlb_list::Tlb_list( Tlb_list *_list ):
  103.   Tlist( _list ),
  104.   hsize( _list->hsize ),
  105.   hbeg_print( _hbeg_print ),
  106.   hmax_print( _hmax_print ),
  107.   hmax_size( _list->hmax_size ),
  108.   changed( _list->changed ),
  109.   overflow( _list->overflow )
  110. {
  111.   hmax_size = 0;
  112.   hbeg_print = 0;
  113.   items_ptr = _list->items_ptr;
  114.   data_size = _list->data_size;
  115.   lb_item_killer = _list->lb_item_killer;
  116.   lb_item_comparator = _list->lb_item_comparator;
  117. }
  118.  
  119. Tlb_list::Tlb_list( uint &v_count, uint &v_current, uint &v_beg_print, int &v_max_print,
  120.                     uint &h_size, uint &h_beg_print, int &h_max_print ):
  121.   Tlist( v_count, v_current, v_beg_print, v_max_print ),
  122.   hsize( h_size ),
  123.   hbeg_print( h_beg_print ),
  124.   hmax_print( h_max_print ),
  125.   hmax_size( _hmax_size ),
  126.   changed( _changed ),
  127.   overflow( _overflow )
  128. {
  129.   items_ptr = (Tlb_arr *)MALLOC( 0x100 * sizeof( Tlb_item * ) );
  130.   scroll_ahead = SCROLL_AHEAD;
  131.   hsize = 0;
  132.   hmax_size = 0;
  133.   hbeg_print = 0;
  134.   data_size = __lsize();
  135.   overflow = 0;
  136.   changed = 1;
  137.   lb_item_killer = __litem_killer();
  138.   lb_item_comparator = __litem_comparator();
  139. }
  140.  
  141. Tlb_list::~Tlb_list( void )
  142. {
  143.   if( !( options & loASSOCIATED ) )
  144.   {
  145.     clear();
  146.     if( items_ptr != NULL ) FREE( items_ptr );
  147.   }
  148. }
  149.  
  150. void Tlb_list::clear( void )
  151. {
  152.   if( items_ptr != NULL )
  153.     for( uint i = 0; i < vcount; i++ )
  154.       free_lb_item( (*items_ptr)[i] );
  155.   hsize = 0;
  156.   hmax_size = 0;
  157.   hbeg_print = 0;
  158.   overflow = 0;
  159.   changed = 1;
  160.   Tlist::clear();
  161. }
  162.  
  163. uint Tlb_list::add( void *data )
  164. {
  165.   Tlb_item *p;
  166.   int (* cmp) ( const Tlb_item *, const Tlb_item * );
  167.   int m, l, r, x;
  168.  
  169.   if( overflow ) return (uint) -1;
  170.   p = alloc_lb_item( (char *) data );
  171.   if( p == NULL )
  172.   {
  173.     overflow = 1;
  174.     return (uint) -1;
  175.   }
  176.   inc_count();
  177.   if( overflow )
  178.   {
  179.     free_lb_item( p );
  180.     return (uint) -1;
  181.   }
  182.   l = vcount - 1;
  183.   if( ( vcount > 1 ) && ( options & loSORTED ) )
  184.   {
  185.     cmp = cmp_function;
  186.     if( lb_item_comparator != NULL ) cmp = _cmp_function;
  187.     ___data_size = data_size;
  188.     ___comparator = lb_item_comparator;
  189.     l = 0; r = vcount - 2;
  190.     while( l <= r )
  191.     {
  192.       m = ( l + r ) / 2;
  193.       x = cmp( (*items_ptr)[m], p );
  194.       if( x == 0 )
  195.       {
  196.         l = m;
  197.         break;
  198.       }
  199.       if( x < 0 ) { l = m+1; continue; }
  200.       if( x > 0 ) r = m-1;
  201.     }
  202.     if( l < ( vcount - 1 ) )
  203.       memmove( &( (*items_ptr)[l + 1] ), &( (*items_ptr)[l] ), (vcount - l - 1) * sizeof( Tlb_item * ) );
  204.   }
  205.   (*items_ptr)[l] = p;
  206.   at( l );
  207.   changed = 1;
  208.   return l;
  209. }
  210.  
  211. void Tlb_list::ins( uint i, void *data )
  212. {
  213.   Tlb_item *lbi;
  214.  
  215.   if( overflow ) return;
  216.   if( i >= vcount )
  217.     add( data );
  218.   else
  219.   {
  220.     lbi = alloc_lb_item( (char *) data );
  221.     if( lbi == NULL )
  222.     {
  223.       overflow = 1;
  224.       return;
  225.     }
  226.     inc_count();
  227.     if( overflow ) return;
  228.     memmove( &( (*items_ptr)[i + 1] ), &( (*items_ptr)[i] ), (vcount - i - 1) * sizeof( Tlb_item * ) );
  229.     (*items_ptr)[i] = lbi;
  230.   }
  231.   changed = 1;
  232. }
  233.  
  234. void Tlb_list::del( uint i )
  235. {
  236.   if( ( i >= vcount ) || !vcount ) return;
  237.   free_lb_item( (*items_ptr)[i] );
  238.   memmove( &( (*items_ptr)[i] ), &( (*items_ptr)[i+1] ), (vcount - i - 1) * sizeof( Tlb_item * ) );
  239.   dec_count();
  240.   if( vcurrent >= vcount ) bottom();
  241.   overflow = 0;
  242.   changed = 1;
  243. }
  244.  
  245. void Tlb_list::get( uint i, void *data )
  246. {
  247.   Tlb_item *p;
  248.  
  249.   if( i >= vcount ) return;
  250.   p = (*items_ptr)[i];
  251.   memmove( data, p->data, data_size );
  252.   strcpy( ( (char *) data ) + data_size, p->data+data_size );
  253. }
  254.  
  255. void Tlb_list::put( uint i, void *data )
  256. {
  257.   Tlb_item *n;
  258.  
  259.   if( i >= vcount ) return;
  260.   n = alloc_lb_item( (char *) data );
  261.   if( n == NULL )
  262.   {
  263.     overflow = 1;
  264.     return;
  265.   }
  266.   free_lb_item( (*items_ptr)[i] );
  267.   (*items_ptr)[i] = n;
  268.   changed = 1;
  269. }
  270.  
  271. void Tlb_list::sort( void )
  272. {
  273.   sort_range( 0, vcount );
  274. }
  275.  
  276. void Tlb_list::sort_range( uint from, uint how_many )
  277. {
  278.   int (* sort_func) ( const void *, const void * );
  279.  
  280.   sort_func = sort_function;
  281.   if( lb_item_comparator != NULL ) sort_func = _sort_function;
  282.   ___data_size = data_size;
  283.   ___comparator = lb_item_comparator;
  284.   qsort( *items_ptr + from, how_many, sizeof( Tlb_item * ), sort_func );
  285. }
  286.  
  287. uint Tlb_list::bin_search( Tlb_item *p )
  288. {
  289.   return bin_search_range( p, 0, vcount );
  290. }
  291.  
  292. uint Tlb_list::bin_search_range( Tlb_item *p, uint from, uint how_many )
  293. {
  294.   int (* search_func) ( const void *, const void * );
  295.   Tlb_item **key;
  296.  
  297.   search_func = search_function;
  298.   if( lb_item_comparator != NULL ) search_func = _search_function;
  299.   ___data_size = data_size;
  300.   ___comparator = lb_item_comparator;
  301.   key = (Tlb_item **) bsearch( p, *items_ptr + from, how_many, sizeof( Tlb_item * ), search_func );
  302.   if( key == NULL ) return -1;
  303.   return key - *items_ptr;
  304. }
  305.  
  306. void Tlb_list::up( void )
  307. {
  308.   uint i, j;
  309.  
  310.   if( !vcount ) return;
  311.   i = vcurrent; j = vbeg_print;
  312.   Tlist::up();
  313.   while( !enabled( vcurrent ) && vcurrent ) Tlist::up();
  314.   if( !enabled( vcurrent ) )
  315.   {
  316.     vcurrent = i;
  317.     vbeg_print = j;
  318.   }
  319. }
  320.  
  321. void Tlb_list::down( void )
  322. {
  323.   uint i, j;
  324.  
  325.   if( !vcount ) return;
  326.   i = vcurrent; j = vbeg_print;
  327.   Tlist::down();
  328.   while( !enabled( vcurrent ) && ( vcurrent < ( vcount - 1 ) ) ) Tlist::down();
  329.   if( !enabled( vcurrent ) )
  330.   {
  331.     vcurrent = i;
  332.     vbeg_print = j;
  333.   }
  334. }
  335.  
  336. void Tlb_list::top( void )
  337. {
  338.   if( !vcount ) return;
  339.   Tlist::top();
  340.   while( !enabled( vcurrent ) && ( vcurrent < ( vcount - 1 ) ) ) Tlist::down();
  341. }
  342.  
  343. void Tlb_list::bottom( void )
  344. {
  345.   if( !vcount ) return;
  346.   Tlist::bottom();
  347.   while( !enabled( vcurrent ) && vcurrent ) Tlist::up();
  348. }
  349.  
  350. void Tlb_list::at( uint i )
  351. {
  352.   if( !vcount ) return;
  353.   if( ( i < vcount ) && enabled( i ) ) Tlist::at( i );
  354. }
  355.  
  356. void Tlb_list::gettxt( uint i, char *t )
  357. {
  358.   Tlb_item *p;
  359.  
  360.   if( ( i < vcount ) && ( ( p = (*items_ptr)[i] ) != NULL ) )
  361.     item_str( p, t );
  362.   else
  363.     *t = 0;
  364. }
  365.  
  366. void *Tlb_list::getptr( uint i )
  367. {
  368.   return (*items_ptr)[i]->data;
  369. }
  370.  
  371. void Tlb_list::error( int error_code )
  372. {
  373.   exit( error_code );
  374. }
  375.  
  376. static char *search = NULL;
  377.  
  378. static boolean text_filter( Tlist *list, uint i )
  379. {
  380.   char s[256];
  381.  
  382.   list->gettxt( i, s );
  383.   return( strcmp( s, search ) == 0 );
  384. }
  385.  
  386. uint Tlb_list::findft( char *t )
  387. {
  388.   search = t;
  389.   return findf( text_filter );
  390. }
  391.  
  392. void Tlb_list::add_title( char *data )
  393. {
  394.   add( data );
  395.   ( (*items_ptr)[vcount - 1] )->flags = lbfTITLE;
  396. }
  397.  
  398. void Tlb_list::add_blank( void )
  399. {
  400.   add( "" );
  401.   ( (*items_ptr)[vcount - 1] )->flags = lbfDISABLED+lbfTITLE;
  402. }
  403.  
  404. void Tlb_list::getdata( uint i, void *data )
  405. {
  406.   Tlb_item *p;
  407.  
  408.   if( i >= vcount ) return;
  409.   p = (*items_ptr)[i];
  410.   if( p == NULL ) return;
  411.   item_data( p, data );
  412. }
  413.  
  414. void Tlb_list::item_data( Tlb_item *p, void *data )
  415. {
  416.   memmove( data, p->data, data_size );
  417. }
  418.  
  419. void Tlb_list::item_str( Tlb_item *p, char *s )
  420. {
  421.   strcpy( s, p->data+data_size );
  422. }
  423.  
  424. void Tlb_list::check( uint i, boolean f )
  425. {
  426.   Tlb_item *p;
  427.  
  428.   if( i >= vcount ) return;
  429.   p = (*items_ptr)[i];
  430.   if( p != NULL )
  431.     if( f )
  432.       p->flags |= lbfCHECKED;
  433.     else
  434.       p->flags &= ~lbfCHECKED;
  435. }
  436.  
  437. boolean Tlb_list::checked( uint i )
  438. {
  439.   Tlb_item *p;
  440.  
  441.   if( i >= vcount ) return 0;
  442.   p = (*items_ptr)[i];
  443.   if( p != NULL ) return ( p->flags & lbfCHECKED ) != 0;
  444.   return 0;
  445. }
  446.  
  447. void Tlb_list::set_enable( uint i, boolean f )
  448. {
  449.   Tlb_item *p;
  450.  
  451.   if( i >= vcount ) return;
  452.   p = (*items_ptr)[i];
  453.   if( p != NULL )
  454.     if( f )
  455.       p->flags &= ~lbfDISABLED;
  456.     else
  457.       p->flags |= lbfDISABLED;
  458. }
  459.  
  460. boolean Tlb_list::enabled( uint i )
  461. {
  462.   Tlb_item *p;
  463.  
  464.   if( i >= vcount ) return 0;
  465.   p = (*items_ptr)[i];
  466.   if( p != NULL ) return ( p->flags & lbfDISABLED ) == 0;
  467.   return 0;
  468. }
  469.  
  470. void Tlb_list::set_comparator( Tlb_item_comparator _lb_item_comparator )
  471. {
  472.   lb_item_comparator = _lb_item_comparator;
  473. }
  474.  
  475. //Tlb_list protected:
  476.  
  477. void Tlb_list::inc_count( void )
  478. {
  479.   Tlb_arr *n;
  480.   uint cnt;
  481.  
  482.   cnt = vcount + 1;
  483.   if( !cnt )
  484.   {
  485.     overflow = 1;
  486.     return;
  487.   }
  488.   if( !( cnt & 0xFF ) )
  489.   {
  490.     n = ( Tlb_arr * ) REALLOC( items_ptr, ( ( cnt & ~0xFF ) + 0x100 ) * sizeof( Tlb_item * ) );
  491.     if( n )
  492.       items_ptr = n;
  493.     else
  494.     {
  495.       overflow = 1;
  496.       return;
  497.     }
  498.   }
  499.   vcount = cnt;
  500. }
  501.  
  502. void Tlb_list::dec_count( void )
  503. {
  504.   Tlb_arr *n;
  505.   uint cnt;
  506.  
  507.   if( !vcount ) return;
  508.   cnt = vcount - 1;
  509.   if( !( vcount & 0xFF ) )
  510.   {
  511.     n = ( Tlb_arr * ) REALLOC( items_ptr, ( ( vcount & ~0xFF ) + 0x100 ) * sizeof( Tlb_item * ) );
  512.     if( n )
  513.       items_ptr = n;
  514.     else
  515.     {
  516.       overflow = 1;
  517.       return;
  518.     }
  519.   }
  520.   vcount = cnt;
  521. }
  522.  
  523. Tlb_item * Tlb_list::alloc_lb_item( char *data )
  524. {
  525.   Tlb_item *p;
  526.   int sl, so;
  527.   void *usr_data;
  528.  
  529.   usr_data = __ldata();
  530.   so = 0;
  531.   if( usr_data == NULL ) usr_data = data, so = data_size;
  532.   sl = strlen( data + so );
  533.   p = (Tlb_item *)MALLOC( 1 + data_size + sl + 1 );
  534.   if( p != NULL )
  535.   {
  536.     p->flags = 0;
  537.     if( data_size ) memmove( p->data, usr_data, data_size );
  538.     memmove( p->data + data_size, data + so, sl + 1 );
  539.     if( sl >= hsize )
  540.     {
  541.       if( sl > hsize )
  542.       {
  543.         hsize = sl;
  544.         hmax_size = 0;
  545.       }
  546.       hmax_size++;
  547.     }
  548.   }
  549.   return p;
  550. }
  551.  
  552. void Tlb_list::free_lb_item( Tlb_item *p )
  553. {
  554.   uint n,i;
  555.   int l;
  556.  
  557.   l = strlen( p->data + data_size );
  558.   if( ( hsize > hmax_print ) && ( l == hsize ) )
  559.   {
  560.     hmax_size--;
  561.     if( !hmax_size )
  562.       for( hsize = i = 0; i < vcount; i++ )
  563.       {
  564.         n = strlen( ( (*items_ptr)[i] )->data + data_size );
  565.         if( n >= hsize )
  566.         {
  567.           if( n > hsize )
  568.           {
  569.             hsize = n;
  570.             hmax_size = 0;
  571.           }
  572.           hmax_size++;
  573.         }
  574.       }
  575.   }
  576.   if( lb_item_killer != NULL ) lb_item_killer( p->data );
  577.   FREE( p );
  578. }
  579.  
  580. void Tlb_list::flip( uint i )
  581. {
  582.   check( i, !checked( i ) );
  583. }
  584.  
  585. void Tlb_list::multi_flip( uint from, uint to )
  586. {
  587.   uint i, min, max;
  588.  
  589.   if( from > to )
  590.   {
  591.     min = to;
  592.     max = from - 1;
  593.   }
  594.   else
  595.   {
  596.     min = from + 1;
  597.     max = to;
  598.   }
  599.   for( i = min; i <= max; i++ ) flip( i );
  600. }
  601.  
  602.  
  603. //Tlist_box publics:
  604.  
  605. Tlist_box::Tlist_box( uint &_data, int _xl, int _yl ):
  606.   Titem( _xl + 2, _yl ),
  607.   Tlb_list()
  608. {
  609.   init( _data );
  610. }
  611.  
  612. Tlist_box::Tlist_box( uint &_data, int _xl, int _yl, Tlb_list *_list ):
  613.   Titem( _xl + 2, _yl ),
  614.   Tlb_list( _list )
  615. {
  616.   init( _data );
  617. }
  618.  
  619. //Tlist_box protected:
  620.  
  621. void Tlist_box::draw( void )
  622. {
  623.   static char t[] = "|r. |n";
  624.   Tlb_item *p;
  625.   uint i, j;
  626.   char ta;
  627.   char s[256];
  628.  
  629.   for( i = 0, j = vbeg_print; i < vmax_print; i++ )
  630.   {
  631.     t[2] = (char) xl;
  632.     if( j >= vcount )
  633.       txt( t );
  634.     else
  635.     {
  636.       p = (*items_ptr)[j++];
  637.       ta = text_attr;
  638.       if( ( i + vbeg_print ) == vcurrent )
  639.         if( state( isSELECTED ) )
  640.           text_attr = selected_attr;
  641.         else
  642.           text_attr = bold_attr;
  643.       else
  644.       {
  645.         if( p->flags & lbfDISABLED ) text_attr = disabled_attr;
  646.         if( p->flags & lbfTITLE ) text_attr = bold_attr;
  647.       }
  648.       if( p->flags & lbfCHECKED )
  649.         txt( "|~√" );
  650.       else
  651.         direct_txt( " " );
  652.       item_str( p, s );
  653.       if( hbeg_print > strlen( s ) )
  654.         *s = 0;
  655.       else
  656.       {
  657.         memmove( s, s + hbeg_print, hmax_print );
  658.         s[hmax_print] = 0;
  659.       }
  660.       direct_txt( s );
  661.       if( strlen( s ) < ( xl - 1 ) ) t[2] = (char) ( xl- strlen( s ) - 1 ); else t[2] = 0;
  662.       txt( t );
  663.       text_attr = ta;
  664.     }
  665.   }
  666. }
  667.  
  668. void Tlist_box::event_handler( Tevent &ev )
  669. {
  670.   static boolean ctrl_down = 0;
  671.   uint i;
  672.  
  673.   Titem::event_handler( ev );
  674.   if( ( ev.code == evCOMMAND ) && ( ev.CMD_CODE == cmDLG_RESET ) && changed )
  675.   {
  676.     h_bar->update();
  677.     v_bar->update();
  678.     changed = 0;
  679.   }
  680.   if( state( isFOCUSED ) )
  681.     switch( ev.code )
  682.     {
  683.       case evKEY_DOWN:
  684.         if( ev.SCAN_CODE == scCTRL ) ctrl_down = 1; break;
  685.       case evKEY_UP:
  686.         if( ev.SCAN_CODE == scCTRL ) ctrl_down = 0; break;
  687.       case evKEY_PRESS:
  688.         i = vcurrent;
  689.         switch( ev.ASCII )
  690.         {
  691.           case kUP:
  692.             up(); break;
  693.           case kDOWN:
  694.             down(); break;
  695.           case kPG_UP:
  696.             pgup(); break;
  697.           case kPG_DN:
  698.             pgdn(); break;
  699.           case kHOME:
  700.             top(); break;
  701.           case kEND:
  702.             bottom(); break;
  703.           case kSPACE:
  704.             if( flags( lfMULTIPLY_SELECTION ) )
  705.               if( ctrl_down )
  706.               {
  707.                 flip( 0 );
  708.                 multi_flip( 0, vcount - 1 );
  709.                 item_acted = this;
  710.               }
  711.               else
  712.               {
  713.                 flip( vcurrent );
  714.                 down();
  715.               }
  716.             break;
  717.           default:
  718.             return;
  719.         }
  720.         handled( ev ); redraw();
  721.         item_acted = this;
  722.         break;
  723. #ifndef NOMOUSE
  724.       case evMOUSE_DOWN:
  725.         if( ev.INSIDE )
  726.         {
  727.           uint j = (uint) -1;
  728.           do
  729.           {
  730.             ev.INSIDE = ( ev.LOCAL_Y >= 0 ) && ( ev.LOCAL_Y < vmax_print );
  731.             if( ev.INSIDE || ( ev.code == evMOUSE_REP ) )
  732.             {
  733.               if( ev.LOCAL_Y >= 0 ) i = ev.LOCAL_Y; else i = 0;
  734.               i = vbeg_print + i;
  735.               if( !ev.INSIDE )
  736.               {
  737.                 if( i > vcurrent ) down(); else up();
  738.                 i = vcurrent;
  739.               }
  740.               if( i >= vcount ) i = vcount - 1;
  741.               if( ( j != i ) && enabled( i ) )
  742.               {
  743.                 if( ( ev.BUTTON == 1 ) && flags( lfMULTIPLY_SELECTION ) )
  744.                   if( ev.code == evMOUSE_DRAG )
  745.                     multi_flip( vcurrent, i );
  746.                   else
  747.                     flip( i );
  748.                 vcurrent = i;
  749.                 redraw();
  750.               }
  751.               if( ev.CLICKS && flags( lfSTOP_MODAL ) &&
  752.                   ( vbeg_print + ev.LOCAL_Y <= vcount ) )
  753.               {
  754.                 stop( cmOK );
  755.                 break;
  756.               }
  757.               j = vcurrent;
  758.             }
  759.           }
  760.           while( get_mouse( ev, evMOUSE_REP|evMOUSE_DRAG ) );
  761.           item_acted = this;
  762.         }
  763. #endif
  764.     }
  765. }
  766.  
  767. void Tlist_box::ok_item( void )
  768. {
  769.   *dta = vcurrent;
  770. }
  771.  
  772. //Tlist_box private:
  773.  
  774. void Tlist_box::init( uint &_data )
  775. {
  776.   set_flags( lfSTOP_MODAL, 1 );
  777.   hmax_print = xl - 2;
  778.   vmax_print = yl;
  779. #ifndef NOMOUSE
  780.   set_events_mask( evMOUSE_REP, 1 );
  781. #endif
  782.   dta = &_data;
  783.   v_bar = NEW( Tvscroll_bar( vmax_print, vcount, vbeg_print ) );
  784.     v_bar->set_flags( sfHANDLE_KEYBOARD, 0 );
  785.     v_bar->max_print = &vmax_print;
  786.   h_bar = NEW( Thscroll_bar( xl, hsize, hbeg_print ) );
  787.     h_bar->set_flags( sfHANDLE_KEYBOARD, 1 );
  788.     h_bar->max_print = &hmax_print;
  789.   put_in( v_bar, xl, 0 );
  790.   put_in( h_bar, 0, yl );
  791.   top();
  792. }
  793.  
  794. //PREFIXES
  795.  
  796. static uint lsize_ = 0;
  797. static void *ldata_ = NULL;
  798. static Tlb_item_killer lkiller_ = NULL;
  799. static Tlb_item_comparator lcomparator_ = NULL;
  800.  
  801. /*
  802.   Description:
  803.     Specify list user data size. Call just before construct list box or
  804.     combo box.
  805.   Entry:
  806.     size: sizeof( user_record ).
  807. */
  808. void _lsize( uint size )
  809. {
  810.   lsize_ = size;
  811. }
  812.  
  813. uint __lsize( void )
  814. {
  815.   uint result;
  816.  
  817.   result = lsize_;
  818.   lsize_ = 0;
  819.   return result;
  820. }
  821.  
  822. /*
  823.   Description:
  824.     Specify user data. Call just before inserting a line in list box or in
  825.     combo box. After that the list will hold not text only but given data as
  826.     well. Before constructing the list or combo box use lsize to specify
  827.     user data size.
  828.   Entry:
  829.     data - user data to insert in the list or combo.
  830. */
  831. void _ldata( void *data )
  832. {
  833.   ldata_ = data;
  834. }
  835.  
  836. void *__ldata( void )
  837. {
  838.   void *result;
  839.  
  840.   result = ldata_;
  841.   ldata_ = NULL;
  842.   return result;
  843. }
  844.  
  845. /*
  846.   Description:
  847.     Specify list item comparator func. This function will be called when
  848.     list is sorting allowing you to produce you own compare. If comparator
  849.     not specified, list is sorted using standard alphabetical comparison.
  850.   Entry:
  851.     _comparator - address of the list item comparator function.
  852. */
  853. void _litem_comparator( Tlb_item_comparator _comparator )
  854. {
  855.   lcomparator_ = _comparator;
  856. }
  857.  
  858. Tlb_item_comparator __litem_comparator( void )
  859. {
  860.   Tlb_item_comparator result;
  861.  
  862.   result = lcomparator_;
  863.   lcomparator_ = NULL;
  864.   return result;
  865. }
  866.  
  867. /*
  868.   Description:
  869.     Specify list item killer func. This function will be called when the
  870.     list needs to free an item, allowing you to dispose some dynamic data
  871.     in list items.
  872.   Entry:
  873.     _killer - address of the list item killer function.
  874. */
  875. void _litem_killer( Tlb_item_killer _killer )
  876. {
  877.   lkiller_ = _killer;
  878. }
  879.  
  880. Tlb_item_killer __litem_killer( void )
  881. {
  882.   Tlb_item_killer result;
  883.  
  884.   result = lkiller_;
  885.   lkiller_ = NULL;
  886.   return result;
  887. }
  888.  
  889.  
  890. //CONSTRUCTORS FOR USE WITH DIALOG BOXES
  891.  
  892. static void insert_list_box( char *t, Tlist_box *l )
  893. {
  894.   Tbox *b;
  895.  
  896.   l->v_bar->set_state( isHIDDEN, 0 );
  897.   b = NEW( Tbox( t, l ) );
  898.   b->resize( b->xl-1, b->yl );
  899.   l->put_in( b, -1, -1 );
  900.   hspace(); vspace();
  901.   put_item( l, b->xl, b->yl - 1 );
  902.   hspaces( -1 );
  903.   return;
  904. }
  905.  
  906. /*
  907.   Description:
  908.     Construct list box and insert it in the dialog box.
  909.   Entry:
  910.     t        - title, shortcut prefix '|~';
  911.     data     - buffer that holds current selection;
  912.     _xl, _yl - bounds of the list box.
  913.   Exit:
  914.     Return pointer to the list box.
  915. */
  916. Tlist_box *list_box( char *t, uint &data, int _xl, int _yl )
  917. {
  918.   Tlist_box *l;
  919.  
  920.   l = NEW( Tlist_box( data, _xl, _yl ) );
  921.   insert_list_box( t, l );
  922.   return l;
  923. }
  924.  
  925. /*
  926.   Description:
  927.     Construct list box and insert it in the dialog box.
  928.   Entry:
  929.     t        - title, shortcut prefix '|~';
  930.     data     - buffer that holds current selection;
  931.     _xl, _yl - bounds of the list box.
  932.     list     - pointer to a pre-constructed list
  933.   Exit:
  934.     Return pointer to the list box.
  935. */
  936. Tlist_box *list_box( char *t, uint &data, int _xl, int _yl, Tlb_list *list )
  937. {
  938.   Tlist_box *l;
  939.  
  940.   l = NEW( Tlist_box( data, _xl, _yl, list ) );
  941.   insert_list_box( t, l );
  942.   return l;
  943. }
  944.  
  945. /*
  946.   Description:
  947.     Construct multiply selection list box and insert it in the dialog box.
  948.   Entry:
  949.     t        - title, shortcut prefix '|~';
  950.     data     - buffer that holds current selection;
  951.     _xl, _yl - bounds of the list box.
  952.   Exit:
  953.     Return pointer to the list box.
  954. */
  955. Tlist_box *mslist_box( char *t, uint &data, int _xl, int _yl )
  956. {
  957.   Tlist_box *l;
  958.  
  959.   l = list_box( t, data, _xl, _yl );
  960.   l->set_flags( lfSTOP_MODAL, 0 ); l->set_flags( lfMULTIPLY_SELECTION, 1 );
  961.   return l;
  962. }
  963.  
  964. /*
  965.   Description:
  966.     Construct multiply selection list box and insert it in the dialog box.
  967.   Entry:
  968.     t        - title, shortcut prefix '|~';
  969.     data     - buffer that holds current selection;
  970.     _xl, _yl - bounds of the list box.
  971.     list     - pointer to a pre-constructed list
  972.   Exit:
  973.     Return pointer to the list box.
  974. */
  975. Tlist_box *mslist_box( char *t, uint &data, int _xl, int _yl, Tlb_list *list )
  976. {
  977.   Tlist_box *l;
  978.  
  979.   l = list_box( t, data, _xl, _yl, list );
  980.   l->set_flags( lfSTOP_MODAL, 0 ); l->set_flags( lfMULTIPLY_SELECTION, 1 );
  981.   return l;
  982. }
  983.