A common request in the Allegro forums is for a way to process player text input. cin doesn't work. The Allegro GUI does, but is simplistic and limiting (*cough* and ugly *cough*). Back when I wrote an article on the standard C++ string class, I wrote a small C++ program that stored player input in a std::string. Since then, I made a simpler C version that uses a char array. The code is very short and simple to use, so modifying it for your purposes (to word wrap, for example, if you want that) is dirt easy. I get asked for it often, so I'm just submitting it for ease of finding.
Both the C and C++ version just take the input and print it onscreen. The C++ version lets you move the caret around, processes the Insert key to toggle replacing and inserting, and lets you both delete and backspace. None of that's really necessary; It's only there because the string class makes it so easy. The functionality can be added to the C version easily enough, I know. But I'm a lazy spoilt C++ coder, so all effort to that end is left as an exercise to the reader.
Here is the C version.
// edittext.c
#include
#define BUFFERSIZE 128
#define WHITE makecol(255, 255, 255)
int main()
{
BITMAP* buffer = NULL;
char edittext[BUFFERSIZE];
int caret = 0;
/* typical Allegro initialization */
allegro_init();
install_keyboard();
set_gfx_mode(GFX_AUTODETECT, 320, 240, 0, 0);
buffer = create_bitmap(320, 240);
do
{
if(keypressed())
{
int newkey = readkey();
char ASCII = newkey & 0xff;
char scancode = newkey >> 8;
/* a character key was pressed; add it to the string */
if(ASCII >= 32 && ASCII <= 126)
{
if(caret < BUFFERSIZE - 1)
{
edittext[caret] = ASCII;
caret++;
edittext[caret] = '\0';
}
}
else if(scancode == KEY_BACKSPACE)
{
if (caret > 0) caret--;
edittext[caret] = '\0';
}
}
/* all drawing goes here */
clear(buffer);
textout(buffer, font, edittext, 0, 10, WHITE);
vline(buffer, caret * 8, 8, 18, WHITE);
blit(buffer, screen, 0, 0, 0, 0, 320, 240);
}
while(!key[KEY_ESC]);
destroy_bitmap(buffer);
return 0;
}
END_OF_MAIN()
The C++ version, as stated, is slightly more robust. This is essentially the code from my original article.
C++:
// edittext.cpp
#include
#include
using namespace std;
#define WHITE makecol(255, 255, 255)
int main()
{
// typical Allegro initialization
allegro_init();
install_keyboard();
set_gfx_mode(GFX_AUTODETECT, 320, 240, 0, 0);
// all variables are here
BITMAP* buffer = create_bitmap(320, 240); // initialize the double buffer
string edittext; // an empty string for editting
string::iterator iter = edittext.begin(); // string iterator
int caret = 0; // tracks the text caret
bool insert = true; // true if text should be inserted
// the game loop
do
{
while(keypressed())
{
int newkey = readkey();
char ASCII = newkey & 0xff;
char scancode = newkey >> 8;
// a character key was pressed; add it to the string
if(ASCII >= 32 && ASCII <= 126)
{
// add the new char, inserting or replacing as need be
if(insert || iter == edittext.end())
iter = edittext.insert(iter, ASCII);
else
edittext.replace(caret, 1, 1, ASCII);
// increment both the caret and the iterator
caret++;
iter++;
}
// some other, "special" key was pressed; handle it here
else
switch(scancode)
{
case KEY_DEL:
if(iter != edittext.end()) iter = edittext.erase(iter);
break;
case KEY_BACKSPACE:
if(iter != edittext.begin())
{
caret--;
iter--;
iter = edittext.erase(iter);
}
break;
case KEY_RIGHT:
if(iter != edittext.end()) caret++, iter++;
break;
case KEY_LEFT:
if(iter != edittext.begin()) caret--, iter--;
break;
case KEY_INSERT:
insert = !insert;
break;
default:
break;
}
}
// clear screen
clear(buffer);
// output the string to the screen
textout(buffer, font, edittext.c_str(), 0, 10, WHITE);
// output some stats using Allegro's printf functions
textprintf(buffer, font, 0, 20, WHITE, "length: %d", edittext.length());
textprintf(buffer, font, 0, 30, WHITE, "capacity: %d", edittext.capacity());
textprintf(buffer, font, 0, 40, WHITE, "empty?: %d", edittext.empty());
if(insert)
textout(buffer, font, "Inserting", 0, 50, WHITE);
else
textout(buffer, font, "Replacing", 0, 50, WHITE);
// draw the caret
vline(buffer, caret * 8, 8, 18, WHITE);
// blit to screen
blit(buffer, screen, 0, 0, 0, 0, 320, 240);
}while(!key[KEY_ESC]); // end of game loop
// clean up
destroy_bitmap(buffer);
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
return 0;
}
END_OF_MAIN()
I hope that was helpful to you. Comments, questions, feedback, etc. can be posted in the forums or sent to crbarry@mts.net.