00001
00002
00003 #include "VisGeant4/VisG4Core/interface/VisG4UIShell.h"
00004 #include <classlib/utils/DebugAids.h>
00005 #include <cstdlib>
00006 #include <unistd.h>
00007 #include <errno.h>
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 VisG4UIShell::VisG4UIShell (const G4String &prompt, G4int maxhist)
00020 : G4UItcsh (prompt, maxhist),
00021 m_reading (false),
00022 m_quit (false)
00023 {
00024 pthread_mutex_init (&m_lock, 0);
00025 VERIFY (pipe (m_oncancel) != -1);
00026 }
00027
00028 G4String
00029 VisG4UIShell::GetCommandLine (const char *msg)
00030 {
00031 G4String result;
00032 pthread_mutex_lock (&m_lock);
00033 if (! m_quit)
00034 {
00035 m_reading = true;
00036 pthread_mutex_unlock (&m_lock);
00037
00038 result = MyGetCommandLine (msg);
00039
00040 pthread_mutex_lock (&m_lock);
00041 m_reading = false;
00042 }
00043
00044
00045
00046 if (m_quit)
00047 result = "exit";
00048 pthread_mutex_unlock (&m_lock);
00049
00050 return result;
00051 }
00052
00053 void
00054 VisG4UIShell::Quit (void)
00055 {
00056
00057
00058
00059 pthread_mutex_lock (&m_lock);
00060 m_quit = true;
00061 if (m_reading)
00062 write (m_oncancel [1], "\n", 1);
00063 pthread_mutex_unlock (&m_lock);
00064 }
00065
00066 char
00067 VisG4UIShell::ReadChar (void)
00068 {
00069
00070 fd_set r;
00071 FD_ZERO (&r);
00072 FD_SET (0, &r);
00073 FD_SET (m_oncancel[0], &r);
00074 while (select (m_oncancel[0]+1, &r, 0, 0, 0) == -1
00075 && (0
00076 #ifdef EAGAIN
00077 || errno == EAGAIN
00078 #endif
00079 #ifdef EINTR
00080 || errno == EINTR
00081 #endif
00082 #ifdef EWOULDBLOCK
00083 || errno == EWOULDBLOCK
00084 #endif
00085 || 0))
00086 ;
00087
00088 if (FD_ISSET (m_oncancel [0], &r))
00089
00090
00091
00092 return '\n';
00093
00094
00095 char cc;
00096 G4cin.get(cc);
00097 return cc;
00098 }
00099
00103
00104 G4String
00105 VisG4UIShell::MyReadLine (void)
00106 {
00107 static const char AsciiCtrA = '\001';
00108 static const char AsciiCtrB = '\002';
00109 static const char AsciiCtrC = '\003';
00110 static const char AsciiCtrD = '\004';
00111 static const char AsciiCtrE = '\005';
00112 static const char AsciiCtrF = '\006';
00113 static const char AsciiCtrK = '\013';
00114 static const char AsciiCtrL = '\014';
00115 static const char AsciiCtrN = '\016';
00116 static const char AsciiCtrP = '\020';
00117 static const char AsciiCtrQ = '\021';
00118 static const char AsciiCtrS = '\023';
00119 static const char AsciiCtrZ = '\032';
00120 static const char AsciiTAB = '\011';
00121 static const char AsciiBS = '\010';
00122 static const char AsciiDEL = '\177';
00123 static const char AsciiESC = '\033';
00124
00125 InitializeCommandLine();
00126
00127 char cc;
00128 do {
00129
00130 switch(cc = ReadChar ()){
00131 case AsciiCtrA:
00132 MoveCursorTop();
00133 break;
00134 case AsciiCtrB:
00135 BackwardCursor();
00136 break;
00137 case AsciiCtrD:
00138 if(commandLine.length()!=0 && IsCursorLast()) ListMatchedCommand();
00139 else if (commandLine.empty()) {
00140 G4cout << G4endl;
00141 exit(0);
00142 } else DeleteCharacter();
00143 break;
00144 case AsciiCtrE:
00145 MoveCursorEnd();
00146 break;
00147 case AsciiCtrF:
00148 ForwardCursor();
00149 break;
00150 case AsciiCtrK:
00151 ClearAfterCursor();
00152 break;
00153 case AsciiCtrL:
00154
00155 break;
00156 case AsciiCtrN:
00157 NextCommand();
00158 break;
00159 case AsciiCtrP:
00160 PreviousCommand();
00161 break;
00162 case AsciiTAB:
00163 if( (!commandLine.empty()) && IsCursorLast()) CompleteCommand();
00164 break;
00165 case AsciiDEL:
00166 BackspaceCharacter();
00167 break;
00168 case AsciiBS:
00169 BackspaceCharacter();
00170 break;
00171 case AsciiCtrC:
00172 break;
00173 case AsciiCtrQ:
00174 break;
00175 case AsciiCtrS:
00176 break;
00177 case AsciiCtrZ:
00178 break;
00179 default:
00180 break;
00181 }
00182
00183
00184 if( cc == AsciiESC) {
00185 G4cin.get(cc);
00186 if (cc == '[') {
00187 G4cin.get(cc);
00188 switch(cc) {
00189 case 'A':
00190 cc = 'P' - '@';
00191 PreviousCommand();
00192 break;
00193 case 'B':
00194 cc = 'N' - '@';
00195 NextCommand();
00196 break;
00197 case 'C':
00198 cc = 'F' - '@';
00199 ForwardCursor();
00200 break;
00201 case 'D':
00202 cc = 'B' - '@';
00203 BackwardCursor();
00204 break;
00205 default:
00206 cc = 0;
00207 break;
00208 }
00209 }
00210 }
00211
00212
00213 InsertCharacter(cc);
00214
00215 } while( cc != '\n');
00216
00217 return commandLine;
00218 }
00219
00220 G4String
00221 VisG4UIShell::MyGetCommandLine (const char *msg)
00222 {
00223 SetTermToInputMode();
00224
00225 MakePrompt(msg);
00226 relativeHistoryIndex= 0;
00227
00228 G4cout << promptString << std::flush;
00229
00230 G4String newCommand= MyReadLine();
00231
00232 while( (newCommand.length() > 0) &&
00233 ( newCommand[newCommand.length()-1] == '_') ) {
00234 newCommand.remove(newCommand.length()-1);
00235 G4cout << G4endl;
00236 promptString= "? ";
00237 G4cout << promptString << std::flush;
00238 G4String newLine= MyReadLine();
00239 newCommand.append(newLine);
00240 }
00241
00242
00243 G4bool isMeaningfull= FALSE;
00244 for (size_t i=0; i<newCommand.length(); i++) {
00245 if(newCommand[i] != ' ') {
00246 isMeaningfull= TRUE;
00247 break;
00248 }
00249 }
00250 if( !newCommand.empty() && isMeaningfull) StoreHistory(newCommand);
00251
00252
00253 RestoreTerm();
00254
00255 G4cout << G4endl;
00256 return newCommand;
00257 }