00001
00002
00003
00004
00005
00006
00007 #include <ctype.h>
00008
00009 #include "Error.h"
00010 #include "FSh.h"
00011 #include "Core.h"
00012 #include "NamedObject.h"
00013 #include "Set.h"
00014
00015 #include "FShGetLine.h"
00016
00017
00018
00019 FShGetLine::FShGetLine(FSh *shell) : GetLine()
00020 {
00021 int res;
00022
00023 _forth = FORTH();
00024
00025 if (!(_shell = shell)) {
00026 failure(ERROR(MSG_NULL_POINTER));
00027 return;
00028 }
00029
00030 if (!(_connection = shell->_connection)) {
00031 failure(ERROR(MSG_NULL_POINTER));
00032 return;
00033 }
00034
00035 if (FAILED(res = _connection->writeStr(_forth->output()))) {
00036 failure(ERROR_BACKTRACE(res));
00037 return;
00038 }
00039
00040 if (FAILED(res = _connection->writeStr(_forth->welcome()))) {
00041 failure(ERROR_BACKTRACE(res));
00042 return;
00043 }
00044 if (FAILED(res = setPrompt(CSTRING(_forth->prompt())))) {
00045 failure(ERROR_BACKTRACE(res));
00046 return;
00047 }
00048 }
00049
00050 FShGetLine::~FShGetLine()
00051 {
00052 }
00053
00054
00055
00056 int FShGetLine::onTab(char *buf, const int, int *cursorLoc, int *i)
00057 {
00058 if (*cursorLoc == 0 || strlen(buf) == 0)
00059 return OK;
00060
00061 String matchedWords;
00062 unsigned int matchedWordsNum = 0;
00063 bool quotation = false;
00064 String completedPart;
00065 StringSet words(_forth->words());
00066 int res;
00067
00068 words += NamedObject::names();
00069
00070 int j;
00071 unsigned int wordsPerLine, len;
00072 char *wordPart = buf;
00073
00074 j = *cursorLoc - 1;
00075 while (j >= 0) {
00076 if (buf[j] == ' ' || buf[j] == '\t' || buf[j] == '"') {
00077 if (buf[j] == '"')
00078 quotation = true;
00079 wordPart = buf + j + 1;
00080 break;
00081 }
00082 --j;
00083 }
00084 if ((len = strlen(wordPart)) == 0)
00085 return OK;
00086
00087 StringSet::const_iterator k = words.begin();
00088 StringSet::const_iterator e = words.end();
00089
00090 wordsPerLine = 0;
00091 while (k != e) {
00092 if (strncasecmp(wordPart, CSTRING(*k), len) == 0) {
00093 if (wordsPerLine > 0)
00094 matchedWords += '\t';
00095 matchedWords += *k;
00096 completedPart.intersection(*k, true);
00097 ++matchedWordsNum;
00098 if (++wordsPerLine >= LIMIT_FORTH_WORDS_PER_LINE) {
00099 wordsPerLine = 0;
00100 matchedWords.append(String::eol());
00101 }
00102 }
00103 ++k;
00104 }
00105
00106 if (matchedWordsNum == 0) {
00107 int actuallyWritten;
00108
00109 if (FAILED(res = _connection->write(&FSH_GETLINE_BEEP, sizeof(FSH_GETLINE_BEEP), actuallyWritten)))
00110 return ERROR_BACKTRACE(res);
00111
00112 return OK;
00113 }
00114
00115 if (matchedWordsNum == 1) {
00116 if (!quotation)
00117 matchedWords += ' ';
00118 strncpy(wordPart, CSTRING(matchedWords), GL_LIMIT_BUFFER_SIZE - 1);
00119 *i = wordPart - buf;
00120 *cursorLoc += matchedWords.length();
00121 } else {
00122 if (FAILED(res = _connection->writeStr(String::eol() + matchedWords + (iscntrl(matchedWords[matchedWords.length() - 1]) ? "" : String::eol()) + prompt() + buf)))
00123 return ERROR_BACKTRACE(res);
00124 if (!completedPart.empty()) {
00125 strncpy(wordPart, CSTRING(completedPart), GL_LIMIT_BUFFER_SIZE - 1);
00126 *i = wordPart - buf;
00127 *cursorLoc += completedPart.length();
00128 }
00129 }
00130
00131 return OK;
00132 }
00133
00134 int FShGetLine::onOutput(const char *buf)
00135 {
00136 int res;
00137
00138 if (strlen(buf) == 0)
00139 if (FAILED(res = CORE()->kill(_shell)))
00140 return ERROR_BACKTRACE(res);
00141
00142 if (FAILED(res = _forth->eval(buf)))
00143 ERROR_BACKTRACE(res);
00144
00145 if (FAILED(res = setPrompt(CSTRING(_forth->prompt()))))
00146 return ERROR_BACKTRACE(res);
00147
00148 String out(_forth->output());
00149 if (!out.empty())
00150 if (FAILED(res = _connection->writeStr(String::eol() + out)))
00151 return ERROR_BACKTRACE(res);
00152
00153 return OK;
00154 }
00155
00156 int FShGetLine::onPutc(const char c)
00157 {
00158 int actuallyWritten;
00159 int res;
00160
00161 if (FAILED(res = _connection->write(&c, sizeof(char), actuallyWritten)))
00162 return ERROR_BACKTRACE(res);
00163 if (c == '\n') {
00164 char ch = '\r';
00165 if (FAILED(res = _connection->write(&ch, sizeof(char), actuallyWritten)))
00166 return ERROR_BACKTRACE(res);
00167 }
00168
00169 return OK;
00170 }
00171
00172 int FShGetLine::onPuts(const char *buf)
00173 {
00174 int actuallyWritten;
00175 int res;
00176
00177 if (buf)
00178 if (FAILED(res = _connection->write(buf, strlen(buf), actuallyWritten)))
00179 return ERROR_BACKTRACE(res);
00180
00181 return OK;
00182 }
00183
00184
00185
00186
00187 unsigned int FShGetLine::onStrlen(const char *str)
00188 {
00189 return String::colorLength(str);
00190 }