home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tv20os2.zip / src / TView.cpp < prev    next >
C/C++ Source or Header  |  1998-07-21  |  18KB  |  805 lines

  1. /*
  2.  * TView.cc
  3.  *
  4.  * Turbo Vision - Version 2.0
  5.  *
  6.  * Copyright (c) 1994 by Borland International
  7.  * All Rights Reserved.
  8.  *
  9.  * Modified by Sergio Sigala <ssigala@globalnet.it>
  10.  */
  11.  
  12. #define Uses_TKeys
  13. #define Uses_TView
  14. #define Uses_TCommandSet
  15. #define Uses_TPoint
  16. #define Uses_TGroup
  17. #define Uses_TRect
  18. #define Uses_TEvent
  19. #define Uses_opstream
  20. #define Uses_ipstream
  21. #include <tvision/tv.h>
  22.  
  23. #include <limits.h>
  24.  
  25. TPoint shadowSize = {2,1};
  26. uchar shadowAttr = 0x08;
  27. Boolean TView::showMarkers = False;
  28. uchar TView::errorAttr = 0xCF;
  29. Boolean TView::commandSetChanged = False;
  30.  
  31. extern TView *TheTopView;
  32.  
  33. static TCommandSet initCommands()
  34. {
  35.     TCommandSet temp;
  36.     for( int i = 0; i < 256; i++ )
  37.         temp.enableCmd( i );
  38.     temp.disableCmd( cmZoom );
  39.     temp.disableCmd( cmClose );
  40.     temp.disableCmd( cmResize );
  41.     temp.disableCmd( cmNext );
  42.     temp.disableCmd( cmPrev );
  43.     return temp;
  44. }
  45.  
  46. TCommandSet TView::curCommandSet = initCommands();
  47.  
  48. TView::TView( const TRect& bounds) :
  49.     owner( 0 ), next( 0 ), options( 0 ), state( sfVisible ),
  50.     growMode( 0 ), dragMode( dmLimitLoY ), helpCtx( hcNoContext ),
  51.     eventMask( evMouseDown | evKeyDown | evCommand )
  52. {
  53.     setBounds( bounds);
  54.     cursor.x = cursor.y = 0;
  55. }
  56.  
  57. TView::~TView()
  58. {
  59. }
  60.  
  61. void TView::awaken()
  62. {
  63. }
  64.  
  65. void TView::blockCursor()
  66. {
  67.      setState(sfCursorIns, True);
  68. }
  69.  
  70. #define grow(i) (( (growMode & gfGrowRel)) ? \
  71.                 (i = (i * s + ((s - d) >> 1)) / (s - d)) : (i += d))
  72.  
  73. inline int range( int val, int min, int max )
  74. {
  75.     if( val < min )
  76.         return min;
  77.     else if( val > max )
  78.         return max;
  79.     else
  80.         return val;
  81. }
  82.  
  83. void TView::calcBounds( TRect& bounds, TPoint delta )
  84. {
  85.     bounds = getBounds();
  86.  
  87.     short s = owner->size.x;
  88.     short d = delta.x;
  89.  
  90.     if( (growMode & gfGrowLoX) != 0 )
  91.         grow(bounds.a.x);
  92.  
  93.     if( (growMode & gfGrowHiX) != 0 )
  94.         grow(bounds.b.x);
  95.  
  96.     s = owner->size.y;
  97.     d = delta.y;
  98.  
  99.     if( (growMode & gfGrowLoY) != 0 )
  100.         grow(bounds.a.y);
  101.  
  102.     if( (growMode & gfGrowHiY) != 0 )
  103.         grow(bounds.b.y);
  104.  
  105.     TPoint minLim, maxLim;
  106.     sizeLimits( minLim, maxLim );
  107.     bounds.b.x = bounds.a.x + range( bounds.b.x-bounds.a.x, minLim.x, maxLim.x );
  108.     bounds.b.y = bounds.a.y + range( bounds.b.y-bounds.a.y, minLim.y, maxLim.y );
  109. }
  110.  
  111. void TView::changeBounds( const TRect& bounds )
  112. {
  113.     setBounds(bounds);
  114.     drawView();
  115. }
  116.  
  117. void TView::clearEvent( TEvent& event )
  118. {
  119.     event.what = evNothing;
  120.     event.message.infoPtr = this;
  121. }
  122.  
  123. Boolean TView::commandEnabled( ushort command )
  124. {
  125.     return Boolean((command > 255) || curCommandSet.has(command));
  126. }
  127.  
  128. ushort TView::dataSize()
  129. {
  130.     return 0;
  131. }
  132.  
  133. void TView::disableCommands( TCommandSet& commands )
  134. {
  135.     commandSetChanged = Boolean( commandSetChanged ||
  136.                                 !(curCommandSet & commands).isEmpty());
  137.     curCommandSet.disableCmd(commands);
  138. }
  139.  
  140. void TView::disableCommand( ushort command )
  141. {
  142.     commandSetChanged = Boolean( commandSetChanged ||
  143.                                  curCommandSet.has(command) );
  144.     curCommandSet.disableCmd(command);
  145. }
  146.  
  147. void TView::moveGrow( TPoint p,
  148.                       TPoint s,
  149.                       TRect& limits,
  150.                       TPoint minSize,
  151.                       TPoint maxSize,
  152.                       uchar mode
  153.                     )
  154. {
  155.     TRect   r;
  156.     s.x = min(max(s.x, minSize.x), maxSize.x);
  157.     s.y = min(max(s.y, minSize.y), maxSize.y);
  158.     p.x = min(max(p.x, limits.a.x - s.x+1), limits.b.x-1);
  159.     p.y = min(max(p.y, limits.a.y - s.y+1), limits.b.y-1);
  160.  
  161.     if( (mode & dmLimitLoX) != 0 )
  162.         p.x = max(p.x, limits.a.x);
  163.     if( (mode & dmLimitLoY) != 0 )
  164.         p.y = max(p.y, limits.a.y);
  165.     if( (mode & dmLimitHiX) != 0 )
  166.         p.x = min(p.x, limits.b.x-s.x);
  167.     if( (mode & dmLimitHiY) != 0 )
  168.         p.y = min(p.y, limits.b.y-s.y);
  169.     r = TRect(p.x, p.y, p.x +  s.x, p.y +  s.y);
  170.     locate(r);
  171. }
  172.  
  173. void TView::change( uchar mode, TPoint delta, TPoint& p, TPoint& s, ulong ctrlState )
  174. {
  175.     if( (mode & dmDragMove) != 0 && (ctrlState & kbShift) == 0 )
  176.         p += delta;
  177.     else if( (mode & dmDragGrow) != 0 && (ctrlState & kbShift) != 0 )
  178.         s += delta;
  179. }
  180.  
  181. void TView::dragView( TEvent& event,
  182.                       uchar mode,
  183.                       TRect& limits,
  184.                       TPoint minSize,
  185.                       TPoint maxSize
  186.                     )
  187. {
  188.     TRect saveBounds;
  189.  
  190.     TPoint p, s;
  191.     setState( sfDragging, True );
  192.  
  193.     if( event.what == evMouseDown )
  194.         {
  195.         if( (mode & dmDragMove) != 0 )
  196.             {
  197.             p = origin - event.mouse.where;
  198.             do  {
  199.                 event.mouse.where += p;
  200.                 moveGrow( event.mouse.where,
  201.                           size,
  202.                           limits,
  203.                           minSize,
  204.                           maxSize,
  205.                           mode
  206.                         );
  207.                 } while( mouseEvent(event,evMouseMove) );
  208.             }
  209.         else
  210.             {
  211.             p = size - event.mouse.where;
  212.             do  {
  213.                 event.mouse.where += p;
  214.                 moveGrow( origin,
  215.                           event.mouse.where,
  216.                           limits,
  217.                           minSize,
  218.                           maxSize,
  219.                           mode
  220.                         );
  221.                 } while( mouseEvent(event,evMouseMove) );
  222.             }
  223.         }
  224.     else
  225.         {
  226.         static TPoint
  227.             goLeft      =   {-1, 0},
  228.             goRight     =   { 1, 0},
  229.             goUp        =   { 0,-1},
  230.             goDown      =   { 0, 1},
  231.             goCtrlLeft  =   {-8, 0},
  232.             goCtrlRight =   { 8, 0};
  233.  
  234.         saveBounds = getBounds();
  235.         do  {
  236.             p = origin;
  237.             s = size;
  238.             keyEvent(event);
  239.             switch (event.keyDown.keyCode & 0xFF00)
  240.                 {
  241.                 case kbLeft:
  242.                     change(mode,goLeft,p,s,event.keyDown.controlKeyState);
  243.                     break;
  244.                 case kbRight:
  245.                     change(mode,goRight,p,s,event.keyDown.controlKeyState);
  246.                     break;
  247.                 case kbUp:
  248.                     change(mode,goUp,p,s,event.keyDown.controlKeyState);
  249.                     break;
  250.                 case kbDown:
  251.                     change(mode,goDown,p,s,event.keyDown.controlKeyState);
  252.                     break;
  253.                 case kbCtrlLeft:
  254.                     change(mode,goCtrlLeft,p,s,event.keyDown.controlKeyState);
  255.                     break;
  256.                 case kbCtrlRight:
  257.                     change(mode,goCtrlRight,p,s,event.keyDown.controlKeyState);
  258.                     break;
  259.                 case kbHome:
  260.                     p.x = limits.a.x;
  261.                     break;
  262.                 case kbEnd:
  263.                     p.x = limits.b.x - s.x;
  264.                     break;
  265.                 case kbPgUp:
  266.                     p.y = limits.a.y;
  267.                     break;
  268.                 case kbPgDn:
  269.                     p.y = limits.b.y - s.y;
  270.                     break;
  271.                 }
  272.             moveGrow( p, s, limits, minSize, maxSize, mode );
  273.             } while( event.keyDown.keyCode != kbEsc &&
  274.                      event.keyDown.keyCode != kbEnter
  275.                    );
  276.         if( event.keyDown.keyCode == kbEsc )
  277.             locate(saveBounds);
  278.         }
  279.     setState(sfDragging, False);
  280. }
  281.  
  282. void TView::draw()
  283. {
  284.     TDrawBuffer  b;
  285.  
  286.     b.moveChar( 0, ' ', getColor(1), size.x );
  287.     writeLine( 0, 0, size.x, size.y, b );
  288. }
  289.  
  290. void TView::drawCursor()
  291. {
  292.     if( (state & sfFocused) != 0 )
  293.         resetCursor();
  294. }
  295.  
  296. void TView::drawHide( TView* lastView )
  297. {
  298.     drawCursor();
  299.     drawUnderView(Boolean(state & sfShadow), lastView);
  300. }
  301.  
  302. void TView::drawShow( TView* lastView )
  303. {
  304.     drawView();
  305.     if( (state & sfShadow) != 0 )
  306.         drawUnderView( True, lastView );
  307. }
  308.  
  309. void TView::drawUnderRect( TRect& r, TView* lastView )
  310. {
  311.     owner->clip.intersect(r);
  312.     owner->drawSubViews(nextView(), lastView);
  313.     owner->clip = owner->getExtent();
  314. }
  315.  
  316. void TView::drawUnderView( Boolean doShadow, TView* lastView )
  317. {
  318.     TRect r = getBounds();
  319.     if( doShadow != False )
  320.         r.b += shadowSize;
  321.     drawUnderRect( r, lastView );
  322. }
  323.  
  324. void TView::drawView()
  325. {
  326.     if (exposed())
  327.         {
  328.         draw();
  329.         drawCursor();
  330.         }
  331. }
  332.  
  333. void TView::enableCommands( TCommandSet& commands )
  334. {
  335.     commandSetChanged = Boolean( commandSetChanged ||
  336.                                 ((curCommandSet&commands) != commands) );
  337.     curCommandSet += commands;
  338. }
  339.  
  340. void TView::enableCommand( ushort command )
  341. {
  342.     commandSetChanged = Boolean( commandSetChanged ||
  343.                                  !curCommandSet.has( command ) );
  344.     curCommandSet += command;
  345. }
  346.  
  347. void TView::endModal( ushort command )
  348. {
  349.     if( TopView() != 0 )
  350.         TopView()->endModal(command);
  351. }
  352.  
  353. Boolean  TView::eventAvail()
  354. {
  355.     TEvent event;
  356.     getEvent(event);
  357.     if( event.what != evNothing )
  358.         putEvent(event);
  359.     return Boolean( event.what != evNothing );
  360. }
  361.  
  362. TRect TView::getBounds()
  363. {
  364.     return TRect( origin, origin+size );
  365. }
  366.  
  367. ushort  TView::execute()
  368. {
  369.     return cmCancel;
  370. }
  371.  
  372. Boolean TView::focus()
  373. {
  374.     Boolean result = True;
  375.  
  376.     if ((state & (sfSelected | sfModal)) == 0)
  377.         {
  378.         if (owner)
  379.             {
  380.             result = owner->focus();
  381.             if (result)
  382. #ifndef __UNPATCHED
  383.                 if ((owner->current == 0) ||
  384.                      ((owner->current->options & ofValidate) == 0) ||
  385.                      (owner->current->valid(cmReleasedFocus)))
  386. #else
  387.                 if ((owner->current->valid(cmReleasedFocus)) &&
  388.                     ((owner->current == 0) ||
  389.                      ((owner->current->options & ofValidate) == 0)))
  390. #endif
  391.                     select();
  392.                 else
  393.                     return False;
  394.             }
  395.         }
  396.     return result;
  397. }
  398.  
  399. TRect TView::getClipRect()
  400. {
  401.     TRect clip = getBounds();
  402.     if( owner != 0 )
  403.         clip.intersect(owner->clip);
  404.     clip.move(-origin.x, -origin.y);
  405.     return clip;
  406. }
  407.  
  408. ushort TView::getColor( ushort color )
  409. {
  410.     ushort colorPair = color >> 8;
  411.  
  412.     if( colorPair != 0 )
  413.         colorPair = mapColor(colorPair) << 8;
  414.  
  415.     colorPair |= mapColor( uchar(color) );
  416.  
  417.     return colorPair;
  418. }
  419.  
  420. void TView::getCommands( TCommandSet& commands )
  421. {
  422.     commands = curCommandSet;
  423. }
  424.  
  425. void TView::getData( void * )
  426. {
  427. }
  428.  
  429. void TView::getEvent( TEvent& event )
  430. {
  431.     if( owner != 0 )
  432.         owner->getEvent(event);
  433. }
  434.  
  435. TRect TView::getExtent()
  436. {
  437.     return TRect( 0, 0, size.x, size.y );
  438. }
  439.  
  440. ushort TView::getHelpCtx()
  441. {
  442.     if( (state & sfDragging) != 0 )
  443.         return hcDragging;
  444.     return helpCtx;
  445. }
  446.  
  447. TPalette& TView::getPalette() const
  448. {
  449.     static char ch = 0;
  450.     static TPalette palette( &ch, 0 );
  451.     return palette;
  452. }
  453.  
  454. Boolean TView::getState( ushort aState )
  455. {
  456.     return Boolean( (state & aState) == aState );
  457. }
  458.  
  459. void TView::growTo( short x, short y )
  460. {
  461.     TRect r = TRect(origin.x, origin.y, origin.x + x, origin.y + y);
  462.     locate(r);
  463. }
  464.  
  465. void TView::handleEvent(TEvent& event)
  466. {
  467.     if( event.what == evMouseDown )
  468.         {
  469.         if(!(state & (sfSelected | sfDisabled)) && (options & ofSelectable) )
  470.             if( !focus() || !(options & ofFirstClick) )
  471.                 clearEvent(event);
  472.         }
  473. }
  474.  
  475. void TView::hide()
  476. {
  477.     if( (state & sfVisible) != 0 )
  478.         setState( sfVisible, False );
  479. }
  480.  
  481. void TView::hideCursor()
  482. {
  483.     setState( sfCursorVis, False );
  484. }
  485.  
  486. void TView::keyEvent( TEvent& event )
  487. {
  488.     do {
  489.        getEvent(event);
  490.        } while( event.what != evKeyDown );
  491. }
  492.  
  493. #define range(Val, Min, Max)    (((Val < Min) ? Min : ((Val > Max) ? Max : Val)))
  494.  
  495. void TView::locate( TRect& bounds )
  496. {
  497.     TPoint   min, max;
  498.     sizeLimits(min, max);
  499.     bounds.b.x = bounds.a.x + range(bounds.b.x - bounds.a.x, min.x, max.x);
  500.     bounds.b.y = bounds.a.y + range(bounds.b.y - bounds.a.y, min.y, max.y);
  501.     TRect r = getBounds();
  502.     if( bounds != r )
  503.         {
  504.         changeBounds( bounds );
  505.         if( owner != 0 && (state & sfVisible) != 0 )
  506.             {
  507.             if( (state & sfShadow) != 0 )
  508.                 {
  509.                 r.Union(bounds);
  510.                 r.b += shadowSize;
  511.                 }
  512.             drawUnderRect( r, 0 );
  513.             }
  514.         }
  515. }
  516.  
  517. void TView::makeFirst()
  518. {
  519.     putInFrontOf(owner->first());
  520. }
  521.  
  522. TPoint TView::makeGlobal( TPoint source )
  523. {
  524.     TPoint temp = source + origin;
  525.     TView *cur = this;
  526.     while( cur->owner != 0 )
  527.         {
  528.         cur = cur->owner;
  529.         temp += cur->origin;
  530.         }
  531.     return temp;
  532. }
  533.  
  534. TPoint TView::makeLocal( TPoint source )
  535. {
  536.     TPoint temp = source - origin;
  537.     TView* cur = this;
  538.     while( cur->owner != 0 )
  539.         {
  540.         cur = cur->owner;
  541.         temp -= cur->origin;
  542.         }
  543.     return temp;
  544. }
  545.  
  546. Boolean TView::mouseEvent(TEvent& event, ushort mask)
  547. {
  548.     do {
  549.        getEvent(event);
  550.         } while( !(event.what & (mask | evMouseUp)) );
  551.  
  552.     return Boolean(event.what != evMouseUp);
  553. }
  554.  
  555. Boolean TView::mouseInView(TPoint mouse)
  556. {
  557.      mouse = makeLocal( mouse );
  558.      TRect r = getExtent();
  559.      return r.contains(mouse);
  560. }
  561.  
  562. void TView::moveTo( short x, short y )
  563. {
  564.      TRect r( x, y, x+size.x, y+size.y );
  565.      locate(r);
  566. }
  567.  
  568. TView *TView::nextView()
  569. {
  570.     if( this == owner->last )
  571.         return 0;
  572.     else
  573.         return next;
  574. }
  575.  
  576. void TView::normalCursor()
  577. {
  578.     setState(sfCursorIns, False);
  579. }
  580.  
  581. TView *TView::prev()
  582. {
  583.     TView* res = this;
  584.     while( res->next != this )
  585.         res = res->next;
  586.     return res;
  587. }
  588.  
  589. TView *TView::prevView()
  590. {
  591.     if( this == owner->first() )
  592.         return 0;
  593.     else
  594.         return prev();
  595. }
  596.  
  597. void TView::putEvent( TEvent& event )
  598. {
  599.     if( owner != 0 )
  600.         owner->putEvent(event);
  601. }
  602.  
  603. void TView::putInFrontOf( TView *Target )
  604. {
  605.     TView *p, *lastView;
  606.  
  607.     if( owner != 0 && Target != this && Target != nextView() &&
  608.          ( Target == 0 || Target->owner == owner)
  609.       )
  610.         if( (state & sfVisible) == 0 )
  611.             {
  612.             owner->removeView(this);
  613.             owner->insertView(this, Target);
  614.             }
  615.         else
  616.             {
  617.             lastView = nextView();
  618.             p = Target;
  619.             while( p != 0 && p != this )
  620.                 p = p->nextView();
  621.             if( p == 0 )
  622.                 lastView = Target;
  623.             state &= ~sfVisible;
  624.             if( lastView == Target )
  625.                 drawHide(lastView);
  626.             owner->removeView(this);
  627.             owner->insertView(this, Target);
  628.             state |= sfVisible;
  629.             if( lastView != Target )
  630.                 drawShow(lastView);
  631.             if( (options & ofSelectable) != 0 )
  632.                 owner->resetCurrent();
  633.             }
  634. }
  635.  
  636. void TView::select()
  637. {
  638.     if( ! (options & ofSelectable))
  639.     return;
  640.     if( (options & ofTopSelect) != 0 )
  641.         makeFirst();
  642.     else if( owner != 0 )
  643.         owner->setCurrent( this, normalSelect );
  644. }
  645.  
  646. void TView::setBounds( const TRect& bounds )
  647. {
  648.     origin = bounds.a;
  649.     size = bounds.b - bounds.a;
  650. }
  651.  
  652. void TView::setCmdState(TCommandSet& commands, Boolean enable)
  653. {
  654.     if (enable)
  655.         enableCommands(commands);
  656.     else
  657.         disableCommands(commands);
  658. }
  659.  
  660. void TView::setCommands( TCommandSet& commands )
  661. {
  662.     commandSetChanged = Boolean( commandSetChanged ||
  663.                                 (curCommandSet != commands ));
  664.     curCommandSet = commands;
  665. }
  666.  
  667. void TView::setCursor( int x, int y )
  668. {
  669.     cursor.x = x;
  670.     cursor.y = y;
  671.     drawCursor();
  672. }
  673.  
  674. void TView::setData( void * )
  675. {
  676. }
  677.  
  678. void TView::setState( ushort aState, Boolean enable )
  679. {
  680.     if( enable == True )
  681.         state |= aState;
  682.     else
  683.         state &= ~aState;
  684.  
  685.     if( owner == 0 )
  686.         return;
  687.  
  688.     switch( aState )
  689.         {
  690.         case  sfVisible:
  691.             if( (owner->state & sfExposed) != 0 )
  692.                 setState( sfExposed, enable );
  693.             if( enable == True )
  694.                 drawShow( 0 );
  695.             else
  696.                 drawHide( 0 );
  697.             if( (options & ofSelectable) != 0 )
  698.                 owner->resetCurrent();
  699.             break;
  700.         case  sfCursorVis:
  701.         case  sfCursorIns:
  702.             drawCursor();
  703.             break;
  704.         case  sfShadow:
  705.             drawUnderView( True, 0 );
  706.             break;
  707.         case  sfFocused:
  708.             resetCursor();
  709.             message( owner,
  710.                      evBroadcast,
  711.                      (enable == True) ? cmReceivedFocus : cmReleasedFocus,
  712.                      this
  713.                    );
  714.             break;
  715.         }
  716. }
  717.  
  718. void TView::show()
  719. {
  720.     if( (state & sfVisible) == 0 )
  721.         setState(sfVisible, True);
  722. }
  723.  
  724. void TView::showCursor()
  725. {
  726.     setState( sfCursorVis, True );
  727. }
  728.  
  729. void TView::sizeLimits( TPoint& min, TPoint& max )
  730. {
  731.     min.x = min.y = 0;
  732.     if( !(growMode & gfFixed) && owner != 0 )
  733.         max = owner->size;
  734.     else
  735.         max.x = max.y = INT_MAX;
  736. }
  737.  
  738. TView* TView::TopView()
  739. {
  740.     if( TheTopView != 0 )
  741.         return TheTopView;
  742.     else
  743.         {
  744.         TView* p = this;
  745.         while( p != 0 && !(p->state & sfModal) )
  746.             p = p->owner;
  747.         return p;
  748.         }
  749. }
  750.  
  751. Boolean TView::valid( ushort )
  752. {
  753.     return True;
  754. }
  755.  
  756. Boolean TView::containsMouse( TEvent& event )
  757. {
  758.     return Boolean( (state & sfVisible) != 0 &&
  759.                     mouseInView( event.mouse.where )
  760.                   );
  761. }
  762.  
  763. void TView::shutDown()
  764. {
  765.     hide();
  766.     if( owner != 0 )
  767.         owner->remove( this );
  768.     TObject::shutDown();
  769. }
  770.  
  771.  
  772. #if !defined(NO_STREAMABLE)
  773.  
  774. void TView::write( opstream& os )
  775. {
  776.     ushort saveState =
  777.         state & ~( sfActive | sfSelected | sfFocused | sfExposed );
  778.  
  779.     os << origin << size << cursor
  780.        << growMode << dragMode << helpCtx
  781.        << saveState << options << eventMask;
  782. }
  783.  
  784. void *TView::read( ipstream& is )
  785. {
  786.     is >> origin >> size >> cursor
  787.        >> growMode >> dragMode >> helpCtx
  788.        >> state >> options >> eventMask;
  789.     owner = 0;
  790.     next = 0;
  791.     return this;
  792. }
  793.  
  794. TStreamable *TView::build()
  795. {
  796.     return new TView( streamableInit );
  797. }
  798.  
  799. TView::TView( StreamableInit )
  800. {
  801. }
  802.  
  803.  
  804. #endif
  805.