メインページ   モジュール   名前空間一覧   クラス階層   アルファベット順一覧   構成   ファイル一覧   構成メンバ   ファイルメンバ   関連ページ    

TTerminalUserInterface.cc

解説を見る。
00001 // =====================================================================
00002 //  $Id: TTerminalUserInterface.cc,v 1.7 2004/06/24 15:15:25 goiwai Exp $
00003 //  $Name: CLDAQ-1-14-03 $
00004 //  $Log: TTerminalUserInterface.cc,v $
00005 //  Revision 1.7  2004/06/24 15:15:25  goiwai
00006 //  たくさんの変更
00007 //  Tcout,Tcerr,Tlogをバッファ経由にした。
00008 //  何個かexternした。Tlog,Tcout,Tcerr,Tinfo...Tcritなど出力関係。
00009 //
00010 //  Revision 1.6  2004/03/07 10:30:31  goiwai
00011 //  ROOTに組みこむためのおまじないマクロを埋めこみました。
00012 //  全てにおいて完全に動作するわけではありません。
00013 //
00014 //  Revision 1.5  2003/10/06 17:02:40  goiwai
00015 //  *** empty log message ***
00016 //
00017 //  Revision 1.4  2003/07/30 16:18:52  goiwai
00018 //  ファイルにコミットログをつけることにしました.
00019 //
00020 // =====================================================================
00021 #include "TTerminalUserInterface.hh"
00022 #include "TRunManager.hh"
00023 #include "TCommand.hh"
00024 
00025 static const Tchar _asciiCtrlA = '\001';
00026 static const Tchar _asciiCtrlB = '\002';
00027 static const Tchar _asciiCtrlD = '\004';
00028 static const Tchar _asciiCtrlE = '\005';
00029 static const Tchar _asciiCtrlF = '\006';
00030 static const Tchar _asciiCtrlK = '\013';
00031 static const Tchar _asciiCtrlL = '\014';
00032 static const Tchar _asciiCtrlN = '\016';
00033 static const Tchar _asciiCtrlP = '\020';
00034 static const Tchar _asciiCtrlY = '\031';
00035 static const Tchar _asciiCtrlZ = '\032';
00036 static const Tchar _asciiTAB = '\011';
00037 static const Tchar _asciiBS = '\010';
00038 static const Tchar _asciiDEL = '\177';
00039 static const Tchar _asciiESC = '\033';
00040 
00041 TTerminalUserInterface::TTerminalUserInterface( const Tstring& prompt, const Tstring& history )
00042   : TUserInterface( history ), theCommandHistoryIndex( 0 ),
00043     theCursorPosition( 0 ), thePrompt( prompt ), theAcceptString(),
00044     theStringBuffer(), theCommandBuffer()
00045 {
00046   tcgetattr( 0, &theTerminal );
00047   setupterm( 0, 1, 0 );
00048 }
00049 
00050 TTerminalUserInterface::~TTerminalUserInterface()
00051 {;}
00052 
00053 Tvoid TTerminalUserInterface::initializeCommandLine()
00054 {
00055   theCommandHistoryIndex = (Tint)theCommandHistory.size();
00056   theCursorPosition = 0;
00057   theAcceptString.erase();
00058   theCommandBuffer.erase();
00059   std::cout << thePrompt << std::flush;
00060   return;
00061 }
00062 
00063 const Tstring& TTerminalUserInterface::readLine()
00064 {
00065   setTerminalInputMode();
00066   initializeCommandLine();
00067 
00068   Tchar cc;
00069 
00070   do {
00071     Tcin.get( cc );
00072 
00073     switch ( cc ) {
00074 
00075       case _asciiCtrlA:
00076         moveCursorTop();
00077         break;
00078 
00079       case _asciiCtrlB:
00080         backwardCursor();
00081         break;
00082 
00083       case _asciiCtrlD:
00084         deleteCharacter();
00085         break;
00086 
00087       case _asciiCtrlE:
00088         moveCursorEnd();
00089         break;
00090 
00091       case _asciiCtrlF:
00092         forwardCursor();
00093         break;
00094 
00095       case _asciiCtrlK:
00096         cutCharacter();
00097         break;
00098 
00099       case _asciiCtrlL:
00100         clearScreen();
00101         break;
00102 
00103       case _asciiCtrlN:
00104         nextCommand();
00105         break;
00106 
00107       case _asciiCtrlP:
00108         previousCommand();
00109         break;
00110 
00111       case _asciiCtrlY:
00112         pasteCharacter();
00113         break;
00114 
00115       case _asciiCtrlZ:
00116         suspendTerminal();
00117         break;
00118 
00119       case _asciiTAB:
00120         completeCommand();
00121         break;
00122 
00123       case _asciiBS:
00124         backspaceCharacter();
00125         break;
00126 
00127       case _asciiDEL:
00128         deleteCharacter();
00129         break;
00130 
00131       default:
00132         break;
00133     }
00134 
00135     if ( cc == _asciiESC ) {
00136       Tcin.get( cc );
00137       if ( cc == '[' ) {
00138         Tcin.get( cc );
00139         switch ( cc ) {
00140           case 'A':  // up
00141             cc = 'P' - '@';
00142             previousCommand();
00143             break;
00144           case 'B':  // down
00145             cc = 'N' - '@';
00146             nextCommand();
00147             break;
00148           case 'C':  // right
00149             cc = 'F' - '@';
00150             forwardCursor();
00151             break;
00152           case 'D':  // left
00153             cc = 'B' - '@';
00154             backwardCursor();
00155             break;
00156           default:
00157             cc = 0;
00158             break;
00159         }
00160       }
00161     }
00162     
00163     insertCharacter( cc );
00164 
00165   } while ( cc != Teol );
00166 
00167   
00168   if ( theAcceptString.size() > 0 ) {
00169 
00170     // erase space character form back
00171     while ( !( theAcceptString.empty() ) && ( theAcceptString.rfind( Tspace ) == theAcceptString.size() - 1 ) ) {
00172       theAcceptString.erase( theAcceptString.end() - 1 );
00173     }
00174 
00175     // erase space character
00176     while ( !( theAcceptString.empty() ) && ( theAcceptString.find( Tspace ) == 0 ) ) {
00177       theAcceptString.erase( theAcceptString.begin() );
00178     }
00179   }
00180   std::cout << std::endl;
00181 
00182   resetTerminal();
00183 
00184   return theAcceptString;
00185 }
00186 
00187 Tvoid TTerminalUserInterface::insertCharacter( Tchar cc )
00188 {
00189   if ( ! isprint( cc ) ) {
00190     return;
00191   }
00192 
00193   std::cout << cc;
00194   for ( Tint i = theCursorPosition; i < (Tint)theAcceptString.size(); i ++ ) {
00195     std::cout << theAcceptString[ i ];
00196   }
00197   for ( Tint i = theCursorPosition; i < (Tint)theAcceptString.size(); i ++ ) {
00198     std::cout << _asciiBS;
00199   }
00200   std::cout << std::flush;
00201     
00202   if ( isCursorEnd() ) {
00203     theAcceptString += cc;
00204   } else {
00205     theAcceptString.insert( theAcceptString.begin() + theCursorPosition, cc );
00206   }
00207 
00208   theCursorPosition ++;
00209   return;
00210 }
00211 
00212 Tvoid TTerminalUserInterface::backspaceCharacter()
00213 {
00214   if ( isCursorTop() ) {
00215     return;
00216   }
00217 
00218   if ( isCursorEnd() ) {
00219     std::cout << _asciiBS << Tspace << _asciiBS;
00220   } else {
00221     std::cout << _asciiBS;
00222     for ( Tint i = theCursorPosition; i < (Tint)theAcceptString.size(); i ++ ) {
00223       std::cout << theAcceptString[ i ];
00224     }
00225     std::cout << Tspace;
00226     for ( Tint i = theCursorPosition; i < (Tint)( theAcceptString.size() + 1 ); i ++ ) {
00227       std::cout << _asciiBS;
00228     }
00229   }
00230   std::cout << std::flush;
00231   theAcceptString.erase( theCursorPosition - 1, 1 );
00232   theCursorPosition --;
00233   return;
00234 }
00235 
00236 Tvoid TTerminalUserInterface::deleteCharacter()
00237 {
00238   forwardCursor();
00239   backspaceCharacter();
00240   return;
00241 }
00242 
00243 Tvoid TTerminalUserInterface::clearLine()
00244 {
00245   moveCursorTop();
00246   clearAfterCursor();
00247   return;
00248 }
00249 
00250 Tvoid TTerminalUserInterface::clearScreen()
00251 {
00252   ClearScreen();
00253   if ( ! theAcceptString.empty() ) {
00254     Tint posbuf = theCursorPosition;
00255     theCursorPosition = theAcceptString.size();
00256     std::cout << thePrompt << theAcceptString;
00257     Tint nback = theCursorPosition - posbuf;
00258     if ( nback > 0 ) {
00259       for ( Tint i = 0; i < nback; i ++ ) {
00260         backwardCursor();
00261       }
00262     }
00263     return;
00264   }
00265   theCursorPosition = 0;
00266   std::cout << thePrompt << std::flush;
00267   return;
00268 }
00269 
00270 Tvoid TTerminalUserInterface::clearAfterCursor()
00271 {
00272   if ( isCursorEnd() ) {
00273     return;
00274   }
00275   for ( Tint i = theCursorPosition; i < (Tint)theAcceptString.size(); i ++ ) {
00276     std::cout << Tspace;
00277   }
00278   for ( Tint i = (Tint)theAcceptString.size(); i > theCursorPosition; i -- ) {
00279     std::cout << _asciiBS;
00280   }
00281   std::cout << std::flush;
00282   theAcceptString.erase( theCursorPosition, theAcceptString.size() - theCursorPosition );
00283   return;
00284 }
00285 
00286 Tvoid TTerminalUserInterface::forwardCursor()
00287 {
00288   if ( isCursorEnd() ) {
00289     return;
00290   }
00291   std::cout << theAcceptString[ (Tsize_t)( theCursorPosition ) ] << std::flush;
00292   theCursorPosition ++;
00293   return;
00294 }
00295 
00296 Tvoid TTerminalUserInterface::backwardCursor()
00297 {
00298   if ( isCursorTop() ) {
00299     return;
00300   }
00301   std::cout << _asciiBS << std::flush;
00302   theCursorPosition --;
00303   return;
00304 }
00305 
00306 Tvoid TTerminalUserInterface::moveCursorTop()
00307 {
00308   while ( isCursorTop() == Tfalse ) {
00309     backwardCursor();
00310   }
00311   return;
00312 }
00313 
00314 Tvoid TTerminalUserInterface::moveCursorEnd()
00315 {
00316   while ( isCursorEnd() == Tfalse ) {
00317     forwardCursor();
00318   }
00319   return;
00320 }
00321 
00322 Tvoid TTerminalUserInterface::cutCharacter()
00323 {
00324   if ( !( theStringBuffer.empty() ) ) {
00325     theStringBuffer.erase();
00326   }
00327   for ( Tint i = theCursorPosition; i < (Tint)theAcceptString.size(); i ++ ) {
00328     theStringBuffer += theAcceptString[ i ];
00329   }
00330   Tint nback = (Tint)( theAcceptString.size() ) - theCursorPosition;
00331   moveCursorEnd();
00332   for ( Tint i = 0; i < nback; i ++ ) {
00333     backspaceCharacter();
00334   }
00335   return;
00336 }
00337 
00338 Tvoid TTerminalUserInterface::pasteCharacter()
00339 {
00340   if ( theStringBuffer.empty() ) {
00341     return;
00342   }
00343   for ( int i = 0; i < (Tint)theStringBuffer.size(); i ++ ) {
00344     insertCharacter( theStringBuffer[ i ] );
00345   }
00346   return;
00347 }
00348 
00349 Tvoid TTerminalUserInterface::nextCommand()
00350 {
00351   if ( theCommandHistoryIndex > (Tint)theCommandHistory.size() - 1 ) {
00352     return;
00353   }
00354   clearLine();
00355   Tstring com;
00356   if ( theCommandHistoryIndex == (Tint)theCommandHistory.size() - 1 ) {
00357     com = theCommandBuffer;
00358   } else {
00359     com = theCommandHistory[ theCommandHistoryIndex + 1 ];
00360   }
00361 
00362   for ( int i = 0; i < (Tint)com.size(); i ++ ) {
00363     insertCharacter( com[ i ] );
00364   }
00365   theCommandHistoryIndex ++;
00366   return;
00367 }
00368 
00369 Tvoid TTerminalUserInterface::previousCommand()
00370 {
00371   if ( theCommandHistory.empty() || theCommandHistoryIndex == 0 ) {
00372     return;
00373   }
00374 
00375   if ( theCommandHistoryIndex == (Tint)theCommandHistory.size() ) {
00376     theCommandBuffer = theAcceptString;
00377   }
00378 
00379   clearLine();
00380 
00381   Tstring com = theCommandHistory[ theCommandHistoryIndex - 1 ];
00382   for ( int i = 0; i < (Tint)com.size(); i ++ ) {
00383     insertCharacter( com[ i ] );
00384   }
00385   theCommandHistoryIndex --;
00386   return;
00387 }
00388 
00389 Tvoid TTerminalUserInterface::completeCommand()
00390 {
00391   Tstring strbuf = theAcceptString;
00392   TstringList input = divide( strbuf );
00393 
00394   if ( input.empty() ) {
00395     complete();
00396   } else if ( input.size() == 1 && strbuf[ strbuf.size() - 1 ] != ' ' ) {
00397     complete( input[ 0 ] );
00398   } else if ( input.size() == 1 && input[ 0 ] == "cd" && strbuf[ strbuf.size() - 1 ] == ' ' ) {
00399     completeDirectory();
00400   } else if ( input.size() == 2 && input[ 0 ] == "cd" && strbuf[ strbuf.size() - 1 ] != ' ' ) {
00401     completeDirectory( input[ 1 ] );
00402   } else if ( input.size() > 1 && strbuf[ strbuf.size() - 1 ] != ' ' ) {
00403     complete( input );
00404   } else if ( input.size() > 0 && strbuf[ strbuf.size() - 1 ] == ' ' ) {
00405     complete();
00406   }
00407 
00408   return;
00409 }
00410 
00411 Tvoid TTerminalUserInterface::complete()
00412 {
00413   std::cout << std::endl;
00414   ExecuteCommand( "ls" );
00415 
00416   if ( ! theAcceptString.empty() ) {
00417     Tint posbuf = theCursorPosition;
00418     theCursorPosition = theAcceptString.size();
00419     std::cout << thePrompt << theAcceptString;
00420     Tint nback = theCursorPosition - posbuf;
00421     if ( nback > 0 ) {
00422       for ( Tint i = 0; i < nback; i ++ ) {
00423         backwardCursor();
00424       }
00425     }
00426     return;
00427   }
00428 
00429   theCursorPosition = 0;
00430   std::cout << thePrompt << std::flush;
00431 
00432   return;
00433 }
00434 
00435 Tvoid TTerminalUserInterface::complete( const Tstring& input )
00436 {
00437   // complete for command
00438   Tstring abspath = ModifyPath( input );
00439   TstringList candidate;
00440   for ( Tint i = 0; i < theCommandTable.GetSize(); i ++ ) {
00441     Tstring fullname = theCommandTable[ i ].GetFullName();
00442     if ( fullname.substr( 0, abspath.size() ) == abspath ) {
00443       candidate.push_back( fullname );
00444     } else if ( theCommandTable[ i ].IsBuiltinCommand() && fullname.substr( 0, input.size() ) == input ) {
00445       candidate.push_back( fullname );
00446     }
00447   }
00448 
00449 
00450   if ( candidate.empty() ) {
00451     return;
00452   }
00453 
00454 
00455   // 候補をフルパスから出力用に変更する
00456   // /run に居て ./sus の候補は /run/suspend だけど ./suspend に変換
00457   TstringList local = candidate;
00458   for ( Tsize_t i = 0; i < local.size(); i ++  ) {
00459     if ( abspath != "/" && input[ input.size() - 1 ] == '/' ) {
00460       local[ i ] = input.substr( 0, input.size() - 1 ) + local[ i ].substr( abspath.size(), local[ i ].size() - abspath.size() );
00461     } else {
00462       if ( candidate[ i ][ 0 ] == '/' ) {
00463         local[ i ] = input + local[ i ].substr( abspath.size(), local[ i ].size() - abspath.size() );
00464       }
00465     }
00466   }
00467 
00468 
00469   if ( local.size() == 1 ) {
00470     // 候補がひとつなので完全補間
00471     clearLine();
00472     theAcceptString = local[ 0 ];
00473     theAcceptString += ' ';
00474     theCursorPosition = theAcceptString.size();
00475     std::cout << theAcceptString;
00476   } else {
00477 
00478     for ( Tsize_t i = 0; i < candidate.size(); i ++  ) {
00479       if ( theCommandTable.GetCommandSpecified( candidate[ i ] ).IsAliasedCommand() ) {
00480         local[ i ] += "@";
00481       } else {
00482         local[ i ] += "*";
00483       }
00484     }
00485 
00486     theCommandTable.Sort( local );
00487     std::cout << std::endl;
00488     theCommandTable.List( GetNumberOfColumns(), local );
00489 
00490     // find out part of coincidence from candidate
00491     Tsize_t pos = input.size() - 1;
00492     Tbool coincidence = Ttrue;
00493     while ( coincidence ) {
00494       pos ++;
00495       for ( Tsize_t i = 0; i < local.size() - 1; i ++ ) {
00496         coincidence &= ( ( local[ i ] )[ pos ] == ( local[ i + 1 ] )[ pos ] );
00497       }
00498     }
00499     
00500     theAcceptString = local[ 0 ];
00501     theAcceptString.erase( pos, ( theAcceptString.size() - pos ) );
00502     theCursorPosition = theAcceptString.size();
00503     std::cout << thePrompt << theAcceptString;
00504 
00505   }
00506 
00507   std::cout << std::flush;
00508 
00509   return;
00510 }
00511 
00512 Tvoid TTerminalUserInterface::complete( const TstringList& inputs )
00513 {
00514   // 第2引数以上の補間
00515   // under construction
00516   // std::cout << "Tvoid TTerminalUserInterface::complete( const TstringList& inputs )" << std::endl;
00517   return;
00518 }
00519 
00520 Tvoid TTerminalUserInterface::completeDirectory()
00521 {
00522   TstringList dirs = theCommandTable.GetDirectoryList( theCurrentWorkingDirectory );
00523   if ( dirs.empty() ) {
00524     return;
00525   }
00526 
00527   std::cout << std::endl;
00528   theCommandTable.List( GetNumberOfColumns(), theCommandTable.Sort( dirs ) );
00529 
00530   std::cout << thePrompt << theAcceptString;
00531 
00532   return;
00533 }
00534 
00535 Tvoid TTerminalUserInterface::completeDirectory( const Tstring& input )
00536 {
00537   if ( input.size() >= 2 && input.substr( input.size() - 2, 2 ) == ".." ) {
00538     theAcceptString += "/";
00539     theCursorPosition += 1;
00540     std::cout << "/" << std::flush;
00541     return;
00542   }
00543 
00544 
00545   enum { DIRLIST, COMPLETE };
00546   Tint mode;
00547   if ( input[ input.size() - 1 ] == '/' ) {
00548     mode = DIRLIST;
00549   } else {
00550     mode = COMPLETE;
00551   }
00552 
00553 
00554   Tstring temppath = input;
00555   if ( temppath.size() > 2 && temppath.substr( 0, 2 ) == "./" ) {
00556     temppath.erase( 0, 2 );
00557   }
00558   Tstring abspath = ModifyPath( temppath );
00559   Tstring targetdir;
00560   Tsize_t pos = abspath.rfind( "/" );
00561   if ( input[ input.size() - 1 ] == '/' && theCommandTable.AlreadyExistDirectory( abspath ) ) {
00562     targetdir = abspath;
00563   } else if ( pos == 0 ) {
00564     targetdir = "/";
00565   } else {
00566     targetdir = abspath.substr( 0, pos );
00567   }
00568 
00569   TstringList dirlist = theCommandTable.GetDirectoryList( targetdir );
00570   TstringList candidate;
00571   if ( dirlist.empty() ) {
00572     return;
00573   } else if ( mode == DIRLIST ) {
00574     std::cout << std::endl;
00575     theCommandTable.Sort( dirlist );
00576     theCommandTable.List( GetNumberOfColumns(), dirlist );
00577     theCursorPosition = theAcceptString.size();
00578     std::cout << thePrompt << theAcceptString << std::flush;
00579     return;
00580   } else if ( mode == COMPLETE ) {
00581     Tsize_t pos = abspath.rfind( '/' );
00582     Tstring dir = abspath.substr( pos + 1, abspath.size() - pos - 1 );
00583     for ( Tsize_t i = 0; i < dirlist.size(); i ++ ) {
00584       if ( dirlist[ i ].substr( 0, dir.size() ) == dir ) {
00585         candidate.push_back( dirlist[ i ] );
00586       }
00587     }
00588 
00589     if ( candidate.empty() ) {
00590       return;
00591     }
00592   } else {
00593     return;
00594   }
00595 
00596 
00597 
00598   if ( candidate.size() == 1 ) {
00599     // 候補がひとつなので完全補間
00600     clearLine();
00601     theAcceptString = "cd " + input.substr( 0, input.rfind( '/' ) + 1 ) + candidate[ 0 ];
00602     theCursorPosition = theAcceptString.size();
00603     std::cout << theAcceptString;
00604   } else {
00605     std::cout << std::endl;
00606     theCommandTable.Sort( candidate );
00607     theCommandTable.List( GetNumberOfColumns(), candidate );
00608 
00609     // find out part of coincidence from candidate
00610     Tsize_t pos = 0;
00611     Tbool coincidence = Ttrue;
00612     while ( coincidence ) {
00613       pos ++;
00614       for ( Tsize_t i = 0; i < candidate.size() - 1; i ++ ) {
00615         coincidence &= ( ( candidate[ i ] )[ pos ] == ( candidate[ i + 1 ] )[ pos ] );
00616       }
00617     }
00618 
00619     theAcceptString = candidate[ 0 ];
00620     theAcceptString.erase( pos, ( theAcceptString.size() - pos ) );
00621     theAcceptString = "cd " + input.substr( 0, input.rfind( '/' ) + 1 ) + theAcceptString;
00622     theCursorPosition = theAcceptString.size();
00623     std::cout << thePrompt << theAcceptString << std::flush;
00624   }
00625 
00626   return;
00627 }
00628 
00629 Tvoid TTerminalUserInterface::suspendTerminal() const
00630 {
00631   pid_t pid = getpid();
00632   if ( fork() == 0 ) {
00633     exit( kill( pid, SIGSTOP ) );
00634   } else {
00635     wait( 0 );
00636   }
00637   return;
00638 }
00639 
00640 Tvoid TTerminalUserInterface::setTerminalInputMode()
00641 {
00642   termios tiosbuf = theTerminal;
00643   tiosbuf.c_iflag |= IGNBRK;
00644   tiosbuf.c_iflag |= IGNPAR;
00645   tiosbuf.c_lflag &= ~ICANON;
00646   tiosbuf.c_lflag &= ~ECHO;
00647   tiosbuf.c_lflag &= ~ISIG;
00648   tiosbuf.c_cc[ VMIN ] = 1;
00649   tiosbuf.c_cc[ VTIME ] = 0;
00650   tcsetattr( 0, TCSANOW, &tiosbuf );
00651 
00652   return;
00653 }
00654 
00655 Tvoid TTerminalUserInterface::resetTerminal()
00656 {
00657   tcsetattr( 0, TCSANOW, &theTerminal );
00658   return;
00659 }
00660 
00661 Tbool TTerminalUserInterface::AcceptCommand()
00662 {
00663   return ( theAcceptString.c_str() != 0 ) ? Ttrue : Tfalse;
00664 }
00665 
00666 const Tstring& TTerminalUserInterface::GetInputCommand()
00667 {
00668   return readLine();
00669 }
00670 
00671 Tvoid TTerminalUserInterface::NotFoundCommand( const Tstring& commandname ) const
00672 {
00673   std::cerr << commandname << ": Command not found." << std::endl;
00674   return;
00675 }
00676 
00677 TstringList TTerminalUserInterface::divide( const Tstring& input ) const
00678 {
00679   TstringList divided;
00680   Tsize_t begin = 0;
00681   Tsize_t end = 0;
00682   Tsize_t inputlen = input.size();
00683 
00684   do {
00685     begin = input.find_first_not_of( ' ', end );
00686     end = input.find( ' ', begin );
00687     if ( begin < inputlen && end >= inputlen ) {
00688       divided.push_back( input.substr( begin, inputlen - begin ) );
00689     } else if ( begin >= inputlen && end >= inputlen ) {
00690       break;
00691     } else {
00692       divided.push_back( input.substr( begin, end - begin ) );
00693     }
00694   } while ( begin < inputlen && end < inputlen );
00695 
00696   return divided;
00697 }
00698 
00699 #ifdef __CLDAQ_ROOT_DLL
00700     ClassImp(TTerminalUserInterface)
00701 #endif


CLDAQ - a Class Library for DataAcQuisition (Version 1.14.3)
Go IWAI -- goiwai at users.sourceforge.jp