Input text in graphics in C programming - c

I am making a project in C. Its simple, just a Hangman Game.
Got the logic already cause I've done that only in console.
Now, I'm trying to do it in C again with GRAPHICS. I am using Turbo C.
I've read some of the functions of graphics.h: so far I've seen outtext() / outtextxy() something like that. It can print a string.
Can you input a char or string in graphics? Searched a lot but seen nothing.
Seen only drawing shapes examples.
How do you input characters, integers etc. in the graphics mode?

From memory, while you can use regular stdio functions printf, scanf, and gets, the graphics driver will paint them over your screen onto a "virtual cursor" position and scroll the screen when it reaches the bottom. You can use the nonstandard conio.h functions such as gotoxy and attempt to position the cursor, but it's still a mediocre way of inputting text, messing up the graphics stuff. You also cannot use the fancy fonts!
So use getch to read characters without showing them; update a string buffer (manually handling special keys such as Backspace and Return), and draw that on the screen using a font of your choice.
A short sample snippet of code to get you started:
#define MAX_INPUT_LEN 80
char inputbuf[MAX_INPUT_LEN];
int input_pos = 0;
then, in your main loop
int the_end = 0;
do
{
outtextxy (0,0, inputbuf);
c = getch();
switch (c)
{
case 8: /* backspace */
if (input_pos)
{
input_pos--;
inputbuf[input_pos] = 0;
}
break;
case 13: /* return */
the_end = 1;
break;
case 27: /* Escape = Abort */
inputbuf[0] = 0;
the_end = 1;
break;
default:
if (input_pos < MAX_INPUT_LEN-1 && c >= ' ' && c <= '~')
{
inputbuf[input_pos] = c;
input_pos++;
inputbuf[input_pos] = 0;
}
}
} while (!the_end);
Before you draw the text, make sure to erase the previous line! I left that out because it's been too long ago I used Turbo-C.

For taking input from used.. you can use scanf function similar to how we take input in any non-graphics c program.

You can do this by using normal scanf function. And by using sprintf copy a integer/whatever variable into a string. Now you can use outtextxy to set the string in specified location using x,y axis. Check geeksforgeeks to learn sprintf syntax.
I know it is too late. Hope it helps someone else.!

Related

Moving cursor in C using atmega16

We're trying to make a project using atmega 16 and C language. The problem is that whenever we want to move a cursor, it goes to random places instead of moving one character right/left.
Our first idea was just
LCD_command(0x10);
for going left. It didn't work although we are sure it should (turning off the cursor works in the same function). We also tried:
uint8_t position = 0;
[...]
void whichButton(){
whatsPressed = keybord();
switch (whatsPressed):
case 1:
{
position = position + 1;
GoToXY (position, 0);
}
case 2:
{
position = position - 1;
GoToXY (position, 0); //for going left
}
}
Has anybody got any idea how to move it?

c doesn't print "┌──┐" character correctly

Good afternoon, I'm facing a problem on my c code and I don't know what is causing it.
Every time I try to print characters like these: "┌──┐" my program simply prints some strange characters, like on this screenshot:
I'm using Qt Creator on Windows, with Qt version 5.5.0 MSVC 64 bits. The compiler is the Microsoft Visual C++ Compiler 12.0 (amd64).
I tried changing the locale but with no success. The only way I found to print these characters was to define them as int variables with the ASCII code and printing them, but it led to some really extensive and ugly coding, like this:
int cSupEsq = 218; //'┌'
int cSupDir = 191; //'┐'
int cInfEsq = 192; //'└'
int cInfDir = 217; //'┘'
int mVert = 179; //'│'
int mHor = 196; //'─'
int espaco = 255; //' '
int letraO = 111; //'o'
//Inicia limpando a tela da aplicação
clrscr();
//Linha 1
printf("%c", cSupEsq);
for (i = 1; i < 79; i++) { printf("%c", mHor); }
printf("%c", cSupDir);
Is there any way I can make the program treat these characters correctly? What could be causing this problem?
Your solution to use the OEM code points is the right way to go, codepage 850/437 is the default code page for the console and therefore should work. You could also use SetConsoleOutputCP to ensure the correct code page is used for the console.
Having said that, what is happening when you do not use your workaround is that the source file is being saved using a different codepage ie. not codepage 850/437. The in memory representation of the source code is Unicode (probably UTF-8), when you save the file the in memory representation of the characters are mapped to the target code page for the file.
What you can do is to save the file using the 850/437 codepage as the target, I don't know how you do this in Qt Creator (If you can at all), in Visual Studio for example you can select the down arrow on the Save button and select "Save with encoding", you can then proceed to select the target codepage, in your case code page 850. This will ensure that the in memory code points are mapped correctly to the file to be compiled.
I hope that helps explain the issue.
It shouldn't be necessary to print the characters one at a time. Instead, you can use an escape sequence:
printf("\xDA\xBF\xC0\xD9\xB3\xC4\xFF");

How do i stop the blocking?

