306 lines
9.1 KiB
C++
306 lines
9.1 KiB
C++
/* i_input.cpp
|
|
*
|
|
* Copyright (c) 1994-1996, Marko Macek
|
|
*
|
|
* You may distribute under the terms of either the GNU General Public
|
|
* License or the Artistic License, as specified in the README file.
|
|
*
|
|
*/
|
|
|
|
#include "fte.h"
|
|
|
|
ExInput::ExInput(const char *APrompt, char *ALine, unsigned int ABufLen, Completer AComp, int Select, int AHistId): ExView() {
|
|
assert(ABufLen > 0);
|
|
MaxLen = ABufLen - 1;
|
|
Comp = AComp;
|
|
SelStart = SelEnd = 0;
|
|
Prompt = strdup(APrompt);
|
|
Line = (char *) malloc(MaxLen + 1);
|
|
MatchStr = (char *) malloc(MaxLen + 1);
|
|
CurStr = (char *) malloc(MaxLen + 1);
|
|
if (Line) {
|
|
Line[MaxLen] = 0;
|
|
strncpy(Line, ALine, MaxLen);
|
|
Pos = strlen(Line);
|
|
LPos = 0;
|
|
}
|
|
if (Select)
|
|
SelEnd = Pos;
|
|
TabCount = 0;
|
|
HistId = AHistId;
|
|
CurItem = 0;
|
|
}
|
|
|
|
ExInput::~ExInput() {
|
|
if (Prompt)
|
|
free(Prompt);
|
|
if (Line)
|
|
free(Line);
|
|
if (MatchStr)
|
|
free(MatchStr);
|
|
if (CurStr)
|
|
free(CurStr);
|
|
Prompt = 0;
|
|
Line = 0;
|
|
}
|
|
|
|
void ExInput::Activate(int gotfocus) {
|
|
ExView::Activate(gotfocus);
|
|
}
|
|
|
|
int ExInput::BeginMacro() {
|
|
return 1;
|
|
}
|
|
|
|
void ExInput::HandleEvent(TEvent &Event) {
|
|
switch (Event.What) {
|
|
case evKeyDown:
|
|
switch (kbCode(Event.Key.Code)) {
|
|
case kbLeft: if (Pos > 0) Pos--; SelStart = SelEnd = 0; TabCount = 0; Event.What = evNone; break;
|
|
case kbRight: Pos++; SelStart = SelEnd = 0; TabCount = 0; Event.What = evNone; break;
|
|
case kbLeft | kfCtrl:
|
|
if (Pos > 0) {
|
|
Pos--;
|
|
while (Pos > 0) {
|
|
if (isalnum(Line[Pos]) && !isalnum(Line[Pos - 1]))
|
|
break;
|
|
Pos--;
|
|
}
|
|
}
|
|
SelStart = SelEnd = 0;
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
break;
|
|
case kbRight | kfCtrl:
|
|
{
|
|
unsigned int len = strlen(Line);
|
|
if (Pos < len) {
|
|
Pos++;
|
|
while (Pos < len) {
|
|
if (isalnum(Line[Pos]) && !isalnum(Line[Pos - 1]))
|
|
break;
|
|
Pos++;
|
|
}
|
|
}
|
|
}
|
|
SelStart = SelEnd = 0;
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
break;
|
|
case kbHome: Pos = 0; SelStart = SelEnd = 0; TabCount = 0; Event.What = evNone; break;
|
|
case kbEnd: Pos = strlen(Line); SelStart = SelEnd = 0; TabCount = 0; Event.What = evNone; break;
|
|
case kbEsc: EndExec(0); Event.What = evNone; break;
|
|
case kbEnter:
|
|
#ifdef CONFIG_HISTORY
|
|
AddInputHistory(HistId, Line);
|
|
#endif
|
|
EndExec(1);
|
|
Event.What = evNone;
|
|
break;
|
|
case kbBackSp | kfCtrl | kfShift:
|
|
SelStart = SelEnd = 0;
|
|
Pos = 0;
|
|
Line[0] = 0;
|
|
TabCount = 0;
|
|
break;
|
|
case kbBackSp | kfCtrl:
|
|
if (Pos > 0) {
|
|
if (Pos > strlen(Line)) {
|
|
Pos = strlen(Line);
|
|
} else {
|
|
char Ch;
|
|
|
|
if (Pos > 0) do {
|
|
Pos--;
|
|
memmove(Line + Pos, Line + Pos + 1, strlen(Line + Pos + 1) + 1);
|
|
if (Pos == 0) break;
|
|
Ch = Line[Pos - 1];
|
|
} while (Pos > 0 && Ch != '\\' && Ch != '/' && Ch != '.' && isalnum(Ch));
|
|
}
|
|
}
|
|
SelStart = SelEnd = 0;
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
break;
|
|
case kbBackSp:
|
|
case kbBackSp | kfShift:
|
|
if (SelStart < SelEnd) {
|
|
memmove(Line + SelStart, Line + SelEnd, strlen(Line + SelEnd) + 1);
|
|
Pos = SelStart;
|
|
SelStart = SelEnd = 0;
|
|
break;
|
|
}
|
|
if (Pos <= 0) break;
|
|
Pos--;
|
|
if (Pos < strlen(Line))
|
|
memmove(Line + Pos, Line + Pos + 1, strlen(Line + Pos + 1) + 1);
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
break;
|
|
case kbDel:
|
|
if (SelStart < SelEnd) {
|
|
memmove(Line + SelStart, Line + SelEnd, strlen(Line + SelEnd) + 1);
|
|
Pos = SelStart;
|
|
SelStart = SelEnd = 0;
|
|
break;
|
|
}
|
|
if (Pos < strlen(Line))
|
|
memmove(Line + Pos, Line + Pos + 1, strlen(Line + Pos + 1) + 1);
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
break;
|
|
case kbDel | kfCtrl:
|
|
if (SelStart < SelEnd) {
|
|
memmove(Line + SelStart, Line + SelEnd, strlen(Line + SelEnd) + 1);
|
|
Pos = SelStart;
|
|
SelStart = SelEnd = 0;
|
|
break;
|
|
}
|
|
SelStart = SelEnd = 0;
|
|
Line[Pos] = 0;
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
break;
|
|
case kbIns | kfShift:
|
|
case 'V' | kfCtrl:
|
|
{
|
|
int len;
|
|
|
|
if (SystemClipboard)
|
|
GetPMClip();
|
|
|
|
if (SSBuffer == 0) break;
|
|
if (SSBuffer->RCount == 0) break;
|
|
|
|
if (SelStart < SelEnd) {
|
|
memmove(Line + SelStart, Line + SelEnd, strlen(Line + SelEnd) + 1);
|
|
Pos = SelStart;
|
|
SelStart = SelEnd = 0;
|
|
}
|
|
|
|
len = SSBuffer->LineChars(0);
|
|
if (strlen(Line) + len < MaxLen) {
|
|
memmove(Line + Pos + len, Line + Pos, strlen(Line + Pos) + 1);
|
|
memcpy(Line + Pos, SSBuffer->RLine(0)->Chars, len);
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
Pos += len;
|
|
}
|
|
}
|
|
break;
|
|
#ifdef CONFIG_HISTORY
|
|
case kbUp:
|
|
SelStart = SelEnd = 0;
|
|
if (CurItem == 0)
|
|
strcpy(CurStr, Line);
|
|
CurItem += 2;
|
|
case kbDown:
|
|
SelStart = SelEnd = 0;
|
|
if (CurItem == 0) break;
|
|
CurItem--;
|
|
{
|
|
int cnt = CountInputHistory(HistId);
|
|
|
|
if (CurItem > cnt) CurItem = cnt;
|
|
if (CurItem < 0) CurItem = 0;
|
|
|
|
if (CurItem == 0)
|
|
strcpy(Line, CurStr);
|
|
else if (GetInputHistory(HistId, Line, MaxLen, CurItem));
|
|
else strcpy(Line, CurStr);
|
|
Pos = strlen(Line);
|
|
// SelStart = SelEnd = 0;
|
|
}
|
|
Event.What = evNone;
|
|
break;
|
|
#endif
|
|
case kbTab | kfShift:
|
|
TabCount -= 2;
|
|
case kbTab:
|
|
if (Comp) {
|
|
char *Str2 = (char *) malloc(MaxLen + 1);
|
|
int n;
|
|
|
|
assert(Str2);
|
|
TabCount++;
|
|
if (TabCount < 1) TabCount = 1;
|
|
if ((TabCount == 1) && (kbCode(Event.Key.Code) == kbTab)) {
|
|
strcpy(MatchStr, Line);
|
|
}
|
|
n = Comp(MatchStr, Str2, TabCount);
|
|
if ((n > 0) && (TabCount <= n)) {
|
|
strcpy(Line, Str2);
|
|
Pos = strlen(Line);
|
|
} else if (TabCount > n) TabCount = n;
|
|
free(Str2);
|
|
}
|
|
SelStart = SelEnd = 0;
|
|
Event.What = evNone;
|
|
break;
|
|
case 'Q' | kfCtrl:
|
|
Event.What = evKeyDown;
|
|
Event.Key.Code = Win->GetChar(0);
|
|
default:
|
|
{
|
|
char Ch;
|
|
|
|
if (GetCharFromEvent(Event, &Ch) && (strlen(Line) < MaxLen)) {
|
|
if (SelStart < SelEnd) {
|
|
memmove(Line + SelStart, Line + SelEnd, strlen(Line + SelEnd) + 1);
|
|
Pos = SelStart;
|
|
SelStart = SelEnd = 0;
|
|
}
|
|
memmove(Line + Pos + 1, Line + Pos, strlen(Line + Pos) + 1);
|
|
Line[Pos++] = Ch;
|
|
TabCount = 0;
|
|
Event.What = evNone;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
Event.What = evNone;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ExInput::UpdateView() {
|
|
if (Next) {
|
|
Next->UpdateView();
|
|
}
|
|
}
|
|
|
|
void ExInput::RepaintView() {
|
|
if (Next) {
|
|
Next->RepaintView();
|
|
}
|
|
}
|
|
|
|
void ExInput::UpdateStatus() {
|
|
RepaintStatus();
|
|
}
|
|
|
|
void ExInput::RepaintStatus() {
|
|
TDrawBuffer B;
|
|
int W, H, FLen, FPos;
|
|
|
|
ConQuerySize(&W, &H);
|
|
|
|
FPos = strlen(Prompt) + 2;
|
|
FLen = W - FPos;
|
|
|
|
if (Pos > strlen(Line))
|
|
Pos = strlen(Line);
|
|
//if (Pos < 0) Pos = 0;
|
|
if (LPos + FLen <= Pos) LPos = Pos - FLen + 1;
|
|
if (Pos < LPos) LPos = Pos;
|
|
|
|
MoveChar(B, 0, W, ' ', hcEntry_Field, W);
|
|
MoveStr(B, 0, W, Prompt, hcEntry_Prompt, FPos);
|
|
MoveChar(B, FPos - 2, W, ':', hcEntry_Prompt, 1);
|
|
MoveStr(B, FPos, W, Line + LPos, hcEntry_Field, FLen);
|
|
MoveAttr(B, FPos + SelStart - LPos, W, hcEntry_Selection, SelEnd - SelStart);
|
|
ConSetCursorPos(FPos + Pos - LPos, H - 1);
|
|
ConPutBox(0, H - 1, W, 1, B);
|
|
ConShowCursor();
|
|
}
|