#include <cassert>
#include <cstdint>
#include <iostream>
#include <functional>
#include <map>
#include "ConsoleInput.hpp"
#include "KeyActions.hpp"
enum class Keys : uint32_t
{ // always omitting the 1b at the beginning of the full key sequence.
// Might as well use it all and uint64_t without the byte fumbling, though.
F5 = 0x7e35315b,
Pos1 = 0x485b,
PgDn = 0x7e365b,
};
static const std::map< Keys, std::function<uint32_t(uint32_t)> > s_map =
{ {Keys::F5, KeyActions::DoFunnyAction},
{Keys::Pos1, KeyActions::DoFunkyAction},
{Keys::PgDn, KeyActions::DoSkunkyAction},
};
static uint32_t U32FromUnalignedBuf(const char* buf, int offs, int count)
{ assert( (unsigned)count <= 4 );
uint32_t x = 0;
for (int i=0; i<count; ++i)
x |= buf[offs+i] << (i*8);
return x;
}
int main()
{
using namespace std;
cout << "Waiting for input..."<< endl;
for (;;)
{
//char c = getch();
const int maxChars = 8; // most I saw was 5
char buf[ maxChars + 1 ]; // +1 for terminating zero
const int readNum = ConsoleInput::GetChars(buf, maxChars);
if (readNum>=0)
buf[readNum] = '\0';
switch (readNum)
{
case 1:
if (27 == buf[0]) // Esc key?
return 0;
cout << buf << endl;
break;
case 2 ... maxChars:
for (int i=readNum; i>=0; --i) // print MSByte first
cout << hex << (unsigned)buf[i];
cout << endl;
// the funny sequences seem to all strt with 1b abd be of max len 5,
// so let's use 0x1b start as a clue and the rest as uint32 key ID.
if (0x1b == buf[0])
{ auto key = U32FromUnalignedBuf( buf, 1, readNum-1 );
//cout << "key: " << key << endl;
auto itr = s_map.find( (Keys) key ); // nasty hard cast, this program tolerates it, though
if (itr != s_map.end())
{ cout << "Action: ";
uint32_t param = 123; // if you need one...
// call the action function of the key-value-pair found by its key,
// i.e. the second parameter ("first" would be the key)
auto ret = itr->second( param );
}
}
break;
default: cout << "Unexpected byte count: "<< readNum << endl; break;
}
}
return 0;
}
#include "KeyActions.hpp"
#include <iostream>
// frowned upon at file scope by many, too lazy for the alternatives now
using namespace std;
namespace KeyActions
{
unsigned DoFunnyAction(unsigned param)
{
cout << "A donkey and a jackass enter a bar..." << endl;
}
unsigned DoFunkyAction(unsigned param)
{
cout << "*slaps bass*" << endl;
}
unsigned DoSkunkyAction(unsigned param)
{
cout << "*sprays and runs*" << endl;
}
}
#pragma once
namespace KeyActions
{
unsigned DoFunnyAction(unsigned param);
unsigned DoFunkyAction(unsigned param);
unsigned DoSkunkyAction(unsigned param);
}
#include "ConsoleInput.hpp"
#include <unistd.h>
#include <termios.h>
#include <cerrno>
#include <cstdio>
namespace ConsoleInput
{
int GetChars(char* dest, int maxnum)
{
struct termios old = {0};
if (tcgetattr(0, &old) < 0)
perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON");
int rdNum=0;
if ((rdNum=read(0, dest, maxnum)) < 0)
perror ("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror ("tcsetattr ~ICANON");
return rdNum;
}
}//namespace ConsoleInput
#pragma once
namespace ConsoleInput
{
int GetChars(char* dest, int maxnum);
}//namespace ConsoleInput