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

  1. //  ____________________________________________________
  2. // |                                                    |
  3. // |  Project:     POWER VIEW INTERFACE                 |
  4. // |  File:        PVCMDGEN.CPP                         |
  5. // |  Compiler:    WPP386 (10.6)                        |
  6. // |                                                    |
  7. // |  Subject:     Command generators                   |
  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_ctype
  16. #define uses_string
  17. #define uses_app
  18. #define uses_cmdgen
  19. #define uses_colors
  20. #define uses_config
  21. #define uses_dc
  22. #define uses_desk
  23. #define uses_help
  24. #define uses_ini
  25. #define uses_system
  26.  
  27. #define DECLARE_PVCMDGEN
  28. #include "PVuses.h"
  29. #undef DECLARE_PVCMDGEN
  30.  
  31. #define SUSPEND_DELAY 10
  32.  
  33. #ifndef NOMAINMENU
  34.  
  35. class Tmain_menu: public Tmenu_bar
  36. {
  37.   public:
  38.     Tmain_menu( void );
  39.  
  40.   protected:
  41.     virtual void calc_bounds( int delta_xl, int delta_yl );
  42. };
  43.  
  44. #endif
  45.  
  46. #ifndef NOLOCALMENU
  47.  
  48. class Tlocal_menu: public Tmenu_box
  49. {
  50.   public:
  51.     Tlocal_menu( Tmenu *_menu );
  52.     virtual void drag( int _x, int _y );
  53.     virtual boolean valid( uint command );
  54.     virtual uint exec( void );
  55.  
  56. #ifndef NOMOUSE
  57.   protected:
  58.     virtual boolean isit_4u( Tevent &ev );
  59.     virtual void event_handler( Tevent &ev );
  60. #endif
  61. };
  62.  
  63. static Tlocal_menu *local_menu = NULL;
  64.  
  65. #endif
  66.  
  67. static int timer_handle = -1;
  68.  
  69. //INTERFACE
  70.  
  71. static inline boolean is_submenu( Tmenu_item *i )
  72. {
  73.   return ( i != NULL ) && ( i->kind == 1 );
  74. }
  75.  
  76. static inline boolean is_valid( Tmenu_item *i )
  77. {
  78.   return ( i != NULL ) && ( i->name != NULL );
  79. }
  80.  
  81. void dispose_menu( Tmenu *p )
  82. {
  83.   Tmenu_item *i, *t;
  84.  
  85.   if( p != NULL )
  86.   {
  87.     i = p->items;
  88.     while( i != NULL )
  89.     {
  90.       if( is_submenu( i ) )
  91.       {
  92.         dispose_menu( i->what.submenu );
  93.         i->what.submenu = NULL;
  94.       }
  95.       t = i;
  96.       i = i->next;
  97.       DELETE( t );
  98.     }
  99.     DELETE( p );
  100.   }
  101. }
  102.  
  103. Tmenu *current_menu = NULL;
  104. Tmenu_item *current_item = NULL;
  105.  
  106. void update_menu( Tmenu *cm, Tmenu_item *ci )
  107. {
  108.   Tmenu_item *i, *t;
  109.  
  110.   current_menu = cm;
  111.   current_item = ci;
  112.   if( cm==NULL || ci==NULL ) return;
  113.   i = ci->next;
  114.   ci->next = NULL;
  115.   while( i != NULL )
  116.   {
  117.     if( is_submenu( i ) )
  118.     {
  119.       dispose_menu( i->what.submenu );
  120.       i->what.submenu = NULL;
  121.     }
  122.     t = i;
  123.     i = i->next;
  124.     DELETE( t );
  125.   }
  126. }
  127.  
  128. void menu( void )
  129. {
  130.   Tmenu *p;
  131.  
  132.   p = NEW( Tmenu );
  133.   p->items=NULL;
  134.   p->old_menu = current_menu;
  135.   p->old_item = current_item;
  136.   p->current = NULL;
  137.   current_menu = p;
  138.   if( current_item != NULL ) current_item->what.submenu = p;
  139.   current_item = NULL;
  140. }
  141.  
  142. Tmenu *endm( void )
  143. {
  144.   Tmenu *p;
  145.  
  146.   p = current_menu;
  147.   current_item = current_menu->old_item;
  148.   current_menu = current_menu->old_menu;
  149.   return p;
  150. }
  151.  
  152. Tmenu_bar *construct_main_menu( Tmenu *m )
  153. {
  154.   dispose_menu( main_menu->menu );
  155.   main_menu->menu = m;
  156.   return main_menu;
  157. }
  158.  
  159. #ifndef NOLOCALMENU
  160. Tmenu_box *construct_local_menu( Tmenu *m )
  161. {
  162.   if( local_menu != NULL ) DELETE( local_menu );
  163.   local_menu = NEW( Tlocal_menu( m ) );
  164.   return local_menu;
  165. }
  166. #endif
  167.  
  168. Tmenu_box *construct_menu_box( Tmenu *m )
  169. {
  170.   return NEW( Tmenu_box( m, NULL ) );
  171. }
  172.  
  173. Tmenu_bar *construct_menu_bar( Tmenu *m, int _xl )
  174. {
  175.   return NEW( Tmenu_bar( m, _xl ) );
  176. }
  177.  
  178. static Tmenu_item *new_item( void )
  179. {
  180.   Tmenu_item *p;
  181.  
  182.   p = NEW( Tmenu_item );
  183.   if( current_item != NULL )
  184.     current_item->next = p;
  185.   else
  186.     current_menu->items = p;
  187. #ifndef NOHELP
  188.   p->help_ctx = __help();
  189. #endif
  190.   p->next = NULL;
  191.   current_item = p;
  192.   return p;
  193. }
  194.  
  195. Tmenu_item *mitem( char *name, uint command )
  196. {
  197.   Tmenu_item *p;
  198.  
  199.   p = mitem( name, "", command );
  200.   p->kind = 0;
  201.   return p;
  202. }
  203.  
  204. Tmenu_item *mitem( char *name, char *param, uint command )
  205. {
  206.   Tmenu_item *p;
  207.  
  208.   p = new_item();
  209.   if( *name == 0 ) p->name = NULL; else p->name = name;
  210.   p->kind = 2;
  211.   p->command = command;
  212.   if( *param == 0 ) p->what.param = NULL; else p->what.param = param;
  213.   return p;
  214. }
  215.  
  216. Tmenu_item *mitem( char *name, uint &_check, uint command )
  217. {
  218.   Tmenu_item *p;
  219.  
  220.   p = mitem( name, "", command );
  221.   p->kind = 3;
  222.   p->what.check = &_check;
  223.   return p;
  224. }
  225.  
  226. Tmenu_item *mitem( void )
  227. {
  228.   Tmenu_item *p;
  229.  
  230.   p = new_item();
  231.   p->name = NULL;
  232.   p->command = 0;
  233.   p->what.param = NULL;
  234.   p->kind = 1;
  235.   return p;
  236. }
  237.  
  238. Tmenu_item *submenu( char *name )
  239. {
  240.   Tmenu_item *p;
  241.  
  242.   p = new_item();
  243.   if( *name == 0 ) p->name = NULL; else p->name = name;
  244.   p->kind = 1;
  245.   p->command = 0;
  246.   menu();
  247.   return p;
  248. }
  249.  
  250. void show_menu_cursor( Tmenu *p )
  251. {
  252.   if( p == NULL ) return;
  253.   p->current = p->items;
  254.   while( !is_valid( p->current ) && ( p->current != NULL ) )
  255.     p->current = p->current->next;
  256. }
  257.  
  258. void show_submenu_cursor( Tmenu_item *p )
  259. {
  260.   if( p == NULL ) return;
  261.   if( is_submenu( p ) ) show_menu_cursor( p->what.submenu );
  262. }
  263.  
  264. static Tmenu_item *get_menu_item_ptr( Tmenu *p, uint command )
  265. {
  266.   Tmenu_item *i;
  267.  
  268.   if( p != NULL )
  269.   {
  270.     i = p->items;
  271.     while( i != NULL )
  272.     {
  273.       if( i->command == command ) return i;
  274.       if( is_submenu( i ) )
  275.       {
  276.         p = (Tmenu *) get_menu_item_ptr( i->what.submenu, command );
  277.         if( p != NULL ) return (Tmenu_item *) p;
  278.       }
  279.       i = i->next;
  280.     }
  281.   }
  282.   return NULL;
  283. }
  284.  
  285. //Tmenu_base publics:
  286.  
  287. Tmenu_base::Tmenu_base( int _xl, int _yl ):
  288.   Titem( _xl, _yl )
  289. {
  290.   set_flags( mfSUSPEND_SELECTION, 1 );
  291.   set_flags( ifSELECTABLE, 0 );
  292.   set_state( isON_TOP, 1 );
  293.   pulled_down = 0;
  294.   shortcut = 0;
  295.   client = NULL;
  296. }
  297.  
  298. Tmenu_base::~Tmenu_base( void )
  299. {
  300.   if( ( menu != NULL ) && ( parent == NULL ) ) dispose_menu( menu );
  301. }
  302.  
  303. uint Tmenu_base::exec( void )
  304. {
  305.   if( owner != NULL ) owner->focus();
  306.   update_commands( menu );
  307.   return Titem::exec();
  308. }
  309.  
  310. //Tmenu_base protected:
  311.  
  312. void Tmenu_base::set_palette( void )
  313. {
  314.   selected_attr = pal_menus.selected;
  315.   disabled_attr = pal_menus.disabled;
  316.   bold_attr = pal_menus.frame;
  317.   text_attr = pal_menus.normal;
  318.   attr[0] = pal_menus.disabled_selected;
  319.   shortcut_attr = pal_menus.shortcut;
  320. }
  321.  
  322. void Tmenu_base::event_handler( Tevent &ev )
  323. {
  324. #ifndef NOHELP
  325.   uint hctx;
  326.   Tmenu_base *pm;
  327. #endif
  328.   Tmenu_item *p;
  329.  
  330.   if( menu != NULL )
  331.   {
  332.     switch( ev.code )
  333.     {
  334.       case evCOMMAND:
  335.         switch( ev.CMD_CODE )
  336.         {
  337.           case cmMENU_CLOSE_SUBMENU:
  338.             if( parent == ev.CMD_INFO )
  339.             {
  340.               handled( ev );
  341.               close_menu();
  342.             }
  343.             break;
  344.           case cmMENU_SELECTION:
  345.             handled( ev );
  346.             if( menu->current == NULL )
  347.               cancelled();
  348.             else
  349.               if( is_submenu( menu->current ) )
  350.                 open_submenu();
  351.               else
  352.                 selection_made();
  353.             break;
  354.           case cmMENU_SELECTION_MADE:
  355.             if( ( menu->current != NULL ) && !is_submenu( menu->current ) )
  356.             {
  357.               if( !menu->current->enabled )
  358.               {
  359.                 handled( ev );
  360.                 break;
  361.               }
  362.               put_command( client, menu->current->command );
  363.             }
  364.           case cmMENU_CANCELLED:
  365.             if( state( isMODAL ) ) stop( ev.CMD_CODE );
  366.             menu->current = NULL;
  367.             close_menu();
  368.             redraw();
  369.             pulled_down = 0;
  370.         }
  371.         break;
  372. #ifndef NOMOUSE
  373.       case evMOUSE_DOWN:
  374.         p = pointed_ptr( ev.LOCAL_X, ev.LOCAL_Y );
  375.         cancel_request( timer_handle );
  376.         close_submenu();
  377.         menu->current = p;
  378.         if( is_submenu( menu->current ) )
  379.         {
  380.           menu->current->what.submenu->current = NULL;
  381.           make_selection();
  382.         }
  383.         if( ev.INSIDE )
  384.         {
  385.           redraw();
  386.           handled( ev );
  387.           if( ( parent == NULL ) && !state( isMODAL ) ) exec();
  388.         }
  389.         else
  390.           if( state( isMODAL ) )
  391.           {
  392.             cancelled();
  393.             put_event( ev );
  394.           }
  395.         break;
  396.       case evMOUSE_REP:
  397.       case evMOUSE_DRAG:
  398.         if( ( parent == NULL ) && !state( isMODAL ) ) return;
  399.         p = pointed_ptr( ev.LOCAL_X, ev.LOCAL_Y );
  400.         if( p != menu->current )
  401.         {
  402.           if( ( p != NULL ) || !pulled_down || ev.INSIDE )
  403.           {
  404.             redraw();
  405.             menu->current = p;
  406.           }
  407.           if( ev.INSIDE )
  408.           {
  409.             cancel_request( timer_handle );
  410.             close_submenu();
  411.             if( is_submenu( menu->current ) )
  412.             {
  413.               menu->current->what.submenu->current = NULL;
  414.               if( flags( mfSUSPEND_SELECTION ) )
  415.                 suspend_selection();
  416.               else
  417.                 make_selection();
  418.             }
  419.           }
  420.         }
  421.         if( ev.INSIDE ) handled( ev );
  422.         break;
  423.       case evMOUSE_UP:
  424.         if( ( parent == NULL ) && !state( isMODAL ) ) return;
  425.         if( ev.INSIDE )
  426.         {
  427.           if( pointed_ptr( ev.LOCAL_X, ev.LOCAL_Y ) == NULL )
  428.           {
  429.             show_menu_cursor( menu );
  430.             redraw();
  431.           }
  432.           else
  433.           {
  434.             if( is_submenu( menu->current ) )
  435.             {
  436.               close_submenu();
  437.               show_submenu_cursor( menu->current );
  438.               cancel_request( timer_handle );
  439.             }
  440.             make_selection();
  441.           }
  442.           handled( ev );
  443.         }
  444.         else
  445.           if( parent == NULL )
  446.           {
  447.             cancelled();
  448.             handled( ev );
  449.           }
  450.         break;
  451. #endif
  452.       case evKEY_PRESS:
  453.         if( !pulled_down )
  454.         {
  455.           if( ( parent != NULL ) || state( isMODAL ) || ( ev.ASCII > 255 ) )
  456.           {
  457.             if( ( ev.ASCII == shortcut ) && !state( isMODAL ) )
  458.             {
  459.               redraw();
  460.               menu->current = menu->items;
  461.               show_menu_cursor( menu );
  462.               handled( ev );
  463.               set_state( isHIDDEN, 0 );
  464.               exec();
  465.             }
  466.             else
  467.             {
  468.               if( !state( isALIVE ) ) return;
  469.               if( ev.ASCII == kESC )
  470.               {
  471.                 handled( ev );
  472.                 if( parent == NULL )
  473.                   cancelled();
  474.                 else
  475.                   close_menu();
  476.               }
  477.               else
  478.               {
  479.                 if( menu->current != NULL )
  480.                 {
  481.                   switch( ev.ASCII )
  482.                   {
  483. #ifndef NOHELP
  484.                     case kF1:
  485.                       pm = this;
  486.                       hctx = 0;
  487.                       do
  488.                       {
  489.                         p = pm->menu->current;
  490.                         if( p == NULL ) continue;
  491.                         hctx = p->help_ctx;
  492.                         pm = pm->parent;
  493.                       }
  494.                       while( ( pm != NULL ) && !hctx );
  495.                       online_help( hctx );
  496.                       break;
  497. #endif
  498.                     case kPG_UP:
  499.                     case kHOME:
  500.                       menu->current = menu->items;
  501.                       show_menu_cursor( menu );
  502.                       redraw();
  503.                       break;
  504.                     case kPG_DN:
  505.                     case kEND:
  506.                       menu->current = menu->items;
  507.                       show_menu_cursor( menu );
  508.                       previous_line();
  509.                       break;
  510.                     case kENTER:
  511.                       make_selection();
  512.                       show_submenu_cursor( menu->current );
  513.                       break;
  514.                     default:
  515.                       goto hot;
  516.                   }
  517.                   handled( ev );
  518.                 }
  519.                 hot:
  520.                 if( ev.code != evNOTHING )
  521.                 {
  522.                   p = shortcut_ptr( ev.ASCII );
  523.                   if( p != NULL )
  524.                   {
  525.                     redraw();
  526.                     menu->current = p;
  527.                     show_submenu_cursor( p );
  528.                     make_selection();
  529.                     if( ( parent == NULL ) && !state( isMODAL ) ) exec();
  530.                     handled( ev );
  531.                   }
  532.                 }
  533.               }
  534.             }
  535.           }
  536.         }
  537.     }
  538.   }
  539.   Titem::event_handler( ev );
  540. }
  541.  
  542. void Tmenu_base::update_commands( Tmenu *m )
  543. {
  544.   Tmenu_item *i;
  545.  
  546.   if( m == NULL ) return;
  547.   i = m->items;
  548.   while( i != NULL )
  549.   {
  550.     i->enabled = cenabled( i->command );
  551.     if( is_submenu( i ) )
  552.       update_commands( i->what.submenu );
  553.     i = i->next;
  554.   }
  555. }
  556.  
  557. Tmenu_item *Tmenu_base::next_line( void )
  558. {
  559.   Tmenu_item *p, *c;
  560.  
  561.   c = menu->current;
  562.   if( c == NULL ) return NULL;
  563.   do
  564.   {
  565.     p = menu->current;
  566.     if( p->next == NULL )
  567.       menu->current = menu->items;
  568.     else
  569.       menu->current = p->next;
  570.   }
  571.   while( !is_valid( menu->current ) && ( menu->current != c ) );
  572.   if( !is_valid( menu->current ) ) menu->current = NULL;
  573.   if( c != menu->current ) redraw();
  574.   return menu->current;
  575. }
  576.  
  577. Tmenu_item *Tmenu_base::previous_line( void )
  578. {
  579.   Tmenu_item *p, *p1, *p2;
  580.  
  581.   p = menu->current;
  582.   if( p == NULL ) return NULL;
  583.   p1 = p;
  584.   do
  585.   {
  586.     p2 = menu->current;
  587.   }
  588.   while( next_line() != p1 );
  589.   menu->current = p2;
  590.   if( p != menu->current ) redraw();
  591.   return p2;
  592. }
  593.  
  594. Tmenu_item *Tmenu_base::shortcut_ptr( uint ascii )
  595. {
  596.   char *p, c1, c2;
  597.   Tmenu_item *i;
  598.  
  599.   if( ( ( parent == NULL ) && !state( isMODAL ) && ( ascii <= 255 ) ) ||
  600.       pulled_down ) return NULL;
  601.   if( ascii>255 )
  602.   {
  603. #ifdef CYR
  604.     ascii = alt2cyr( ascii );
  605. #endif
  606.     ascii = alt2lat( ascii );
  607.   }
  608.   if( ascii )
  609.   {
  610.     i = menu->items;
  611.     while( i != NULL )
  612.     {
  613.       if( i->name != NULL )
  614.       {
  615.         p = i->name;
  616.         do
  617.         {
  618.           if( ( p = strchr( p, '|' ) ) == NULL ) break;
  619.         }
  620.         while( *(++p) != '~' );
  621.         if( ( p != NULL ) && is_valid( i ) )
  622.         {
  623.           c1 = toupper( *(++p) ); c2 = toupper( (char)ascii );
  624. #ifdef CYR
  625.           c1 = cyr_toupper( c1 ); c2 = cyr_toupper( c2 );
  626. #endif
  627.           if( c1 == c2 ) return i;
  628.         }
  629.       }
  630.       i = i->next;
  631.     }
  632.   }
  633.   return NULL;
  634. }
  635.  
  636. void Tmenu_base::suspend_selection( void )
  637. {
  638.   Tevent ev;
  639.  
  640.   ev.code = evCOMMAND;
  641.   ev.CMD_CODE = cmMENU_SELECTION;
  642.   ev.priority = 0;
  643.   ev.destination = this;
  644.   event_request( timer_handle, ev, SUSPEND_DELAY );
  645. }
  646.  
  647. void Tmenu_base::open_submenu( void )
  648. {
  649.   if( pulled_down ) return;
  650.   pulled_down = 1;
  651.   message( this, cmMENU_OPEN_SUBMENU );
  652. }
  653.  
  654. void Tmenu_base::close_submenu( void )
  655. {
  656.   _command_info( this, 0 );
  657.     modal_broadcast( cmMENU_CLOSE_SUBMENU );
  658.   pulled_down = 0;
  659. }
  660.  
  661. void Tmenu_base::close_menu( void )
  662. {
  663.   close_submenu();
  664.   if( parent != NULL ) parent->pulled_down = 0;
  665.   if( flags( ifCLOSEABLE ) ) message( this, cmDONE );
  666. }
  667.  
  668.  
  669. //Tmenu_box publics:
  670.  
  671. static int get_xl( Tmenu *menu )
  672. {
  673.   Tmenu_item *i;
  674.   int xl, l;
  675.  
  676.   xl = 0;
  677.   i = menu->items;
  678.   while( i != NULL )
  679.   {
  680.     if( i->name != NULL )
  681.     {
  682.       l = smart_len( i->name ) + (char) ( ( i->kind == 1 ) << 1 );
  683.       if( i->kind == 2 ) l += ( 2 + smart_len( i->what.param ) );
  684.       if( l > xl ) xl = l;
  685.     }
  686.     i = i->next;
  687.   }
  688.   return xl + 4;
  689. }
  690.  
  691. static int get_yl( Tmenu *menu )
  692. {
  693.   Tmenu_item *i;
  694.   int yl;
  695.  
  696.   yl = 0;
  697.   i = menu->items;
  698.   while( i != NULL )
  699.   {
  700.     yl++;
  701.     i = i->next;
  702.   }
  703.   return yl + 2;
  704. }
  705.  
  706. Tmenu_box::Tmenu_box( Tmenu *_menu, Tmenu_base *_parent ):
  707.   Tmenu_base( get_xl( _menu ), get_yl( _menu ) )
  708. {
  709.   menu = _menu;
  710.   parent = _parent;
  711.   if( parent != NULL ) client = parent->client;
  712. }
  713.  
  714. void Tmenu_box::initialize( void )
  715. {
  716.   int xx, yy;
  717.  
  718.   if( owner != NULL )
  719.   {
  720.     owner->make_global( x, y, xx, yy );
  721.     if( xx < 0 ) xx = 0;
  722.     if( ( xx + xl ) > (int) scr_columns ) xx = scr_columns - xl;
  723.     if( ( yy + yl ) > (int) scr_rows ) yy = scr_rows - yl;
  724.     owner->make_local( xx, yy, xx, yy );
  725.   }
  726.   if( ( xx != x ) || ( yy != y ) ) drag( xx, yy );
  727. }
  728.  
  729. //Tmenu_box protected:
  730.  
  731. void Tmenu_box::draw( void )
  732. {
  733.   char m[3] = " \020";
  734.   Tmenu_item *i;
  735.   char sa;
  736.   char c, s, b;
  737.   char *p;
  738.   boolean f;
  739.  
  740.   if( menu == NULL ) return;
  741.   sa = shortcut_attr;
  742.   i = menu->items;
  743.   c = char( xl-2 );
  744.   txtf( "|b%c|r%c%c%c|n", frame_normal[0], c, frame_normal[1], frame_normal[2] );
  745.   while( i != NULL )
  746.   {
  747.     shortcut_attr = sa;
  748.     if( i->name != NULL )
  749.     {
  750.       f = ( i == menu->current );
  751.       if( !i->command || i->enabled )
  752.       {
  753.         s = 't';
  754.         if( f ) s = 's';
  755.       }
  756.       else
  757.       {
  758.         shortcut_attr = 0;
  759.         s = 'd';
  760.         if( f ) s = '0';
  761.       }
  762.       c = ' '; p = "";
  763.       switch( i->kind )
  764.       {
  765.         case 1:
  766.           p = m; break;
  767.         case 2:
  768.           p = i->what.param; break;
  769.         case 3:
  770.           if( *i->what.check == i->command ) c = '√';
  771.       }
  772.       b = (char) ( xl - smart_len( i->name ) - smart_len( p ) - 4 );
  773.       txtf( "|b%c|%c%c%s|r%c %s |b%c|n", frame_normal[3], s, c, i->name, b, p, frame_normal[5] );
  774.     }
  775.     else
  776.     {
  777.       c = (char) ( xl - 4 );
  778.       txtf( "|b%c |r%c%c |b%c|n", frame_normal[3], c, frame_standard[1], frame_normal[5] );
  779.     }
  780.     i = i->next;
  781.   }
  782.   c = (char) ( xl - 2 );
  783.   txtf( "|b%c|r%c%c%c", frame_normal[6], c, frame_normal[7], frame_normal[8] );
  784. }
  785.  
  786. void Tmenu_box::event_handler( Tevent &ev )
  787. {
  788.   Tmenu_box *b;
  789.   int px, py;
  790.  
  791.   if( menu == NULL ) return;
  792.   if( state( isALIVE ) )
  793.     switch( ev.code )
  794.     {
  795.       case evCOMMAND:
  796.         switch( ev.CMD_CODE )
  797.         {
  798.           case cmMENU_OPEN_SUBMENU:
  799.             if( is_submenu( menu->current ) )
  800.             {
  801.               b = NEW( Tmenu_box( menu->current->what.submenu, this ) );
  802.               px = xl - 2; py = item_y( menu->current ) - 1;
  803.               make_global( px, py, px, py );
  804.               if( ( px + b->xl ) > (int) scr_columns ) px -= xl + b->xl - 4;
  805.               if( ( py + b->yl ) > (int) scr_rows ) py = scr_rows -  b->yl;
  806.               make_local( px, py, px, py );
  807.               put_in( b, px, py );
  808.               handled( ev );
  809.             }
  810.         }
  811.         break;
  812.       case evKEY_PRESS:
  813.         switch( ev.ASCII )
  814.         {
  815.           case kUP:
  816.             previous_line(); break;
  817.           case kDOWN:
  818.             next_line(); break;
  819.           default:
  820.             goto hot;
  821.         }
  822.         handled( ev );
  823.     }
  824. hot:
  825.   Tmenu_base::event_handler( ev );
  826. }
  827.  
  828. #pragma off( unreferenced )
  829. int Tmenu_box::item_x( Tmenu_item *p )
  830. {
  831.   return 1;
  832. }
  833. #pragma on( unreferenced )
  834.  
  835. int Tmenu_box::item_y( Tmenu_item *p )
  836. {
  837.   Tmenu_item *i;
  838.   int iy;
  839.  
  840.   iy = 1;
  841.   i = menu->items;
  842.   while( i != NULL )
  843.   {
  844.     if( i == p ) return iy;
  845.     iy++;
  846.     i = i->next;
  847.   }
  848.   return -1;
  849. }
  850.  
  851. Tmenu_item *Tmenu_box::pointed_ptr( int mx, int my )
  852. {
  853.   Tmenu_item *i;
  854.   int iy;
  855.  
  856.   iy = 0;
  857.   i = menu->items;
  858.   while( i != NULL )
  859.   {
  860.     iy++;
  861.     if( is_valid( i ) && ( mx >= 1 ) && ( mx <= ( xl - 2 ) ) && ( my == iy ) )
  862.       return i;
  863.     i = i->next;
  864.   }
  865.   return NULL;
  866. }
  867.  
  868.  
  869. #ifndef NOLOCALMENU
  870.  
  871. //Tlocal_menu publics:
  872.  
  873. Tlocal_menu::Tlocal_menu( Tmenu *_menu ):
  874.   Tmenu_box( _menu, NULL )
  875. {
  876.   int _x, _y;
  877.  
  878.   set_state( isHIDDEN, 1 );
  879.   set_flags( ifCLOSEABLE, 0 );
  880.   shortcut = kALT_F10;
  881.   application->make_local( desktop_x, desktop_y, _x, _y );
  882.   application->put_in( this, _x, _y );
  883. }
  884.  
  885. void Tlocal_menu::drag( int _x, int _y )
  886. {
  887.   Tmenu_box::drag( _x, _y );
  888.   initialize();
  889. }
  890.  
  891. boolean Tlocal_menu::valid( uint command )
  892. {
  893.   if( command == cmDONE )
  894.   {
  895.     set_state( isHIDDEN, 1 );
  896.     return 0;
  897.   }
  898.   return Tmenu_box::valid( command );
  899. }
  900.  
  901. uint Tlocal_menu::exec( void )
  902. {
  903.   set_state( isHIDDEN, 0 );
  904.   uint result = Tmenu_box::exec();
  905.   set_state( isHIDDEN, 1 );
  906.   return result;
  907. }
  908.  
  909. //Tlocal_menu protected:
  910.  
  911. #ifndef NOMOUSE
  912. boolean Tlocal_menu::isit_4u( Tevent &ev )
  913. {
  914.   if( Tmenu_box::isit_4u( ev ) ) return 1;
  915.   if( state( isHIDDEN ) && ev.code==evMOUSE_DOWN && ev.BUTTON==1 &&
  916.       ev.GLOBAL_Y>=desktop_y && menu!=NULL && menu->items!=NULL ) return 1;
  917.   return 0;
  918. }
  919.  
  920. void Tlocal_menu::event_handler( Tevent &ev )
  921. {
  922.   int xx, yy;
  923.  
  924.   if( state( isHIDDEN ) && ( ev.code == evMOUSE_DOWN ) && ( ev.BUTTON == 1 ) )
  925.   {
  926.     xx = ev.GLOBAL_X; yy = ev.GLOBAL_Y;
  927.     if( ev.GLOBAL_X > ( desktop_x + ( desktop_xl >> 1 ) ) ) xx -= xl - 1;
  928.     if( ev.GLOBAL_Y > ( desktop_y + ( desktop_yl >> 1 ) ) ) yy -= yl - 1;
  929.     if( yy < desktop_y ) yy = desktop_y;
  930.     if( ( xx + xl ) > (int) scr_columns ) xx = scr_columns - xl;
  931.     if( ( yy + yl ) > (int) scr_rows ) yy = scr_rows - yl;
  932.     owner->make_local( xx, yy, xx, yy );
  933.     drag( xx, yy );
  934.     owner->make_global( xx, yy, xx, yy );
  935.     make_local( xx, yy, xx, yy );
  936.     menu->current = pointed_ptr( xx, yy );
  937.     if( is_submenu( menu->current ) )
  938.     {
  939.       menu->current->what.submenu->current = NULL;
  940.       suspend_selection();
  941.     }
  942.     exec();
  943.     handled( ev );
  944.   }
  945.   Tmenu_box::event_handler( ev );
  946. }
  947.  
  948. #endif //NOMOUSE
  949.  
  950. #endif //NOLOCALMENU
  951.  
  952.  
  953. //Tmenu_bar publics:
  954.  
  955. Tmenu_bar::Tmenu_bar( Tmenu *_menu, int _xl ):
  956.   Tmenu_base( _xl, 1 )
  957. {
  958.   set_flags( ifPRE_PROCESS, 1 );
  959.   set_flags( mfSUSPEND_SELECTION+ifCLOSEABLE, 0 );
  960.   parent = NULL;
  961.   menu = _menu;
  962. }
  963.  
  964. //Tmenu_bar protected:
  965.  
  966. void Tmenu_bar::draw( void )
  967. {
  968.   Tmenu_item *i;
  969.   char n, ta, s;
  970.   boolean f;
  971.  
  972.   if( menu == NULL ) return;
  973.   i = menu->items;
  974.   n = 0;
  975.   while( i != NULL )
  976.   {
  977.     ta = shortcut_attr;
  978.     f = ( i == menu->current );
  979.     if( !i->command || i->enabled )
  980.     {
  981.       s = 't';
  982.       if( f ) s = 's';
  983.     }
  984.     else
  985.     {
  986.       shortcut_attr = 0;
  987.       s = 'd';
  988.       if( f ) s = '0';
  989.     }
  990.     txtf( "|%c%s", s, i->name );
  991.     shortcut_attr = ta;
  992.     n += smart_len( i->name );
  993.     i = i->next;
  994.   }
  995.   txtf( "|r%c ", (char) ( xl - n ) );
  996. }
  997.  
  998. void Tmenu_bar::event_handler( Tevent &ev )
  999. {
  1000.   Tmenu_box *b;
  1001.   int px, py;
  1002.   boolean fl;
  1003.  
  1004.   if( menu == NULL ) return;
  1005.   if( state( isALIVE ) )
  1006.     switch( ev.code )
  1007.     {
  1008.       case evCOMMAND:
  1009.         if( ( ev.CMD_CODE == cmMENU_OPEN_SUBMENU ) &&
  1010.             is_submenu( menu->current ) )
  1011.         {
  1012.           b = NEW( Tmenu_box( menu->current->what.submenu, this ) );
  1013.           px = item_x( menu->current ); py = 1;
  1014.           make_global( px, py, px, py );
  1015.           if( ( py + b->yl ) > scr_rows ) py -= b->yl + 1;
  1016.           make_local( px, py, px, py );
  1017.           put_in( b, px, py );
  1018.           handled( ev );
  1019.         }
  1020.         break;
  1021.       case evKEY_PRESS:
  1022.         if( menu->current != NULL )
  1023.         {
  1024.           if( ( ev.ASCII == kLEFT ) || ( ev.ASCII == kRIGHT ) )
  1025.           {
  1026.             if( fl = pulled_down ) close_submenu();
  1027.             if( ev.ASCII == kLEFT )
  1028.               previous_line();
  1029.             else
  1030.               next_line();
  1031.             if( fl )
  1032.             {
  1033.               open_submenu();
  1034.               show_submenu_cursor( menu->current );
  1035.             }
  1036.             handled( ev );
  1037.           }
  1038.         }
  1039.     }
  1040.   Tmenu_base::event_handler( ev );
  1041. }
  1042.  
  1043. int Tmenu_bar::item_x( Tmenu_item *p )
  1044. {
  1045.   Tmenu_item *i;
  1046.   int ix;
  1047.  
  1048.   ix = 0;
  1049.   i = menu->items;
  1050.   while( i != NULL )
  1051.   {
  1052.     if( i==p ) return ix;
  1053.     ix += smart_len( i->name );
  1054.     i = i->next;
  1055.   }
  1056.   return -1;
  1057. }
  1058.  
  1059. #pragma off( unreferenced )
  1060. int Tmenu_bar::item_y( Tmenu_item *p )
  1061. {
  1062.   return 0;
  1063. }
  1064. #pragma on( unreferenced )
  1065.  
  1066. Tmenu_item *Tmenu_bar::pointed_ptr( int mx, int my )
  1067. {
  1068.   Tmenu_item *i;
  1069.   int ix;
  1070.  
  1071.   i = menu->items;
  1072.   while( i != NULL )
  1073.   {
  1074.     ix = item_x( i );
  1075.     if( ( i->name != NULL ) &&
  1076.         ( mx >= ix ) &&
  1077.         ( mx < ( ix + smart_len( i->name ) ) ) &&
  1078.         ( my == item_y( i ) ) &&
  1079.         is_valid( i ) ) return i;
  1080.     i = i->next;
  1081.   }
  1082.   return NULL;
  1083. }
  1084.  
  1085.  
  1086. #if !defined( NOMAINMENU ) || !defined( NOLOCALMENU )
  1087.  
  1088. //Tmain_menu publics:
  1089.  
  1090. Tmain_menu::Tmain_menu( void ):
  1091.   Tmenu_bar( NULL, 1 )
  1092. {
  1093.   shortcut = kF10;
  1094.   grow_mode = gmGROW_HOR;
  1095. }
  1096.  
  1097. //Tmain_menu protected:
  1098.  
  1099. #pragma off( unreferenced )
  1100. void Tmain_menu::calc_bounds( int delta_xl, int delta_yl )
  1101. {
  1102.   drag( desktop_x, desktop_y );
  1103.   desktop_y++;
  1104.   desktop_yl--;
  1105.   resize( application->xl, 1 );
  1106. }
  1107. #pragma on( unreferenced )
  1108.  
  1109. #endif //!defined( NOMAINMENU ) || !defined( NOLOCALMENU )
  1110.  
  1111.  
  1112. #ifndef NOTOOLBAR
  1113.  
  1114. class Ttoolbar: public Titem
  1115. {
  1116.   public:
  1117.     Ttoolbar( void );
  1118.     void reset( void );
  1119.     Tbutton *addtool( char *t, uint cmd );
  1120.     void addkey( uint k, uint cmd );
  1121.  
  1122.   protected:
  1123.     int tool_x;
  1124.     virtual void set_palette( void );
  1125.     virtual void calc_bounds( int delta_xl, int delta_yl );
  1126.     virtual void event_handler( Tevent &ev );
  1127. };
  1128.  
  1129. #endif
  1130.  
  1131. #ifndef NOTOOLBAR
  1132.  
  1133. class Ttool: public Tbutton
  1134. {
  1135.   public:
  1136.     Ttool( char *t, uint cmd );
  1137. };
  1138.  
  1139. //Ttool publics:
  1140.  
  1141. Ttool::Ttool( char *t, uint cmd ):
  1142.   Tbutton( t, cmd )
  1143. {
  1144.   set_flags( bfBROADCAST, 1 ); set_flags( ifSELECTABLE, 0 );
  1145. }
  1146.  
  1147. #endif //NOTOOLBAR
  1148.  
  1149. #ifndef NOTOOLBAR
  1150.  
  1151. //Ttoolbar publics:
  1152.  
  1153. Ttoolbar::Ttoolbar( void ):
  1154.   Titem( 1, 1 )
  1155. {
  1156.   set_flags( ifSELECTABLE, 0 ); set_flags( ifPRE_PROCESS, 1 );
  1157.   backgrnd_attr = pal_windows.tool_normal;
  1158.   set_state( isHIDDEN, toolbar_enabled != cmWINDOW_TOOLBAR );
  1159.   reset();
  1160. }
  1161.  
  1162. void Ttoolbar::reset( void )
  1163. {
  1164.   while( last != NULL ) DELETE( last );
  1165.   redraw();
  1166.   tool_x = 1;
  1167. }
  1168.  
  1169. Tbutton *Ttoolbar::addtool( char *t, uint cmd )
  1170. {
  1171.   Ttool *p;
  1172.  
  1173.   p = NEW( Ttool( t, cmd ) );
  1174.   put_in( p, tool_x, 0 );
  1175.   tool_x += smart_len( p->title ) + 2;
  1176.   set_state( isDISABLED, 0 );
  1177.   if( toolbar_enabled == cmWINDOW_TOOLBAR ) set_state( isHIDDEN, 0 );
  1178.   return p;
  1179. }
  1180.  
  1181. void Ttoolbar::addkey( uint k, uint cmd )
  1182. {
  1183.   Tkey *p;
  1184.  
  1185.   p = NEW( Tkey( k, cmd ) );
  1186.   p->set_flags( ifPRE_PROCESS, 1 );
  1187.   put_in( p, 0, 0 );
  1188.   set_state( isDISABLED, 0 );
  1189. }
  1190.  
  1191. //Ttoolbar protected:
  1192.  
  1193. void Ttoolbar::set_palette( void )
  1194. {
  1195.   text_attr = backgrnd_attr;
  1196.   shortcut_attr = pal_windows.shortcut;
  1197. }
  1198.  
  1199. #pragma off( unreferenced )
  1200. void Ttoolbar::calc_bounds( int delta_xl, int delta_yl )
  1201. {
  1202.   resize( owner->xl, 1 );
  1203.   drag( 0, desktop_y );
  1204.   if( state( isHIDDEN ) ) return;
  1205.   desktop_y++;
  1206.   desktop_yl--;
  1207. }
  1208. #pragma on( unreferenced )
  1209.  
  1210.  
  1211. void Ttoolbar::event_handler( Tevent &ev )
  1212. {
  1213.   boolean h;
  1214.  
  1215.   Titem::event_handler( ev );
  1216.   switch( ev.code )
  1217.   {
  1218.     case evCOMMAND:
  1219.       if( ev.CMD_CODE == cmWINDOW_TOOLBAR )
  1220.       {
  1221.         h = !state( isHIDDEN );
  1222.         set_state( isHIDDEN, h );
  1223.         if( h )
  1224.         {
  1225.           desktop_y--; desktop_yl++;
  1226.           toolbar_enabled = 0;
  1227.         }
  1228.         else
  1229.         {
  1230.           desktop_yl--; desktop_y++;
  1231.           toolbar_enabled = cmWINDOW_TOOLBAR;
  1232.         }
  1233.         desktop->drag( desktop_x, desktop_y );
  1234.         desktop->resize( desktop_xl, desktop_yl );
  1235.         handled( ev );
  1236.       }
  1237.   }
  1238. }
  1239.  
  1240. #endif //NOTOOLBAR
  1241.  
  1242. //INTERFACE
  1243.  
  1244. static Tcontext_handler current_context_handler = NULL;
  1245. static int current_context = 0;
  1246.  
  1247. #ifndef NOTOOLBAR
  1248.  
  1249. void construct_toolbar( void )
  1250. {
  1251.   ( (Ttoolbar *) toolbar )->reset();
  1252. }
  1253.  
  1254. #endif
  1255.  
  1256. #ifndef NOTOOLBAR
  1257.  
  1258. Tbutton *add_tool( char *t, uint cmd, uint key )
  1259. {
  1260.   Tbutton *b;
  1261.  
  1262.   b = add_tool( t, cmd );
  1263.   b->shortcut = key;
  1264.   return b;
  1265. }
  1266.  
  1267. Tbutton *add_tool( char *t, uint cmd )
  1268. {
  1269.   return ( (Ttoolbar *) toolbar )->addtool( t, cmd );
  1270. }
  1271.  
  1272. void add_tool( uint cmd, uint key )
  1273. {
  1274.   ( (Ttoolbar *) toolbar )->addkey( key, cmd );
  1275. }
  1276.  
  1277. #endif //NOTOOLBAR
  1278.  
  1279. void install_context_handler( Tcontext_handler ctxhnd )
  1280. {
  1281.   current_context_handler = ctxhnd;
  1282. }
  1283.  
  1284. void set_context( int context )
  1285. {
  1286.   if( ( current_context_handler != NULL ) && context && ( context != current_context ) )
  1287.   {
  1288. #ifndef NOLOCALMENU
  1289.     DELETE( local_menu );
  1290.     local_menu = NULL;
  1291. #endif
  1292.     current_context_handler( context );
  1293.     current_context = context;
  1294.   }
  1295. }
  1296.  
  1297. void update_context( void )
  1298. {
  1299.   if( ( current_context_handler != NULL ) && current_context )
  1300.   {
  1301. #ifndef NOLOCALMENU
  1302.     DELETE( local_menu );
  1303.     local_menu = NULL;
  1304. #endif
  1305.     current_context_handler( current_context );
  1306.   }
  1307. }
  1308.  
  1309. #if !defined( NOCONFIG ) && !defined( NOTOOLBAR )
  1310. static void read_params( void )
  1311. {
  1312.   boolean x;
  1313.  
  1314.   seek_section( 0, SECTION_DESKTOP );
  1315. #ifndef NOTOOLBAR
  1316.   ini( VAR_TOOLBAR, x, 1 );
  1317.     if( x ) toolbar_enabled = cmWINDOW_TOOLBAR; else toolbar_enabled = 0;
  1318. #endif
  1319. }
  1320. #endif
  1321.  
  1322. void global_key( uint cmd, uint key )
  1323. {
  1324.   local_key( application, cmd, key );
  1325. }
  1326.  
  1327. void local_key( Titem *p, uint cmd, uint key )
  1328. {
  1329.   Tkey *k;
  1330.  
  1331.   k = NEW( Tkey( key, cmd ) );
  1332.   k->set_flags( ifPRE_PROCESS, 1 );
  1333.   p->put_in( k, 0, 0 );
  1334. }
  1335.  
  1336. void __init_cmdgen( void )
  1337. {
  1338.  
  1339. //init tools
  1340. #if !defined( NOTOOLBAR ) && !defined( NOCONFIG )
  1341.   read_params();
  1342. #endif
  1343.  
  1344. #ifndef NOTOOLBAR
  1345.   toolbar = NEW( Ttoolbar );
  1346.   application->put_in( toolbar, 0, 0 );
  1347. #endif
  1348.  
  1349. //init menu
  1350.   timer_handle = alloc_timer();
  1351. #if !defined( NOMAINMENU ) || !defined( NOLOCALMENU )
  1352.   main_menu = NEW( Tmain_menu );
  1353.   application->put_in( main_menu, 0, 0 );
  1354. #endif
  1355. }
  1356.