International character input

I'm programming something that will have to take input of "international characters" (US-International layout), to put it short. For example, µ, altgr+m.
However, regardless of OS keyboard configuration, Allegro seams to react with keypresses anyway.
I've made the code to recognize a modifier + keypress, but my question is if there's a shortcut, so I don't have to code for all modifiers in specific. I mean, it clearly recognizes shift (event.keyboard.unichar will input both M and m just fine), so why not altgr too? Am I missing something?
Also, I wonder what's the case with non-QWERTY layouts and language support of other languages (say, Japanese keyboard layout).


If I switch to the US international layout, AltGr+M works fine in ex_keyboard_events. I get both a CHAR event for 'µ', and UP and DOWN events for both AltGr and M. My keyboard is actually French, don't know if that matters.

EDIT: Should mention that I'm on Windows 10. And tested with ex_keyboard_events from Allegro 5.0.5, that's what I had laying around.

Edgar Reynaldo

I edited something since I last posted this, forgot something important to add.

Instructions unclear: code now appends garbage whenever it stores a non-ASCII character (ex.: µ). (I'm joking, but it's true)

I tested ex_keyboard_events, on Windows, and it doesn't output the altgr characters, although I can see it (try to) render characters with accents (such as é).

1#define alt_gr_m 0xB5 /*µ*/ 2ALLEGRO_USTR_INFO *text_typed = al_ustr_new(""); 3... 4switch(event.type) 5 { 6 case ALLEGRO_EVENT_TIMER: 7 // game logic goes here. 8 if(key[ALLEGRO_KEY_ESCAPE]) 9 done = true; 10 11 for(int i = 0; i < ALLEGRO_KEY_MAX; i++) 12 key[i] &= KEY_SEEN; 13 14 redraw = true; 15 break; 16 17 case ALLEGRO_EVENT_KEY_CHAR: 18 switch(event.keyboard.keycode) 19 { 20 case ALLEGRO_KEY_LEFT: 21 if(caret_position>0) 22 { 23 caret_position--; 24 } 25 break; 26 case ALLEGRO_KEY_RIGHT: 27 if(caret_position<al_ustr_length(text_typed)) 28 { 29 caret_position++; 30 } 31 break; 32 case ALLEGRO_KEY_HOME: 33 caret_position=0; 34 break; 35 case ALLEGRO_KEY_BACKSPACE: 36 al_ustr_remove_chr(text_typed, caret_position-1); 37 if(caret_position>0) 38 { 39 caret_position--; 40 } 41 break; 42 case ALLEGRO_KEY_DELETE: 43 al_ustr_remove_chr(text_typed, caret_position); 44 break; 45 default: 46 if(event.keyboard.modifiers & ALLEGRO_KEYMOD_ALTGR) 47 { 48 switch(event.keyboard.keycode) 49 { 50 case ALLEGRO_KEY_M: 51 al_ustr_insert_chr(text_typed,caret_position,alt_gr_m); 52 caret_position++; 53 break; 54 default: 55 break; 56 } 57 } 58 al_ustr_insert_chr(text_typed,caret_position,event.keyboard.unichar); 59 caret_position++; 60 break; 61 } 62 //printf("%s \n",al_cstr(text_typed)); 63 break; 64... 65al_draw_ustr(font, al_map_rgb(255, 255, 255), 160, 130, 0, text_typed);

The problem here is a bit tricky to explain. It seems to be appending some garbage character by the end of the string. When I type the non-ASCII character, it seemingly types two characters (because of the caret), which always remains on the end of the string. The string renders up to before the intended non-ASCII character, but shows up back if it's the last one.


1 if(event.keyboard.modifiers & ALLEGRO_KEYMOD_ALTGR) 2 { 3 switch(event.keyboard.keycode) 4 { 5 case ALLEGRO_KEY_M: 6 al_ustr_insert_chr(text_typed,caret_position,alt_gr_m); 7 caret_position++; 8 break; 9 default: 10 break; 11 } 12 } 13 else 14 { 15 al_ustr_insert_chr(text_typed,caret_position,event.keyboard.unichar); 16 caret_position++; 17 }

If Ctrl sets event.keyboard.unichar to 13 (A = 1, B = 2, etc), what does AltGr change it to? Have you tried adding an else if AltGr is not pressed?


I figured out the issue. What DanielH mentioned is right, the code is also putting the key without altgr together, I need to make sure it doesn't.
The issue is this: it wasn't garbage. What happens is that in UTF-8, those non-ASCII characters are usually represented by 2 bytes, instead of just one in the case of ASCII. But then, I didn't account the extra length of such characters with the caret. In the end, the caret would then insert data IN BETWEEN the two bytes of the non-ASCII UTF-8 characters, resulting in usually unreadable characters, and corrupting the rest of the string for matters of rendering (or maybe rendering characters that the font didn't have).
I modified this code a bit too much to quote, but in short, it revolves around using al_ustr_offset. Whenever I need a specific position in the string, regarding characters, not bytes, using al_ustr_offset will count the characters in the string, not the bytes. So the caret logic stays the same, but al_ustr_insert_chr(text_typed, caret_position, event.keyboard.unichar); should use al_ustr_offset(text_typed,caret_position) instead of just caret_position.

Thread #618661. Printed from