From 10a874299557382df51d32e91a90c246992d43a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Wed, 7 Sep 2016 08:07:36 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/pip@256 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5 --- src/console/pikbdlistener.cpp | 145 +++++++++++++++++----------------- src/console/pikbdlistener.h | 23 ++++++ src/console/piterminal.cpp | 129 +++++++++++++++++++++--------- src/console/piterminal.h | 1 + 4 files changed, 189 insertions(+), 109 deletions(-) diff --git a/src/console/pikbdlistener.cpp b/src/console/pikbdlistener.cpp index 5bc67384..70608feb 100644 --- a/src/console/pikbdlistener.cpp +++ b/src/console/pikbdlistener.cpp @@ -45,78 +45,78 @@ PIKbdListener * PIKbdListener::_object = 0; #ifndef WINDOWS -struct EscSeq { - const char * seq; - int key; - int mod; - // 1 - shift - // 2 - alt - // 4 - ctrl -}; // unix -const EscSeq esc_seq[] = { - {"[1A", PIKbdListener::UpArrow, 0}, - {"[A", PIKbdListener::UpArrow, 0}, - {"OA", PIKbdListener::UpArrow, 4}, - {"[1B", PIKbdListener::DownArrow, 0}, - {"[B", PIKbdListener::DownArrow, 0}, - {"OB", PIKbdListener::DownArrow, 4}, - {"[1C", PIKbdListener::RightArrow, 0}, - {"[C", PIKbdListener::RightArrow, 0}, - {"OC", PIKbdListener::RightArrow, 4}, - {"[1D", PIKbdListener::LeftArrow, 0}, - {"[D", PIKbdListener::LeftArrow, 0}, - {"OD", PIKbdListener::LeftArrow, 0}, - {"[H", PIKbdListener::Home, 0}, - {"[1H", PIKbdListener::Home, 0}, - {"[1~", PIKbdListener::Home, 0}, - {"[F", PIKbdListener::End, 0}, - {"[1F", PIKbdListener::End, 0}, - {"[4~", PIKbdListener::End, 0}, - {"[2~", PIKbdListener::Insert, 0}, - {"[3~", PIKbdListener::Delete, 0}, - {"[5~", PIKbdListener::PageUp, 0}, - {"[6~", PIKbdListener::PageDown, 0}, - {"[Z", PIKbdListener::Tab, 1}, - {"OP", PIKbdListener::F1, 0}, - {"[[A", PIKbdListener::F1, 0}, - {"[11~", PIKbdListener::F1, 0}, - {"OQ", PIKbdListener::F2, 0}, - {"[[B", PIKbdListener::F2, 0}, - {"[12~", PIKbdListener::F2, 0}, - {"OR", PIKbdListener::F3, 0}, - {"[[C", PIKbdListener::F3, 0}, - {"[13~", PIKbdListener::F3, 0}, - {"[25~", PIKbdListener::F3, 1}, - {"OS", PIKbdListener::F4, 0}, - {"[[D", PIKbdListener::F4, 0}, - {"[14~", PIKbdListener::F4, 0}, - {"[26~", PIKbdListener::F4, 1}, - {"[[E", PIKbdListener::F5, 0}, - {"OT", PIKbdListener::F5, 0}, - {"[15~", PIKbdListener::F5, 0}, - {"[28~", PIKbdListener::F5, 1}, - {"OU", PIKbdListener::F6, 0}, - {"[17~", PIKbdListener::F6, 0}, - {"[29~", PIKbdListener::F6, 1}, - {"OV", PIKbdListener::F7, 0}, - {"[18~", PIKbdListener::F7, 0}, - {"[31~", PIKbdListener::F7, 1}, - {"OW", PIKbdListener::F8, 0}, - {"[19~", PIKbdListener::F8, 0}, - {"[32~", PIKbdListener::F8, 1}, - {"OX", PIKbdListener::F9, 0}, - {"[20~", PIKbdListener::F9, 0}, - {"[33~", PIKbdListener::F9, 1}, - {"OY", PIKbdListener::F10, 0}, - {"[21~", PIKbdListener::F10, 0}, - {"[34~", PIKbdListener::F10, 1}, - {"OZ", PIKbdListener::F11, 0}, - {"[23~", PIKbdListener::F11, 0}, - {"O[", PIKbdListener::F12, 0}, - {"[24~", PIKbdListener::F12, 0}, +const PIKbdListener::EscSeq PIKbdListener::esc_seq[] = { + {"OA", PIKbdListener::UpArrow, 0, 0 , 1 }, + {"OA", PIKbdListener::UpArrow, 4, 0 , 0 }, + {"[1A", PIKbdListener::UpArrow, 0, 0 , 0 }, + {"[A", PIKbdListener::UpArrow, 0, vt_all , 0 }, + {"OB", PIKbdListener::DownArrow, 0, 0 , 1 }, + {"OB", PIKbdListener::DownArrow, 4, 0 , 0 }, + {"[1B", PIKbdListener::DownArrow, 0, 0 , 0 }, + {"[B", PIKbdListener::DownArrow, 0, vt_all , 0 }, + {"OC", PIKbdListener::RightArrow, 0, 0 , 1 }, + {"OC", PIKbdListener::RightArrow, 4, 0 , 0 }, + {"[1C", PIKbdListener::RightArrow, 0, 0 , 0 }, + {"[C", PIKbdListener::RightArrow, 0, vt_all , 0 }, + {"OD", PIKbdListener::LeftArrow, 0, 0 , 1 }, + {"OD", PIKbdListener::LeftArrow, 4, 0 , 0 }, + {"[1D", PIKbdListener::LeftArrow, 0, 0 , 0 }, + {"[D", PIKbdListener::LeftArrow, 0, vt_all , 0 }, + {"[H", PIKbdListener::Home, 0, vt_xterm , 0 }, + {"[1H", PIKbdListener::Home, 0, 0 , 0 }, + {"OH", PIKbdListener::Home, 0, 0 , 1 }, + {"[1~", PIKbdListener::Home, 0, vt_linux , 0 }, + {"[F", PIKbdListener::End, 0, vt_xterm , 0 }, + {"[1F", PIKbdListener::End, 0, 0 , 0 }, + {"OF", PIKbdListener::End, 0, 0 , 1 }, + {"[4~", PIKbdListener::End, 0, vt_linux , 0 }, + {"[2~", PIKbdListener::Insert, 0, vt_all , 0 }, + {"[3~", PIKbdListener::Delete, 0, vt_all , 0 }, + {"[5~", PIKbdListener::PageUp, 0, vt_all , 0 }, + {"[6~", PIKbdListener::PageDown, 0, vt_all , 0 }, + {"[Z", PIKbdListener::Tab, 1, vt_xterm , 0 }, + {"OP", PIKbdListener::F1, 0, vt_xterm , 0 }, + {"[[A", PIKbdListener::F1, 0, vt_linux , 0 }, + {"[11~", PIKbdListener::F1, 0, 0 , 0 }, + {"[25~", PIKbdListener::F1, 1, vt_linux , 0 }, + {"OQ", PIKbdListener::F2, 0, vt_xterm , 0 }, + {"[[B", PIKbdListener::F2, 0, vt_linux , 0 }, + {"[12~", PIKbdListener::F2, 0, 0 , 0 }, + {"[26~", PIKbdListener::F2, 1, vt_linux , 0 }, + {"OR", PIKbdListener::F3, 0, vt_xterm , 0 }, + {"[[C", PIKbdListener::F3, 0, vt_linux , 0 }, + {"[13~", PIKbdListener::F3, 0, 0 , 0 }, + {"[28~", PIKbdListener::F3, 1, vt_linux , 0 }, + {"OS", PIKbdListener::F4, 0, vt_xterm , 0 }, + {"[[D", PIKbdListener::F4, 0, vt_linux , 0 }, + {"[14~", PIKbdListener::F4, 0, 0 , 0 }, + {"[29~", PIKbdListener::F4, 1, vt_linux , 0 }, + {"[[E", PIKbdListener::F5, 0, vt_linux , 0 }, + {"OT", PIKbdListener::F5, 0, 0 , 0 }, + {"[15~", PIKbdListener::F5, 0, vt_xterm , 0 }, + {"[31~", PIKbdListener::F5, 1, vt_linux , 0 }, + {"OU", PIKbdListener::F6, 0, 0 , 0 }, + {"[17~", PIKbdListener::F6, 0, vt_all , 0 }, + {"[32~", PIKbdListener::F6, 1, vt_linux , 0 }, + {"OV", PIKbdListener::F7, 0, 0 , 0 }, + {"[18~", PIKbdListener::F7, 0, vt_all , 0 }, + {"[33~", PIKbdListener::F7, 1, vt_linux , 0 }, + {"OW", PIKbdListener::F8, 0, 0 , 0 }, + {"[19~", PIKbdListener::F8, 0, vt_all , 0 }, + {"[34~", PIKbdListener::F8, 1, vt_linux , 0 }, + {"OX", PIKbdListener::F9, 0, 0 , 0 }, + {"[20~", PIKbdListener::F9, 0, vt_all , 0 }, + {"[35~", PIKbdListener::F9, 1, vt_linux , 0 }, + {"OY", PIKbdListener::F10, 0, 0 , 0 }, + {"[21~", PIKbdListener::F10, 0, vt_all , 0 }, + {"[36~", PIKbdListener::F10, 1, vt_linux , 0 }, + {"OZ", PIKbdListener::F11, 0, 0 , 0 }, + {"[23~", PIKbdListener::F11, 0, vt_all , 0 }, + {"O[", PIKbdListener::F12, 0, 0 , 0 }, + {"[24~", PIKbdListener::F12, 0, vt_all , 0 }, // End - {0, 0, 0}, + {0, 0, 0, 0, 0}, }; #endif @@ -242,8 +242,8 @@ void PIKbdListener::readKeyboard() { #else tcsetattr(0, TCSANOW, &PRIVATE->tterm); ret = read(0, rc, 8); - /*piCout << NewLine << "read" << ret; - for (int i = 0; i < ret; ++i) + //piCout << "key" << PIString(rc).replaceAll("\e", "\\e"); + /*for (int i = 0; i < ret; ++i) cout << std::hex << int(((uchar * )&rc)[i]) << ' '; cout << endl; for (int i = 0; i < ret; ++i) @@ -288,6 +288,7 @@ void PIKbdListener::readKeyboard() { } for (int i = 0; ; ++i) { if (!esc_seq[i].seq) break; + //piCout << "search" << rc[1] << esc_seq[i].seq; if (strcmp(esc_seq[i].seq, &(rc[1])) == 0) { ke.key = esc_seq[i].key; mod |= esc_seq[i].mod; diff --git a/src/console/pikbdlistener.h b/src/console/pikbdlistener.h index a5dff354..2a7503c2 100644 --- a/src/console/pikbdlistener.h +++ b/src/console/pikbdlistener.h @@ -32,6 +32,7 @@ class PIP_EXPORT PIKbdListener: public PIThread { PIOBJECT_SUBCLASS(PIKbdListener, PIThread) friend class PIConsole; + friend class PITerminal; public: //! Special keyboard keys @@ -152,6 +153,28 @@ private: void run() {readKeyboard();} void end(); +#ifndef WINDOWS + struct EscSeq { + const char * seq; + int key; + int mod; + int vt; + int flags; + // 1 - shift + // 2 - alt + // 4 - ctrl + }; + + enum VTType { + vt_none, + vt_xterm = 0x1, + vt_linux = 0x2, + vt_all = 0xFF + }; + + static const EscSeq esc_seq[]; +#endif + PRIVATE_DECLARATION #ifdef WINDOWS DWORD diff --git a/src/console/piterminal.cpp b/src/console/piterminal.cpp index f587d788..c059143e 100644 --- a/src/console/piterminal.cpp +++ b/src/console/piterminal.cpp @@ -23,6 +23,7 @@ # include # include #else +# include "piprocess.h" # include # include # include @@ -48,6 +49,9 @@ struct PITerminalAuxData { }; #else # define BUFFER_SIZE 4096 +enum DECType { + CKM = 1 +}; #endif @@ -62,11 +66,13 @@ PRIVATE_DEFINITION_START(PITerminal) PIString shell; PIByteArray read_buf, tmp_buf; PIScreenTypes::CellFormat cur_format; + int term_type; int fd, cur_x, cur_y; int save_cur_x, save_cur_y; pid_t pid; PIString esc_seq; bool is_esc_seq, last_read; + PIMap DEC; termios desc; #endif PRIVATE_DEFINITION_END(PITerminal) @@ -131,9 +137,9 @@ void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers PIByteArray ba; #ifdef WINDOWS switch (k) { - case PIKbdListener::Tab: ba << uchar('\t'); break; + case PIKbdListener::Tab: ba << uchar('\t'); break; case PIKbdListener::Return: ba << uchar('\r') << uchar('\n'); break; - case PIKbdListener::Space: ba << uchar(' '); break; + case PIKbdListener::Space: ba << uchar(' '); break; default: break; } //piCout << "write" << ba.size(); @@ -146,35 +152,57 @@ void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers writePipe(PRIVATE->pipe, msg); } #else + int term = PRIVATE->term_type; + int flags = 0; switch (k) { case PIKbdListener::Tab: ba << uchar('\t'); break; case PIKbdListener::Return: ba << uchar('\n'); break; case PIKbdListener::Esc: ba << uchar('\e'); break; - case PIKbdListener::Space: ba << uchar(' '); break; + case PIKbdListener::Space: ba << uchar(' '); break; case PIKbdListener::Backspace: ba << uchar(0x7f); break; - case PIKbdListener::UpArrow: ba << uchar('\e') << uchar('[') /*<< uchar('1')*/ << uchar('A'); break; - case PIKbdListener::DownArrow: ba << uchar('\e') << uchar('[') /*<< uchar('1')*/ << uchar('B'); break; - case PIKbdListener::RightArrow: ba << uchar('\e') << uchar('[') /*<< uchar('1')*/ << uchar('C'); break; - case PIKbdListener::LeftArrow: ba << uchar('\e') << uchar('[') /*<< uchar('1')*/ << uchar('D'); break; - case PIKbdListener::Home: break; - case PIKbdListener::End: break; - case PIKbdListener::PageUp: ba << uchar('\e') << uchar('[') << uchar('5') << uchar('~'); break; - case PIKbdListener::PageDown: ba << uchar('\e') << uchar('[') << uchar('6') << uchar('~'); break; - case PIKbdListener::Insert: ba << uchar('\e') << uchar('[') << uchar('2') << uchar('~'); break; - case PIKbdListener::Delete: ba << uchar('\e') << uchar('[') << uchar('3') << uchar('~'); break; - case PIKbdListener::F1: break; - case PIKbdListener::F2: break; - case PIKbdListener::F3: break; - case PIKbdListener::F4: break; - case PIKbdListener::F5: break; - case PIKbdListener::F6: break; - case PIKbdListener::F7: break; - case PIKbdListener::F8: break; - case PIKbdListener::F9: break; - case PIKbdListener::F10: break; - case PIKbdListener::F11: break; - case PIKbdListener::F12: break; - default: break; + case PIKbdListener::UpArrow: + case PIKbdListener::DownArrow: + case PIKbdListener::RightArrow: + case PIKbdListener::LeftArrow: if (PRIVATE->DEC.value(CKM, false)) flags = 1; + /*case PIKbdListener::Home: //break; + case PIKbdListener::End: //break; + case PIKbdListener::PageUp: //ba << uchar('\e') << uchar('[') << uchar('5') << uchar('~'); break; + case PIKbdListener::PageDown: //ba << uchar('\e') << uchar('[') << uchar('6') << uchar('~'); break; + case PIKbdListener::Insert: //ba << uchar('\e') << uchar('[') << uchar('2') << uchar('~'); break; + case PIKbdListener::Delete: //ba << uchar('\e') << uchar('[') << uchar('3') << uchar('~'); break; + case PIKbdListener::F1: //break; + case PIKbdListener::F2: //break; + case PIKbdListener::F3: //break; + case PIKbdListener::F4: //break; + case PIKbdListener::F5: //break; + case PIKbdListener::F6: //break; + case PIKbdListener::F7: //break; + case PIKbdListener::F8: //break; + case PIKbdListener::F9: //break; + case PIKbdListener::F10: //break; + case PIKbdListener::F11: //break; + case PIKbdListener::F12: //break; + */ + default: { + //piCout << flags; + int mod = 0; + if (m[PIKbdListener::Shift]) m |= 1; + if (m[PIKbdListener::Alt]) m |= 2; + if (m[PIKbdListener::Ctrl]) m |= 4; + for (int i = 0; ; ++i) { + const PIKbdListener::EscSeq & e(PIKbdListener::esc_seq[i]); + if (!e.seq) break; + //piCout << "search" << rc[1] << esc_seq[i].seq; + if (e.key == k && e.mod == m) { + if (((e.vt & term) == term) || (((e.flags & flags) == flags) && (flags != 0))) { + //piCout << "found key" << PIString(e.seq).replaceAll("\e", "\\e"); + PIByteArray d = ("\e" + PIString(e.seq)).toByteArray(); + write(d); + break; + } + } + } + } break; } //piCout << "write" << ba.size(); if (!ba.isEmpty()) write(ba); @@ -188,7 +216,11 @@ void PITerminal::write(PIKbdListener::KeyEvent ke) { if (isSpecialKey(ke.key)) write((PIKbdListener::SpecialKey)ke.key, ke.modifiers); else { PIByteArray ba; +#ifdef WINDOWS ba << uchar(PIChar(ke.key).toConcole1Byte()); +#else + ba = PIString(PIChar(ke.key)).toUTF8(); +#endif write(ba); } } @@ -196,7 +228,6 @@ void PITerminal::write(PIKbdListener::KeyEvent ke) { PIVector > PITerminal::content() { readConsole(); - getCursor(cursor_x, cursor_y); PIVector > ret = cells; if (cursor_blink && cursor_visible) if (cursor_x >= 0 && cursor_x < size_x) @@ -253,6 +284,7 @@ void PITerminal::initPrivate() { PRIVATE->fd = PRIVATE->cur_x = PRIVATE->cur_y = 0; PRIVATE->save_cur_x = PRIVATE->save_cur_y = 0; PRIVATE->pid = 0; + PRIVATE->term_type = 0; PRIVATE->is_esc_seq = false; PRIVATE->last_read = true; PRIVATE->esc_seq.clear(); @@ -311,12 +343,10 @@ uchar PITerminal::invertColor(uchar c) { void PITerminal::run() { + getCursor(cursor_x, cursor_y); if (cursor_tm.elapsed_m() >= 500) { cursor_tm.reset(); cursor_blink = !cursor_blink; - if (cursor_blink) { - getCursor(cursor_x, cursor_y); - } } #ifndef WINDOWS if (PRIVATE->fd == 0) return; @@ -326,7 +356,7 @@ void PITerminal::run() { if (readed > 0) { PRIVATE->last_read = true; //piCoutObj << "readed" << readed << PIString(PRIVATE->tmp_buf.resized(readed)).replaceAll("\e", "\\e"); - piCoutObj << "readed" << readed << (PRIVATE->tmp_buf.resized(readed)); + //piCoutObj << "readed" << readed << (PRIVATE->tmp_buf.resized(readed)); PRIVATE->read_buf.append(PRIVATE->tmp_buf.resized(readed)); for (;;) { int ind = -1; @@ -340,7 +370,11 @@ void PITerminal::run() { parseInput(PIString((const char *)PRIVATE->read_buf.data(), ind)); PRIVATE->read_buf.remove(0, ind); } - if (PRIVATE->read_buf.size_s() >= BUFFER_SIZE) { + bool parse = PRIVATE->read_buf.size_s() >= BUFFER_SIZE; + if (PRIVATE->read_buf.size_s() == 1) + if (PRIVATE->read_buf[0] < 0x80) + parse = true; + if (parse) { parseInput(PIString(PRIVATE->read_buf)); PRIVATE->read_buf.clear(); } @@ -414,12 +448,19 @@ bool PITerminal::isCompleteEscSeq(const PIString & es) { void PITerminal::applyEscSeq(PIString es) { - piCoutObj << es; + //piCoutObj << es; if (es.size_s() < 2) return; - if (es[1] == '?' && es.size_s() >= 2) { // cursor - PIString c = es.mid(2); - if (c == "25l") cursor_visible = false; - if (c == "25h") cursor_visible = true; + if (es[1] == '?' && es.size_s() >= 2) { + char a = es.takeRight(1)[0].toAscii(); + bool val = false; + if (a == 'l') val = false; + if (a == 'h') val = true; + int dec = es.mid(2).toInt(); + //piCoutObj << "DEC" << dec << val; + switch (dec) { + case 25: cursor_visible = val; break; + default: PRIVATE->DEC[dec] = val; break; + } } PIScreenTypes::Cell def_cell = PIScreenTypes::Cell(' ', PRIVATE->cur_format); if (es[0] == '[') { // CSI @@ -590,6 +631,13 @@ void PITerminal::moveCursor(int dx, int dy) { cells[y].fill(PIScreenTypes::Cell()); } } + + +int PITerminal::termType(const PIString & t) { + if (t == "xterm") return PIKbdListener::vt_xterm; + else if (t == "linux") return PIKbdListener::vt_linux; + return PIKbdListener::vt_none; +} #endif @@ -665,6 +713,13 @@ bool PITerminal::initialize() { winsize ws; ws.ws_col = dsize_x; ws.ws_row = dsize_y; + PIStringList env = PIProcess::currentEnvironment(); + piForeachC (PIString & e, env) + if (e.startsWith("TERM=")) { + PRIVATE->term_type = termType(e.mid(5).trim().toLowerCase()); + //piCout << PRIVATE->term_type; + piBreak; + } pid_t fr = forkpty(&(PRIVATE->fd), pty, 0, &ws); //piCoutObj << fr << PRIVATE->fd << pty; if (fr == 0) { diff --git a/src/console/piterminal.h b/src/console/piterminal.h index fb6cc31c..8e23c415 100644 --- a/src/console/piterminal.h +++ b/src/console/piterminal.h @@ -61,6 +61,7 @@ private: bool isCompleteEscSeq(const PIString & es); void applyEscSeq(PIString es); void moveCursor(int dx, int dy); + int termType(const PIString & t); #endif PRIVATE_DECLARATION