Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [a5] keyboard.unichar help needed

This thread is locked; no one can reply to it. rss feed Print
[a5] keyboard.unichar help needed
Desmond Taylor
Member #11,943
May 2010
avatar

I am making input boxes in my game and I am having problems converting the unichar to char. How would I do this.

The reason I'm using unichar than keycode is because it's less handling needed for special characters.

Matthew Leverton
Supreme Loser
January 1999
avatar

Use a single ALLEGRO_USTR to store multiple unichars (there are plenty of functions for manipulating an ALLEGRO_USTR), and then use the various _ustr drawing functions to output to a bitmap.

Desmond Taylor
Member #11,943
May 2010
avatar

Sorry but I really do not get any of that web page :S I use std::string to store my text. It's only converting from unichar to char I need.

Thomas Fjellstrom
Member #476
June 2000
avatar

Use an ALLEGRO_USTR instead of a std::string. You get free unicode support that way.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Desmond Taylor
Member #11,943
May 2010
avatar

I've been trying and I don't get it. I get the unicode number all the time.

jmasterx
Member #11,410
October 2009

#SelectExpand
1inline size_t encodeUtf8(char outputChars[], int inputUnichar) const 2 { 3 size_t uc = inputUnichar; 4 5 if (uc <= 0x7f) { 6 outputChars[0] = static_cast<char>(uc); 7 return 1; 8 } 9 10 if (uc <= 0x7ff) { 11 outputChars[0] = 0xC0 | ((uc >> 6) & 0x1F); 12 outputChars[1] = 0x80 | (uc & 0x3F); 13 return 2; 14 } 15 16 if (uc <= 0xffff) { 17 outputChars[0] = 0xE0 | ((uc >> 12) & 0x0F); 18 outputChars[1] = 0x80 | ((uc >> 6) & 0x3F); 19 outputChars[2] = 0x80 | (uc & 0x3F); 20 return 3; 21 } 22 23 if (uc <= 0x10ffff) { 24 outputChars[0] = 0xF0 | ((uc >> 18) & 0x07); 25 outputChars[1] = 0x80 | ((uc >> 12) & 0x3F); 26 outputChars[2] = 0x80 | ((uc >> 6) & 0x3F); 27 outputChars[3] = 0x80 | (uc & 0x3F); 28 return 4; 29 } 30 31 /* Otherwise is illegal. */ 32 return 0; 33 } 34 35};

This will convert UTF32 (unichar) to UTF-8.

#SelectExpand
1 inline size_t getUnicharLength(int c) const 2 { 3 4 size_t uc = c; 5 6 if (uc <= 0x7f) 7 return 1; 8 if (uc <= 0x7ff) 9 return 2; 10 if (uc <= 0xffff) 11 return 3; 12 if (uc <= 0x10ffff) 13 return 4; 14 /* The rest are illegal. */ 15 return 0; 16}

this will tell you how big your char buffer needs to be for the previous function.

Desmond Taylor
Member #11,943
May 2010
avatar

I have it working by doing this:

#SelectExpand
1 case ALLEGRO_EVENT_KEY_CHAR: 2 { 3 char buf[1]; 4 al_utf8_encode( buf, this->event.keyboard.unichar ); 5 printf( "%s", buf ); 6 } 7 break;

Another noobie question in this simular matter.

How do I blank the buffer before using al_utf8_encode? as some special keys mess it up :/

jmasterx
Member #11,410
October 2009

the (somewhat) proper way:

 case ALLEGRO_EVENT_KEY_CHAR:
        {
            char buf[5];
            for(int i = 0; i < 5; ++i)
                buf[i] = NULL;
              
            al_utf8_encode( buf, this->event.keyboard.unichar );
            printf( "%s", buf );
        }
        break;

Because do not forget, utf-8 != to ascii, it has ascii + tons more so it needs up to 4 chars + NULL terminating which is why you need to use the function to get the size and to NULL size + 1.

ALLEGRO_USTR makes this easier, but I use std::string because my GUI API is backend independent.

