Ashley Mills / ATConsole

Dependencies:   mbed-rtos VodafoneUSBModem mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Console.cpp Source File

Console.cpp

00001 #include "Console.h"
00002 //#define DEBUG
00003 
00004 Console::Console(Serial *terminal, int lineLength, int numLines, bool characterBased)
00005     : _terminal(terminal), _lineLength(lineLength), _numLines(numLines), _characterBased(characterBased) {
00006     
00007     _terminal->printf("Console ready!\r\n");
00008     
00009     // set the buffer timeout
00010     _bufferWaitTimeout_ms = BUFFER_WAIT_TIMEOUT_MS;
00011      
00012     // allocate space for current line
00013     _lineBuffer = (char*)malloc((_lineLength+1)*sizeof(char));
00014     
00015     // character based consoles need a history
00016     if(_characterBased) {
00017        _lines = (char**)malloc(_numLines*sizeof(char*));
00018        for(int i=0; i<_numLines; i++) {
00019           _lines[i] = (char*)malloc((_lineLength+1)*sizeof(char));
00020        }
00021     
00022        // blank out current line with NULLs
00023        for(int i=0; i<=_lineLength; i++)
00024           _lineBuffer[i] = 0x00;
00025     }
00026     
00027     // set line position, number of used lines, and line buffer pointer to 0    
00028     _linePos     = 0;
00029     _prevLinePos = 0;
00030     _usedLines   = 0;
00031     _currentLine = 0;
00032 }
00033 
00034 // destructor
00035 Console::~Console() {
00036     free(_lineBuffer);
00037 }
00038 
00039 // store the current lineBuffer in the history
00040 void Console::storeBuffer() {
00041     // only do so if history specified
00042     if(_numLines==0)
00043         return;
00044     
00045     // imagine the command history as a FILO buffer
00046     // here we rightshift the command history    
00047     if(_usedLines==_numLines-1) {
00048         char* p = _lines[0];
00049         for(int i=0; i<_numLines-1; i++) {
00050             _lines[i] = _lines[i+1];
00051         }
00052         _lines[_numLines-1] = p;
00053     }
00054     
00055     // and insert the current line in the newest position
00056     strncpy(_lines[_usedLines],_lineBuffer,_lineLength+1);
00057     
00058     // this just deals with the filling up stage
00059     if(_usedLines<_numLines-1) {
00060         _usedLines++;
00061         if(_currentLine<_usedLines)
00062             _currentLine = _usedLines;
00063     } else {
00064         _currentLine = _usedLines+1;
00065     }
00066 }
00067 
00068 // clear the current-line buffer
00069 void Console::clearBuffer() {
00070     _linePos=0;
00071     for(int i=0; i<=_lineLength; i++)
00072         _lineBuffer[i] = 0x00;
00073 }
00074 
00075 // load the next buffer in the line history (activated by DOWN key)
00076 void Console::loadNextBuffer() {
00077     if(_currentLine<_usedLines) {
00078         _currentLine++;
00079     } else {
00080         _linePos=0;
00081         for(int i=0; i<=_lineLength; i++)
00082             _lineBuffer[i] = 0x00;
00083         return;
00084     }
00085     strncpy(_lineBuffer,_lines[_currentLine],_lineLength+1);
00086     _prevLinePos = _linePos;
00087     _linePos=0;
00088     while(_lineBuffer[_linePos]!=0x00)
00089         _linePos++;
00090 }
00091 
00092 // load the previous buffer in the line history (activated by UP key)
00093 void Console::loadPreviousBuffer() {
00094     if(_currentLine>0) {
00095         _currentLine--;
00096     }
00097     strncpy(_lineBuffer,_lines[_currentLine],_lineLength+1);
00098     _prevLinePos = _linePos;
00099     _linePos=0;
00100     while(_lineBuffer[_linePos]!=0x00)
00101         _linePos++;
00102 }
00103 
00104 // process a command entered (received by CRLF)
00105 void Console::processCommand() {
00106     _terminal->printf("Command: \"%s\"\r\n",_lineBuffer);
00107 }
00108 
00109 // wait on the console for input, returns false on timeout
00110 // this is useful for processing escape chars
00111 bool Console::waitForInput() {
00112     Timer timer;
00113     timer.start();
00114     while(!_terminal->readable()&&timer.read_ms()<_bufferWaitTimeout_ms);
00115     return _terminal->readable();
00116 }
00117 
00118 // print the entire command history
00119 void Console::printHistory() {
00120     for(int i=0; i<_numLines; i++)
00121         printBuffer(i);
00122 }
00123 
00124 // print the command at index in the history
00125 void Console::printBuffer(int index) {
00126     if(index==_currentLine)
00127         _terminal->printf("> ");
00128     else
00129         _terminal->printf("  ");
00130     _terminal->printf("%d) \"%s\"\r\n",index,_lines[index]);
00131 }
00132 
00133 
00134 void Console::reprintBuffer() {
00135     _terminal->putc('\r');
00136     for(int i=0; i<_lineLength; i++) {;
00137         _terminal->putc(' ');
00138     }
00139     
00140     _terminal->putc('\r');
00141     if(_linePos>0) {
00142        _terminal->printf("%s",_lineBuffer);
00143        _terminal->putc('\r');
00144        for(int i=0; i<_linePos; i++) {;
00145             _terminal->putc(0x1b);
00146             _terminal->putc('[');
00147             _terminal->putc('C');
00148        }
00149     }
00150 }
00151 
00152 // print the current-line buffer including debugging stuff
00153 void Console::printLineBuffer() {
00154     printHistory();
00155     _terminal->printf("C) \"%s\"\r\n",_lineBuffer);
00156     _terminal->printf("   \"");
00157     for(int i=0; i<_linePos; i++) {
00158         _terminal->printf(" ");
00159     }
00160     _terminal->printf("^");
00161     for(int i=_linePos+1; i<_lineLength; i++) {
00162         _terminal->printf(" ");
00163     }
00164     _terminal->printf("\"\r\n");
00165     for(int i=0; i<=_lineLength; i++) {
00166         _terminal->printf("%x ",_lineBuffer[i]);
00167     }
00168     _terminal->printf("\r\n");
00169 }
00170 
00171 void Console::updateLineBased() {
00172    //_terminal->printf("line based\r\n");
00173    // save until a line is read and then dump to the modem
00174    while(_terminal->readable()) {
00175       int c = _terminal->getc();
00176       if(_linePos<_lineLength) {
00177          
00178          _lineBuffer[_linePos++] = c;
00179          _terminal->printf("%c",c);
00180          // activate process command when
00181          if(c==0x0a) {
00182             processCommand();
00183             clearBuffer();
00184             return;
00185          }
00186       } else {
00187          _terminal->printf("WARNING, max line length exceeded!!!");
00188       }
00189       
00190    }      
00191 }
00192 
00193 void Console::updateCharacterBased() {
00194 // process console input
00195     while(_terminal->readable()) {
00196         int c = _terminal->getc();
00197         switch(c) {
00198             // backspace
00199             case 0x08:
00200                 if(_linePos>0) {
00201                     // case where pointer is at end of line
00202                     if(_lineBuffer[_linePos]==0x00) {
00203                         _lineBuffer[--_linePos] = 0x00;
00204                     } else {
00205                         // case where pointer is somewhere in the middle of the line
00206                         int copyPointer = --_linePos;
00207                         while(_lineBuffer[copyPointer]!=0x00) {
00208                             _lineBuffer[copyPointer] = _lineBuffer[copyPointer+1];
00209                             copyPointer++;
00210                         }
00211                     }
00212                     
00213                     reprintBuffer();
00214                 }           
00215             break;
00216                 
00217             // escape sequence 0x1b 0x5b
00218             case 0x1b:
00219                 // check that escape sequence exists
00220                 if(waitForInput()&&_terminal->getc()==0x5b) {
00221                         
00222                     // process escape characters
00223                     if(waitForInput()) {
00224                         c = _terminal->getc();
00225                         switch(c) {
00226                             // up
00227                             case 0x41:
00228                                 loadPreviousBuffer();
00229                                 reprintBuffer();
00230                             break;
00231                                 
00232                             // down
00233                             case 0x42:
00234                                 loadNextBuffer();
00235                                 reprintBuffer();
00236                             break;
00237                                 
00238                             // left
00239                             case 0x44:
00240                                 if(_linePos>0) {
00241                                     _linePos--;
00242                                     _terminal->putc('\b');
00243                                 }
00244                             break;
00245                                 
00246                             // right
00247                             case 0x43:
00248                                 // only move right within a string upto its end
00249                                 if(_lineBuffer[_linePos]!=0x00) {
00250                                     _linePos++;
00251                                     _terminal->putc(0x1b);
00252                                     _terminal->putc('[');
00253                                     _terminal->putc('C');
00254                                 }
00255                             break;
00256                         }
00257                     }
00258                 }
00259             break;
00260                 
00261             // carriage return
00262             case 0x0d:
00263                 storeBuffer();
00264                 processCommand();
00265                 clearBuffer();
00266             break;
00267                 
00268             default:
00269                 if(_linePos<_lineLength) {
00270                     // INS mode
00271                     if(false) {
00272                         _lineBuffer[_linePos++] = c;
00273                         _terminal->printf("%c",c);
00274                     } else {    
00275                         if(_lineBuffer[_linePos]==0x00) {
00276                             _lineBuffer[_linePos++] = c;
00277                         } else {
00278                             // move everything to the right
00279                             // so long as string end isn't at end of buffer
00280                             int strEnd = _linePos;
00281                             while(_lineBuffer[++strEnd]!=0x00);
00282                             if(strEnd!=_lineLength) {
00283                                 int copyPointer = _lineLength;
00284                                 while(--copyPointer!=_linePos) {
00285                                     _lineBuffer[copyPointer] = _lineBuffer[copyPointer-1];
00286                                 }
00287                                 
00288                                 // insert character
00289                                 _lineBuffer[_linePos++] = c;
00290                             }
00291                         }  
00292                         reprintBuffer();
00293                     }
00294                     
00295                 }
00296                   
00297             break;
00298         }
00299             
00300         #ifdef DEBUG
00301         printLineBuffer();
00302         #endif
00303     }
00304 }
00305 
00306 // process the console
00307 void Console::update() {
00308    if(_characterBased) {
00309       updateCharacterBased();
00310    } else {
00311       updateLineBased();
00312    }
00313 }