This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
fte/i_input.cpp

306 lines
9.1 KiB
C++
Raw Normal View History

/* 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();
}