home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 9.ddi / TVSRC.ZIP / TMNUVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  16.1 KB  |  574 lines

  1. /*------------------------------------------------------------*/
  2. /* filename -       tmnuview.cpp                              */
  3. /*                                                            */
  4. /* function(s)                                                */
  5. /*                  TMenuView member functions                */
  6. /*------------------------------------------------------------*/
  7.  
  8. /*------------------------------------------------------------*/
  9. /*                                                            */
  10. /*    Turbo Vision -  Version 1.0                             */
  11. /*                                                            */
  12. /*                                                            */
  13. /*    Copyright (c) 1991 by Borland International             */
  14. /*    All Rights Reserved.                                    */
  15. /*                                                            */
  16. /*------------------------------------------------------------*/
  17.  
  18. #define Uses_TMenuItem
  19. #define Uses_TMenu
  20. #define Uses_TMenuView
  21. #define Uses_TKeys
  22. #define Uses_TRect
  23. #define Uses_TEvent
  24. #define Uses_TGroup
  25. #define Uses_TMenuBox
  26. #define Uses_opstream
  27. #define Uses_ipstream
  28. #include <tv.h>
  29.  
  30. #if !defined( __ASSERT_H )
  31. #include <Assert.h>
  32. #endif  // __ASSERT_H
  33.  
  34. #if !defined( __CTYPE_H )
  35. #include <ctype.h>
  36. #endif  // __CTYPE_H
  37.  
  38. #if !defined( __STRING_H )
  39. #include <String.h>
  40. #endif  // __STRING_H
  41.  
  42. #define cpMenuView "\x02\x03\x04\x05\x06\x07"
  43.  
  44. TMenuItem::TMenuItem(   const char *aName,
  45.                         ushort aCommand,
  46.                         ushort aKeyCode,
  47.                         ushort aHelpCtx,
  48.                         char *p,
  49.                         TMenuItem *aNext
  50.              )
  51. {
  52.     name = newStr( aName );
  53.     command = aCommand;
  54.     disabled = Boolean(!TView::commandEnabled(command));
  55.     keyCode = aKeyCode;
  56.     helpCtx = aHelpCtx;
  57.     if( p == 0 )
  58.         param = 0;
  59.     else
  60.         param = newStr( p );
  61.     next = aNext;
  62. }
  63.  
  64. TMenuItem::TMenuItem( const char *aName,
  65.                       ushort aKeyCode,
  66.                       TMenu *aSubMenu,
  67.                       ushort aHelpCtx,
  68.                       TMenuItem *aNext
  69.                     )
  70. {
  71.     name = newStr( aName );
  72.     command = 0;
  73.     disabled = Boolean(!TView::commandEnabled(command));
  74.     keyCode = aKeyCode;
  75.     helpCtx = aHelpCtx;
  76.     subMenu = aSubMenu;
  77.     next = aNext;
  78. }
  79.  
  80. TMenuItem::~TMenuItem()
  81. {
  82.     delete (char *)name;
  83.     if( command == 0 )
  84.         delete subMenu;
  85.     else
  86.         delete (char *)param;
  87. }
  88.  
  89. TMenu::~TMenu()
  90. {
  91.     while( items != 0 )
  92.         {
  93.         TMenuItem *temp = items;
  94.         items = items->next;
  95.         delete temp;
  96.         }
  97. }
  98.  
  99. void TMenuView::trackMouse( TEvent& e )
  100. {
  101.     TPoint mouse = makeLocal( e.mouse.where );
  102.     for( current = menu->items; current != 0; current = current->next )
  103.         {
  104.         TRect r = getItemRect( current );
  105.         if( r.contains(mouse) )
  106.             return;
  107.         }
  108. }
  109.  
  110. void TMenuView::nextItem()
  111. {
  112.     if( (current = current->next) == 0 )
  113.         current = menu->items;
  114. }
  115.  
  116. void TMenuView::prevItem()
  117. {
  118.     TMenuItem *p;
  119.  
  120.     if( (p = current) == menu->items)
  121.         p = 0;
  122.  
  123.     do  {
  124.         nextItem();
  125.         } while( current->next != p );
  126. }
  127.  
  128. void TMenuView::trackKey( Boolean findNext )
  129. {
  130.     if( current == 0 )
  131.         return;
  132.  
  133.     do  {
  134.         if( findNext )
  135.             nextItem();
  136.         else
  137.             prevItem();
  138.         } while( current->name == 0 );
  139. }
  140.  
  141. Boolean TMenuView::mouseInOwner( TEvent& e )
  142. {
  143.     if( parentMenu == 0 || parentMenu->size.y != 1 )
  144.         return False;
  145.     else
  146.         {
  147.         TPoint mouse = parentMenu->makeLocal( e.mouse.where );
  148.         TRect r = parentMenu->getItemRect( parentMenu->current );
  149.         return r.contains( mouse );
  150.         }
  151. }
  152.  
  153. Boolean TMenuView::mouseInMenus( TEvent& e )
  154. {
  155.     TMenuView *p =  parentMenu;
  156.     while( p != 0 && !p->mouseInView(e.mouse.where) )
  157.         p = p->parentMenu;
  158.  
  159.     return Boolean( p != 0 );
  160. }
  161.  
  162. TMenuView *TMenuView::topMenu()
  163. {
  164.     TMenuView *p = this;
  165.     while( p->parentMenu != 0 )
  166.         p = p->parentMenu;
  167.     return p;
  168. }
  169.  
  170. enum menuAction { doNothing, doSelect, doReturn };
  171.  
  172. ushort TMenuView::execute()
  173. {
  174.     Boolean    autoSelect = False;
  175.     menuAction action;
  176.     char   ch;
  177.     ushort result = 0;
  178.     TMenuItem *itemShown = 0;
  179.     TMenuItem *p;
  180.     TMenuView *target;
  181.     TRect  r;
  182.     TEvent e;
  183.  
  184.     current = menu->deflt;
  185.     do  {
  186.         action = doNothing;
  187.         getEvent(e);
  188.         switch (e.what)
  189.             {
  190.             case  evMouseDown:
  191.                 if( mouseInView(e.mouse.where) || mouseInOwner(e) )
  192.                     {
  193.                     trackMouse(e);
  194.                     if( size.y == 1 )
  195.                         autoSelect = True;
  196.                     }
  197.                 else
  198.                     action =  doReturn;
  199.                 break;
  200.             case  evMouseUp:
  201.                 trackMouse(e);
  202.                 if( mouseInOwner(e) )
  203.                     current = menu->deflt;
  204.                 else if( current != 0 && current->name != 0 )
  205.                     action = doSelect;
  206.                 else
  207.                     action = doReturn;
  208.                 break;
  209.             case  evMouseMove:
  210.                 if( e.mouse.buttons != 0 )
  211.                     {
  212.                     trackMouse(e);
  213.                     if( !(mouseInView(e.mouse.where) || mouseInOwner(e)) &&
  214.                         mouseInMenus(e) )
  215.                         action = doReturn;
  216.                     }
  217.                 break;
  218.             case  evKeyDown:
  219.                 switch( ctrlToArrow(e.keyDown.keyCode) )
  220.                     {
  221.                     case  kbUp:
  222.                     case  kbDown:
  223.                         if( size.y != 1 )
  224.                             trackKey(Boolean(ctrlToArrow(e.keyDown.keyCode) == kbDown));
  225.                         else if( e.keyDown.keyCode == kbDown )
  226.                             autoSelect =  True;
  227.                         break;
  228.                     case  kbLeft:
  229.                     case  kbRight:
  230.                         if( parentMenu == 0 )
  231.                             trackKey(Boolean(ctrlToArrow(e.keyDown.keyCode) == kbRight));
  232.                         else
  233.                             action =  doReturn;
  234.                         break;
  235.                     case  kbHome:
  236.                     case  kbEnd:
  237.                         if( size.y != 1 )
  238.                             {
  239.                             current = menu->items;
  240.                             if( e.keyDown.keyCode == kbEnd )
  241.                                 trackKey(False);
  242.                             }
  243.                         break;
  244.                     case  kbEnter:
  245.                         if( size.y == 1 )
  246.                             autoSelect =  True;
  247.                         action = doSelect;
  248.                         break;
  249.                     case  kbEsc:
  250.                         action = doReturn;
  251.                         if( parentMenu == 0 || parentMenu->size.y != 1 )
  252.                             clearEvent(e);
  253.                         break;
  254.                     default:
  255.                         target = this;
  256.                         ch = getAltChar(e.keyDown.keyCode);
  257.                         if( ch == 0 )
  258.                             ch = e.keyDown.charScan.charCode;
  259.                         else
  260.                             target = topMenu();
  261.                         p = target->findItem(ch);
  262.                         if( p == 0 )
  263.                             {
  264.                             p = topMenu()->hotKey(e.keyDown.keyCode);
  265.                             if( p != 0 && commandEnabled(p->command) )
  266.                                 {
  267.                                 result = p->command;
  268.                                 action = doReturn;
  269.                                 }
  270.                             }
  271.                         else if( target == this )
  272.                             {
  273.                             if( size.y == 1 )
  274.                                 autoSelect = True;
  275.                             action = doSelect;
  276.                             current = p;
  277.                             }
  278.                         else if( parentMenu != target ||
  279.                                  parentMenu->current != p )
  280.                                 action = doReturn;
  281.                     }
  282.                 break;
  283.             case  evCommand:
  284.                 if( e.message.command == cmMenu )
  285.                     {
  286.                     autoSelect = False;
  287.                     if (parentMenu != 0 )
  288.                         action = doReturn;
  289.                     }
  290.                 else
  291.                     action = doReturn;
  292.                 break;
  293.             }
  294.  
  295.         if( itemShown != current )
  296.             {
  297.             itemShown =  current;
  298.             drawView();
  299.             }
  300.  
  301.         if( (action == doSelect || (action == doNothing && autoSelect)) &&
  302.             current != 0 &&
  303.             current->name != 0 )
  304.                 if( current->command == 0 )
  305.                     {
  306.                     if( (e.what & (evMouseDown | evMouseMove)) != 0 )
  307.                         putEvent(e);
  308.                     r = getItemRect( current );
  309.                     r.a.x = r.a.x + origin.x;
  310.                     r.a.y = r.b.y + origin.y;
  311.                     r.b = owner->size;
  312.                     if( size.y == 1 )
  313.                         r.a.x--;
  314.                     target = topMenu()->newSubView(r, current->subMenu,this);
  315.                     result = owner->execView(target);
  316.                     destroy( target );
  317.                     }
  318.                 else if( action == doSelect )
  319.                     result = current->command;
  320.  
  321.         if( result != 0 && commandEnabled(result) )
  322.             {
  323.             action =  doReturn;
  324.             clearEvent(e);
  325.             }
  326.         } while( action != doReturn );
  327.  
  328.     if( e.what != evNothing &&
  329.         (parentMenu != 0 || e.what == evCommand))
  330.             putEvent(e);
  331.     if( current != 0 )
  332.         {
  333.         menu->deflt = current;
  334.         current = 0;
  335.         drawView();
  336.         }
  337.     return result;
  338. }
  339.  
  340. TMenuItem *TMenuView::findItem( char ch )
  341. {
  342.     ch = toupper(ch);
  343.     TMenuItem *p = menu->items;
  344.     while( p != 0 )
  345.         {
  346.         if( p->name != 0 && !p->disabled )
  347.             {
  348.             char *loc = strchr( p->name, '~' );
  349.             if( loc != 0 && (uchar)ch == toupper( loc[1] ) )
  350.                 return p;
  351.             }
  352.         p =  p->next;
  353.         }
  354.     return 0;
  355. }
  356.  
  357. TRect TMenuView::getItemRect( TMenuItem * )
  358. {
  359.     return TRect( 0, 0, 0, 0 );
  360. }
  361.  
  362. ushort TMenuView::getHelpCtx()
  363. {
  364.     TMenuView *c = this;
  365.  
  366.     while( c != 0 &&
  367.                 (c->current == 0 || 
  368.                  c->current->helpCtx == hcNoContext ||
  369.                  c->current->name == 0 )
  370.          )
  371.         c = c->parentMenu;
  372.  
  373.     if( c != 0 )
  374.         return c->current->helpCtx;
  375.     else
  376.         return hcNoContext;
  377. }
  378.  
  379. TPalette& TMenuView::getPalette() const
  380. {
  381.     static TPalette palette( cpMenuView, sizeof( cpMenuView )-1 );
  382.     return palette;
  383. }
  384.  
  385. Boolean TMenuView::updateMenu( TMenu *menu )
  386. {
  387.     Boolean res = False;
  388.     for( TMenuItem *p = menu->items; p != 0; p = p->next )
  389.         {
  390.         if( p->name != 0 )
  391.             if( p->command == 0 )
  392.                 {
  393.                 if (updateMenu(p->subMenu) == True)
  394.                     res = True;
  395.                 }
  396.             else
  397.                 {
  398.                 Boolean commandState = commandEnabled(p->command);
  399.                 if( p->disabled == commandState )
  400.                     {
  401.                     p->disabled = Boolean(!commandState);
  402.                     res = True;
  403.                     }
  404.                 }
  405.         }
  406.     return res;
  407. }
  408.  
  409. void TMenuView::do_a_select( TEvent& event )
  410. {
  411.     putEvent( event );
  412.     event.message.command = owner->execView(this);
  413.     if( event.message.command != 0 && commandEnabled(event.message.command) )
  414.         {
  415.         event.what = evCommand;
  416.         event.message.infoPtr = 0;
  417.         putEvent(event);
  418.         }
  419.     clearEvent(event);
  420. }
  421.  
  422. void TMenuView::handleEvent( TEvent& event )
  423. {
  424.     if( menu != 0 )
  425.         switch (event.what)
  426.             {
  427.             case  evMouseDown:
  428.                 do_a_select(event);
  429.                 break;
  430.             case  evKeyDown:
  431.                 if( findItem(getAltChar(event.keyDown.keyCode)) != 0 )
  432.                     do_a_select(event);
  433.                 else
  434.                     {
  435.                     TMenuItem *p = hotKey(event.keyDown.keyCode);
  436.                     if( p != 0 && commandEnabled(p->command))
  437.                         {
  438.                         event.what = evCommand;
  439.                         event.message.command = p->command;
  440.                         event.message.infoPtr = 0;
  441.                         putEvent(event);
  442.                         clearEvent(event);
  443.                         }
  444.                     }
  445.                 break;
  446.             case  evCommand:
  447.                 if( event.message.command == cmMenu )
  448.                     do_a_select(event);
  449.                 break;
  450.             case  evBroadcast:
  451.                 if( event.message.command == cmCommandSetChanged )
  452.                     {
  453.                     if( updateMenu(menu) )
  454.                         drawView();
  455.                     }
  456.                 break;
  457.             }
  458. }
  459.  
  460.  
  461. TMenuItem *TMenuView::findHotKey( TMenuItem *p, ushort keyCode )
  462. {
  463.  
  464.     while( p != 0 )
  465.         {
  466.         if( p->name != 0 )
  467.             if( p->command == 0 )
  468.                 {
  469.                 TMenuItem *T;
  470.                 if( (T = findHotKey( p->subMenu->items, keyCode )) != 0 )
  471.                     return T;
  472.                 }
  473.             else if( !p->disabled &&
  474.                      p->keyCode != kbNoKey &&
  475.                      p->keyCode == keyCode
  476.                    )
  477.                 return p;
  478.         p =  p->next;
  479.         }
  480.     return 0;
  481. }
  482.  
  483. TMenuItem *TMenuView::hotKey( ushort keyCode )
  484. {
  485.     return findHotKey( menu->items, keyCode );
  486. }
  487.  
  488. TMenuView *TMenuView::newSubView( const TRect& bounds,
  489.                                   TMenu *aMenu,
  490.                                   TMenuView *aParentMenu
  491.                                )
  492. {
  493.     return new TMenuBox( bounds, aMenu, aParentMenu );
  494. }
  495.  
  496. void TMenuView::writeMenu( opstream& os, TMenu *menu )
  497. {
  498.     uchar tok = 0xFF;
  499.     for( TMenuItem *item = menu->items; item != 0; item = item->next )
  500.         {
  501.         os << tok;
  502.         os.writeString( item->name );
  503.         os << item->command << (int)(item->disabled)
  504.            << item->keyCode << item->helpCtx;
  505.         if( item->name != 0 )
  506.             {
  507.             if( item->command == 0 )
  508.                 writeMenu( os, item->subMenu );
  509.             else
  510.                 os.writeString( item->param );
  511.             }
  512.         }
  513.     tok = 0;
  514.     os << tok;
  515. }
  516.  
  517. void TMenuView::write( opstream& os )
  518. {
  519.     TView::write( os );
  520.     writeMenu( os, menu );
  521. }
  522.  
  523. TMenu *TMenuView::readMenu( ipstream& is )
  524. {
  525.     TMenu *menu = new TMenu;
  526.     TMenuItem **last = &(menu->items);
  527.     TMenuItem *item = 0;
  528.     uchar tok;
  529.     is >> tok;
  530.     while( tok != 0 )
  531.         {
  532.         assert( tok == 0xFF );
  533.         item = new TMenuItem( 0, 0, (void *)0 );
  534.         *last = item;
  535.         last = &(item->next);
  536.         item->name = is.readString();
  537.         int temp;
  538.         is >> item->command >> temp
  539.            >> item->keyCode >> item->helpCtx;
  540.         item->disabled = Boolean( temp );
  541.         if( item->name != 0 )
  542.             {
  543.             if( item->command == 0 )
  544.                 item->subMenu = readMenu( is );
  545.             else
  546.                 item->param = is.readString();
  547.             }
  548.         is >> tok;
  549.         }
  550.     *last = 0;
  551.     menu->deflt = menu->items;
  552.     return menu;
  553. }
  554.  
  555. void *TMenuView::read( ipstream& is )
  556. {
  557.     TView::read( is );
  558.     menu = readMenu( is );
  559.     parentMenu = 0;
  560.     current = 0;
  561.     return this;
  562. }
  563.  
  564. TStreamable *TMenuView::build()
  565. {
  566.     return new TMenuView( streamableInit );
  567. }
  568.  
  569. TMenuView::TMenuView( StreamableInit ) : TView( streamableInit )
  570. {
  571. }
  572.  
  573.  
  574.