Hey all I've asked this question a few times in the past few days but I just don't get it...I basically want to have the while loop for the Beep command executed in the background while the user can interact with the available case statements (only one shown..there are others)....i keep getting blocked and everytime i want the beep to make a sound constantly i block the rest of my program...I have to use Beep so please don't suggest any other functionality..
here's a sample code...
while( keypress != 'q' || keypress != 'Q')
{
x = Beep(x);
while (x == 1)
Beep(350,300);
alarm_t current;
keypress = _getch();
switch(keypress){
case 'h':
sprintf_s(current.message,"high alarm");
current.timeOfEvent = time(NULL);
recordEvent(current);
break;
Now...my issue is with the while loop and the Beep command....here is what i call to Beep(x)
int Beep(int y)
{
return y;
}
So basically i am trying to call a function outside of my current cpp file to just compare x and y, and return y as being equivalent to x...i thought this might avoid blocking but it doesn't...
Your while loop around beep just won't work and _getch is blocking. So it will just block until there's a character.
Depending what platform you are on, you need something like kbhit (and if you google that you will find alternatives for other platforms). ie it's not standard C functionality and platform specific.
kbhit will return true or false depending if there is a character or not.
So you can do:
while(!key_is_quit(ch))
{
Beep();
if(kbhit())
{
ch = getch();
// switch....
}
}

Can't Read (!##$...and Capital Letters) from console with ReadConsoleInput

have wrote this app which reads input from console.
for(; ; )
{
GetNumberOfConsoleInputEvents(stdinInput, &numEvents);
if (numEvents != 0) {
INPUT_RECORD eventBuffer;
ReadConsoleInput(stdinInput, &eventBuffer, 1, &numEventsRead);
if (eventBuffer.EventType == KEY_EVENT) {
if(eventBuffer.Event.KeyEvent.bKeyDown)
{
printf("%c",eventBuffer.Event.KeyEvent.uChar.AsciiChar);
dataBuffer[bufferLen++] = eventBuffer.Event.KeyEvent.uChar.AsciiChar;
dataBuffer[bufferLen] = '\0';
if ( dataBuffer[bufferLen] == 99 || eventBuffer.Event.KeyEvent.uChar.AsciiChar == '\r' ) {
printf("User Wrote: %s\n",dataBuffer);
memset(dataBuffer,0,sizeof(dataBuffer));
bufferLen = 0;
}
}
}
}
}
It puts the data on a buffer and then it prints out the buffer. The problem occurs when im using Shift or CapsLock to write Capital letters or ! # # $ % characters. Then it prints out NOTHING.
Ive tried something with the VK_LSHIFT code but didn't worked.
Also if try to write something in other language than English it prints out something like this ▒├╞▒├╞▒├│▒├│ It cannot recognize the other language.
Can someone give me a hint on how to fix those problems ?
Thanks!
ReadConsoleInput returns events for each keystroke. For example, if you type SHIFT+A to get a capital A then you'll receive four key events: SHIFT down, A down, A up, SHIFT up.
The SHIFT key does not have a corresponding ASCII code so eventBuffer.Event.KeyEvent.uChar.AsciiChar is set to zero. This zero terminates the string you are building in dataBuffer so you don't see anything typed after the SHIFT key.
The simplest fix is to ignore any key event with an ASCII code of zero.
Additionally, if you want this to work well with foreign languages you might do better to use ReadConsoleInputW and eventBuffer.Event.KeyEvent.uChar.UnicodeChar. Better yet, compile it all as a Unicode app.

erasing terminal output on linux

I was writing a command line program which will have a status bar, much like wget.
The main problem I'm facing is: how do I delete what I've already sent into stdout/stderr?
I had on idea: use the backspace char '\b' and erase the output I've sent. Is that the best way? Is it the only way? Is there a better way?
PS: I don't want to use anything like ncurses. Plain old C please.
Thanks
EDIT:
Can I also go up and/or down? Example: I have 10 lines of output, I want to change the 3rd line from Doing ABC to ABC: Done. How can I do that?
Also, can anyone post more details about what VT102 characters are? What are its capabilities? Please post good links on this if you have any.
Thanks
The basic formatting control characters are backspace (\b), tab (\t), newline (\n), and carriage return (\r). If you need more than that then you can use ANSI X3.64 / ISO/IEC 6429 / ECMA-48 escape sequences; at least the VT100 subset is recognized by most modern terminals and emulators. An advantage of using ncurses is that it will look up the capabilities of your particular terminal and so it will work even if your terminal uses a different set of escape sequences.
You have to remember that as far as the regular stdio routines are concerned, stdout is just a byte stream with no inherent display characteristics; that depends on the target device, which can be anything from a regular VT100-style terminal to a hardcopy terminal to a sheet-fed printer to a plotter to whatever.
IMO, you're far better off using a library like ncurses than trying to hack together your own display management code with VT100 escape codes, even for a relatively simple task like this. I know you want to stick with "plain old C", but this is a task that falls outside the bounds of plain old C.
Use '\r' to return to the beginning of the line and possibly rewrite the whole line.
Look for VT102 control sequences - these are character sequences ESC ... to control your terminal.
There is also the possiblity of using Ncurses, which is a library for Textual UI, where this kind of behaviour should have some support. However, it may be overkill for something like this.
A slight variation on your own solution:
You can also print a carriage return (\r), which will return you to the start of the line.
It is a progressbar for bash.
function gauge()
{
progress="$1"
total="$2"
width=`tput cols`
let gwidth=width-7
if [ "$total" == "0" ]; then
percent=100
else
set +e
let percent=progress*100/total;
set -e
fi
set +e
let fillcount=percent*gwidth/100
let nofillcount=gwidth-fillcount
set -e
fill="";
if [ "$fillcount" -gt "0" ]; then
for i in `seq $fillcount`; do
fill="$fill""|"
done
fi;
nofill=""
if [ "$nofillcount" -gt "0" ]; then
for i in `seq $nofillcount`; do
nofill="$nofill"" ";
done
fi
echo -e -n "\r[""$fill""$nofill""] ""$percent""%";
}
About the progress bar: something like this?
#include <stdio.h>
#include <unistd.h>
typedef enum
{
false=0,
true=!false
} bool;
typedef struct
{
/* Start delimiter (e.g. [ )*/
char StartDelimiter;
/* End Delimiter (e.g. ] )*/
char EndDelimiter;
/* Central block (e.g. = )*/
char Block;
/* Last block (e.g. > ) */
char CurBlock;
/* Width of the progress bar (in characters) */
unsigned int Width;
/* Maximum value of the progress bar */
double Max;
/* True if we have to print also the percentage of the operation */
bool PrintPercentage;
/* True if the bar must be redrawn;
note that this must be just set to false before the first call, the function then will change it by itself. */
bool Update;
} ProgressBarSettings;
/* Prints/updates the progress bar */
void PrintProgressBar(double Pos, ProgressBarSettings * Settings);
/* Inits the settings of the progress bar to the default values */
void DefaultProgressBar(ProgressBarSettings * Settings);
int main()
{
int i;
/* Init the bar settings */
ProgressBarSettings pbs;
DefaultProgressBar(&pbs);
pbs.Max=200;
pbs.Width=60;
printf("Progress: ");
/* Show the empty bar */
PrintProgressBar(0,&pbs);
for(i=0;i<=pbs.Max;i++)
{
/* Wait 50 msec */
usleep(50000);
/* Update the progress bar */
PrintProgressBar(i,&pbs);
}
puts(" Done");
return 0;
}
/* Inits the settings of the progress bar to the default values */
void DefaultProgressBar(ProgressBarSettings * Settings)
{
Settings->StartDelimiter='[';
Settings->EndDelimiter=']';
Settings->Block='=';
Settings->CurBlock='>';
Settings->PrintPercentage=true;
Settings->Update=false;
Settings->Max=100;
Settings->Width=40;
}
/* Prints/updates the progress bar */
void PrintProgressBar(double Pos, ProgressBarSettings * Settings)
{
/* Blocks to print */
unsigned int printBlocks=(unsigned int)(Settings->Width*Pos/Settings->Max);
/* Counter */
unsigned int counter;
/* If we are updating an existing bar...*/
if(Settings->Update)
{
/* ... we get back to its first character to rewrite it... */
for(counter=Settings->Width+2+(Settings->PrintPercentage?5:0);counter;counter--)
putchar('\b');
}
else
Settings->Update=true; /* next time we'll be updating it */
/* Print the first delimiter */
putchar(Settings->StartDelimiter);
/* Reset the counter */
counter=Settings->Width;
/* Print all the blocks except the last; in the meantime, we decrement the counter, so in the end we'll have
the number of spaces to fill the bar */
for(;printBlocks>1;printBlocks--,counter--)
putchar(Settings->Block);
/* Print the last block; if the operation ended, use the normal block, otherwise the one for the last block */
putchar((Settings->Max==Pos)?Settings->Block:Settings->CurBlock);
/* Another block was printed, decrement the counter */
counter--;
/* Fill the rest of the bar with spaces */
for(;counter;counter--)
putchar(' ');
/* Print the end delimiter */
putchar(Settings->EndDelimiter);
/* If asked, print also the percentage */
if(Settings->PrintPercentage)
printf(" %3d%%",(int)(100*Pos/Settings->Max));
/* Flush the output buffer */
fflush(stdout);
};
Note: the unistd.h and usleep thing is just to fake the progress of an operation, the progress bar code itself just uses the standard library. Its only assumptions about the output stream are that \b actually gets to the previous written character. I tried it successfully on Windows and Linux (with gnome-terminal), don't know if it doesn't work correctly with some terminal emulators.
Sorry for the excessive amount of comments, I wrote it for another forum where I needed to explain pratically every line of the code to a C newbie.

Resources