Desmond Taylor
Member #11,943
May 2010
avatar

Matthew Leverton
Supreme Loser
January 1999
avatar

Definitely some bizarre code in this thread...

ALLEGRO_USTR *foo = al_ustr_new("");
al_ustr_append_chr(foo, unichar);

printf("%s", al_cstr(foo)); // to convert to a C string

al_draw_ustr(font, color, x,y, 0, foo);

Desmond Taylor
Member #11,943
May 2010
avatar

Thanks, That one works better. I was just about to post this video showing an error I get when rendering buttons afterwards :P

Here is the video anyway :)

http://www.youtube.com/watch?v=M_A_Ty71JlY

This is my new case

#SelectExpand
1 case ALLEGRO_EVENT_KEY_CHAR: 2 { 3 if ( this->event.keyboard.keycode == ALLEGRO_KEY_BACKSPACE ) 4 { 5 this->input->set_special_key_state( KEY_STATE_BACKSPACE ); 6 } 7 else if ( this->event.keyboard.keycode == ALLEGRO_KEY_ENTER ) 8 { 9 this->input->set_special_key_state( KEY_STATE_ENTER ); 10 } 11 else if ( this->event.keyboard.keycode == ALLEGRO_KEY_TAB ) 12 { 13 this->input->set_special_key_state( KEY_STATE_TAB ); 14 } 15 else 16 { 17 ALLEGRO_USTR* ustr = al_ustr_new( "" ); 18 al_ustr_append_chr( ustr, this->event.keyboard.unichar ); 19 this->input->set_last_repeat_char( al_cstr( ustr ) ); 20 this->input->set_special_key_state( KEY_STATE_NONE ); 21 al_ustr_free( ustr ); 22 } 23 } 24 break;

Matthew Leverton
Supreme Loser
January 1999
avatar

You shouldn't create a new ustr on every key press. Have a single ustr for each text box. Append the new character to it, and draw it to the bitmap.

I don't know what your input class is doing, but this is very simple:

#SelectExpand
1 case ALLEGRO_EVENT_KEY_CHAR: 2 { 3 if ( this->event.keyboard.keycode == ALLEGRO_KEY_BACKSPACE ) 4 { 5 // may need to check if the ustr is empty 6 al_ustr_remove_chr(this->ustr, al_ustr_offset(this->ustr, -1)); 7 } 8 else if ( this->event.keyboard.keycode == ALLEGRO_KEY_ENTER ) 9 { 10 this->input->set_special_key_state( KEY_STATE_ENTER ); 11 } 12 else if ( this->event.keyboard.keycode == ALLEGRO_KEY_TAB ) 13 { 14 this->input->set_special_key_state( KEY_STATE_TAB ); 15 } 16 else 17 { 18 al_ustr_append_chr( this->ustr, this->event.keyboard.unichar ); 19 } 20 } 21 break;

Use the various draw_ustr functions to output the text.

Desmond Taylor
Member #11,943
May 2010
avatar

I have one event queue that handles everything since it's a simple game to re-create. The input field is a class and the data is stored in the input box due to needing them later on. It's a clone of Endless Online since the server was taken down by the owner. It's not been updated since 2007, the site was last updated 2009 so I'm creating the entire thing again since I used to play that daily :( Miss it to be honest. Anyway, I am making a clone of his MMORPG :)

Thomas Fjellstrom
Member #476
June 2000
avatar

The input field is a class and the data is stored in the input box due to needing them later on.

Yes, and if you make it an `ALLEGRO_USTR *` instead of a `char *`, you can do as Matthew says, and save the memory allocation and excess copying.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Desmond Taylor
Member #11,943
May 2010
avatar

Yes, and if you make it an `ALLEGRO_USTR *` instead of a `char *`, you can do as Matthew says, and save the memory allocation and excess copying.

Yes, but I'm too used to std::string functions for appending text ect so it's copied to that. :/

I shall read more about ALLEGRO_USTR* for sure but for now I shall use std::string since I know it better :)

Go to: