0

I have an irc bot written in c++ with the use of Qt library. I store console text input in std::string , and then i'm using QSocket to post it on irc chat. But the problem is im want to use special signs (polish letters), which dont appear properly on chat. What is the problem? The way i use QSocketis:

void Socket::poster(const QByteArray send)    
{
    mSocket->write(send);
    mSocket->flush();
    mSocket->reset();
}

QByteArray i create from std::string and std::cin

he code's long so i only post the parts crucial for the specific functonality which fails

Socket class (which is the main class in the program, providing data to other classes):

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
protected:
    QSslSocket *mSocket;
--------------------

    connect(mSocket, SIGNAL(readyRead()),
            this, SLOT(readyReady())
--------------------
//console input:
    QThread *thread = new QThread;
    consoleInput = new ConsoleInput();
    consoleInput->startConsole(thread, mSocket);
    consoleInput->moveToThread(thread);
    thread->start();

-------------------
void Socket::readyReady()
{
    QString data;
    data2 = data;
    mSocket->ReadOnly;
    while(mSocket->canReadLine())
    {
    data = mSocket->readLine();
    }
    mSocket->reset();
}


---------------------
void Socket::poster(const QByteArray send)   //sending to irc from many classes news, console itd
{
    mSocket->write(send);
    mSocket->flush();
    mSocket->reset();
}
-------------------
ConsoleInput class (which takes console input, which is later sent to irc chat):
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


void ConsoleInput::run()
{
    std::cout << "!ConsoleInput::run()" << "\n";

    while(1){
    std::string input;
    std::getline(std::cin, input);
    determineOption(input);

    if(input[0] != '/' || input[0] != '\\')
        postInput(input);

    input.clear();
    }
}


----------------------------------

void ConsoleInput::postInput(std::string &input)
{
    if(input[0]=='/')
        return; //this prevents bot poting "/command" to channel
    std::string lineToPost;

    std::cout << "!lineToPost - input " << input << "\n";
    ColourManipulation c;
    lineToPost = "PRIVMSG #grunge " + c.addColours(input) + "\r\n";
    emit mySignal(QByteArray::fromStdString(lineToPost)); // problem
}
black_gay
  • 143
  • 7
  • please provide a [mre] – eyllanesc Apr 17 '20 at 17:43
  • I posted more code. – black_gay Apr 17 '20 at 19:22
  • console may not support non-ascii characters by default – Vladimir Bershov Apr 17 '20 at 22:26
  • I changed console encoding in windows in "Administrative language settings" and "Beta: Use Unicode UTF-8 for worldwide language support", now it shows 65001(UTF-8) but the problem remains Also i tried all the possible encodings in: QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextDecoder *decoder = codec->makeDecoder(); QString string = decoder->toUnicode(send); delete decoder; mSocket->write(send); – black_gay Apr 17 '20 at 23:18
  • @black_gay do cin/cout accept & show national symbols? – Vladimir Bershov Apr 18 '20 at 13:25
  • It appeared that setting windows console to utf-8 with the option "Beta: Use Unicode UTF-8 for worldwide language support" doesnt make std::cin or getline work as expected. Anyways it can be solved by using text editor widget in Qt. – black_gay Apr 19 '20 at 15:06
  • ut seems like also adding colours from a legit utf-8 source - a txt file, disrupts their apperance on chat, using "\x03""06" + char + "\x03"; For example what i post to irc is: 04m13u04s04z06─13ů06 04p06e13w13n06i06e uwa┼╝a─ç ┼╝eby si─Ö nie pozabija─ç a­čĺÄie spali─ç cha┼éupy , where only the coloured part is disrupted. I dont understand how it happens as i follow this example: "\x0304,02Example\x03" – black_gay Apr 19 '20 at 15:06

1 Answers1

0

Make sure std::cin/cout can accept & show non-ascii characters

Check the code can accept & show non-ascii characters:

std::string input;
std::getline(std::cin, input);
std::cout << input;

If you don't have problems with non-ascii characters in console itself

You need:

  1. Know in which encoding the data originally comes from console to std::string &input.

std::string type per se uses no encoding -- it will return the bytes you put in it - What encoding does std::string.c_str() use?.

  1. Import the bytes into QString using necessary encoding convertion

  2. Export the resulting QString to UTF-8 encoded QByteArray (QByteArray itself is just an array of bytes too).

  3. Write the QByteArray to a socket.


You can write something like the following:

/*
From doc: QTextCodec::codecForLocale() 
Returns a pointer to the codec most suitable for this locale.
The codec will be retrieved from ICU where that backend is in use, 
otherwise it may be obtained from an OS-specific API. 
In the latter case, the codec's name may be "System".    
*/
QTextCodec *codec = QTextCodec::codecForLocale(); // In most cases, it is not UTF-8

// Or set the encoding explicitly:
//QTextCodec *codec = QTextCodec::codecForName("Shift-JIS"); // put your input encoding here

QTextDecoder *decoder = codec->makeDecoder();

QByteArray chunk = QByteArray::fromStdString(input);

QString string = decoder->toUnicode(chunk);
delete decoder;

emit mySignal(string.toUtf8());

Be note that you can avoid std::string and use QString only:

QString is more comfortable to use, and, once received the data correctly, it always stores data in the same known format internally, despite of std::string, which has no idea what data it stores.

How to read from console to QString directly:

QTextStream in(stdin);
in.setCodec(<your console codec>);

QString input = in.readLine();    

See QTextCodec and QTextStream.

Read also The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

Vladimir Bershov
  • 2,701
  • 2
  • 21
  • 51