So I was browsing the Internet for a project and stumbled upon this piece of code. It runs perfectly until the point you enter a website(include "www" :P) and press Enter and then boom! The program terminates, no error message, nothing.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <dos.h>
#include <string.h>
void initialize_graphics_mode();
int get_key();
void draw();
union REGS i, o;
main()
{
int key, i = 0, xpos, ypos, button;
char arr[200], temp[5], *ptr;
char a[] = "C:\\Progra~1\\Mozill~1\\firefox ";
strcpy(arr,a);
i = strlen(a);
initialize_graphics_mode();
draw();
while(1)
{
if(kbhit())
key = get_key();
if((key>=97&&key<=122)||(key>=65&&key<=90)||key==46||key==47||key==63)
{
arr[i] = key;
sprintf(temp,"%c",arr[i]);
outtext(temp);
if(getx()>470)
{
clearviewport();
moveto(5,2);
}
i++;
}
else if ( key == 13 )
{
arr[i] = '\0';
system(arr);
break;
}
else if ( key == 27 )
{
closegraph();
exit(EXIT_SUCCESS);
}
if(button==1&&xpos>=150&&xpos<=480&&ypos>=300&&ypos<=330)
{
system("C:\\Progra~1\\Mozill~1\\firefox programmingsimplified.com");
break;
}
key = -1;
}
closegraph();
return 0;
}
void initialize_graphics_mode()
{
int gd = DETECT, gm, errorcode;
initgraph(&gd,&gm,"C:\\TURBOC3\\BGI");
errorcode = graphresult();
if( errorcode != grOk )
{
printf("Graphics error : %s\n",grapherrormsg(errorcode));
printf("Press any key to exit...\n");
getch();
exit(EXIT_FAILURE);
}
}
int get_key()
{
i.h.ah = 0;
int86(22,&i,&o);
return( o.h.al );
}
void draw()
{
settextstyle(SANS_SERIF_FONT,HORIZ_DIR,2);
outtextxy(275,11,"Web Browser");
outtextxy(155,451,"<a> href=http://www.programmingsimplified.com"">www.programmingsimplified.com</a>");
outtextxy(5,105,"Enter URL : ");
rectangle(120,100,600,130);
setviewport(121,101,599,129,1);
moveto(5,1);
}
Could someone help me in understanding why this happens? and possibly a fix for this?
NOTE: + It is supposed to work if you have Mozilla Firefox. If you have any other browser, please edit the code accordingly.
I am running this on Turbo C++, what would I have to do in order to convert this code for Dev-C++?
Thanks in advance.
P.S: I'm new to C++ so elaborate as much as possible.
Related
I wrote a getSample(devicePath) function that reads raw input events from keyboard, however after running this function, ncurses doesn't display anything.
includes
#include <linux/input.h>
#include <unistd.h>
#include <fcntl.h>
#include <ncurses.h>
#include <vector>
#include <string>
getSample
const int KEY_PRESSED = 1;
const int KEY_RELEASED = 0;
std::vector<input_event> getSample(std::string devicePath) {
std::vector<input_event> events;
int fileDescriptor = open(devicePath.c_str(), O_RDONLY);
while (true) {
struct input_event event;
read(fileDescriptor, &event, sizeof(struct input_event));
if (event.type == EV_KEY)
if (event.value == KEY_PRESSED || event.value == KEY_RELEASED) {
if (event.code == 28 && event.value == KEY_PRESSED)
break;
events.push_back(event);
}
}
close(fileDescriptor);
return events;
}
main
int main() {
std::string devicePath = "/dev/input/by-id/"
"usb-Microsft_Microsoft_Wireless_Desktop_Receiver_3."
"1-event-kbd";
std::vector<input_event> sample = getSample(devicePath);
initscr();
printw("Hello World!");
refresh();
getch();
endwin();
return 0;
}
Is there a way to fix it?
Tip
Function getSample works correctly, because when I replace ncurses code with simple printf(), everything works fine
int main() {
std::string devicePath = "/dev/input/by-id/"
"usb-Microsft_Microsoft_Wireless_Desktop_Receiver_3."
"1-event-kbd";
std::vector<input_event> sample = getSample(devicePath);
for (unsigned int i = 0; i < sample.size(); i++)
printf("%d | %3d | %ld.%06ld\n", sample[i].value, sample[i].code,
(long)sample[i].time.tv_sec, (long)sample[i].time.tv_usec);
return 0;
}
I am trying to learn how to use graphics.h and conio.h libraries.I am developing a graphic program which i need to move a rectangle after keyboard input.ex: if player press right , rectangle should move right side.Problem is i don't know how to get user input.I need to get user input inside a loop continuous.Here is my code.Any help is appreciated(keyword,function name etc)
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>
void drawrect(int left,int top,int right,int bot);
int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");
drawrect(5,400,40,450); // default start position
firsttime=1;//counter for if its first time in for loop
int currentl=5;
int currentt=400;
int currentr=40;
int currentb=450;
if(firsttime==1)
{
//get user input and drawrectangle with new inputs
//if player press right add 5 to currentl and current r and
//redraw the rectangle
}
getch();
closegraph();
}
void drawrect(int left,int top,int right,int bot)
{
rectangle(left,top,right,bot);
}
You can use getch() or _getch() to read codes of keys and react on it. But some things you should think over.
1) loop is needed to perform continuois action in your program.
2) keys such as "arrow left", "arrow up", etc. is given by getch() as two codes - the first -32 and the second depends on key.
Use the following programm to see the loop example and to find codes for keys:
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
int main(void)
{
char ch;
printf("Press 'q' to exit prom program\n");
do{
ch = _getch();
printf("%c (%d)\n", ch, ch);
} while( ch != 'q');
}
Its solved this code works thanks for help
#include
#include
void drawrect(int left,int top,int right,int bot);
int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");
int firsttime=1;//counter for if its first time in for loop
int currentl=5;
int currentt=400;
int currentr=40;
int currentb=450;
char ch;
settextstyle(0, HORIZ_DIR, 1);
outtextxy(20, 20, "To start press 'S'");
ch = getch();
cleardevice();
drawrect(5,400,40,450); // default start position
while(ch!='q')
{
ch = getch();
switch (ch)
{
case KEY_RIGHT:currentr=currentr+5;
currentl=currentl+5;
break;
case KEY_LEFT:currentr=currentr-5;
currentl=currentl-5;
break;
}
cleardevice();
drawrect(currentl,currentt,currentr,currentb);
}
getch();
closegraph();
}
void drawrect(int left,int top,int right,int bot)
{
rectangle(left,top,right,bot);
}
I tried to write a program which hooks keyboard messages to pronounce the name of each key whenever it is pressed in Ubuntu (KDE); without interfering with normal action of keyboard in programs (just announcing the key name).
This is my program:
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
void SendPressKeyEvent(Display *display, XKeyEvent xkey)
{
Window current_focus_window;
int current_focus_revert;
XGetInputFocus(display, ¤t_focus_window, ¤t_focus_revert);
xkey.type = KeyPress;
xkey.display = display;
xkey.window = current_focus_window;
xkey.root = DefaultRootWindow(display);
xkey.subwindow = None;
xkey.time = 1000 * time(0);
xkey.x = 0;
xkey.y = 0;
xkey.x_root = 0;
xkey.y_root = 0;
xkey.same_screen = True;
XSendEvent(display, InputFocus, True, KeyPressMask, (XEvent *)(&xkey));
}
void SendReleaseKeyEvent(Display *display, XKeyEvent xkey)
{
Window current_focus_window;
int current_focus_revert;
XGetInputFocus(display, ¤t_focus_window, ¤t_focus_revert);
xkey.type = KeyRelease;
xkey.display = display;
xkey.window = current_focus_window;
xkey.root = DefaultRootWindow(display);
xkey.subwindow = None;
xkey.time = 1000 * time(0);
xkey.x = 0;
xkey.y = 0;
xkey.x_root = 0;
xkey.y_root = 0;
xkey.same_screen = True;
XSendEvent(display, InputFocus, True, KeyReleaseMask, (XEvent *)(&xkey));
}
void *TaskCode(void* arg)
{
switch(*(int*)arg)
{
case 38:
system("espeak -v en " "\"a\"");
}
return 0;
}
int main()
{
Display *display = XOpenDisplay(0);
if(display == 0)
exit(1);
XGrabKeyboard(display, DefaultRootWindow(display), True, GrabModeAsync, GrabModeAsync, CurrentTime);
XEvent event;
while(true)
{
XNextEvent(display, &event);
if(event.type == Expose)
{
}
if(event.type == KeyPress)
{
SendPressKeyEvent(display,event.xkey);
if(event.xkey.keycode == 38)
{
pthread_t thread;
int thread_arg = event.xkey.keycode;
pthread_create(&thread,0, TaskCode, (void*) &thread_arg);
}
}
if(event.type == KeyRelease)
SendReleaseKeyEvent(display,event.xkey);
}
XCloseDisplay(display);
}
This program is just for the key a which can be extended to other keys.
But when this program is running, some programs (e.g. Chromium) do not show the blinker (cursor) in their edit boxes. Also all KDE hotkeys become disabled.
How can this be fixed?
Here's my quick and dirty example
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <ctype.h>
int main ()
{
Display* d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
Window curFocus;
char buf[17];
KeySym ks;
XComposeStatus comp;
int len;
int revert;
XGetInputFocus (d, &curFocus, &revert);
XSelectInput(d, curFocus, KeyPressMask|KeyReleaseMask|FocusChangeMask);
while (1)
{
XEvent ev;
XNextEvent(d, &ev);
switch (ev.type)
{
case FocusOut:
printf ("Focus changed!\n");
printf ("Old focus is %d\n", (int)curFocus);
if (curFocus != root)
XSelectInput(d, curFocus, 0);
XGetInputFocus (d, &curFocus, &revert);
printf ("New focus is %d\n", (int)curFocus);
if (curFocus == PointerRoot)
curFocus = root;
XSelectInput(d, curFocus, KeyPressMask|KeyReleaseMask|FocusChangeMask);
break;
case KeyPress:
printf ("Got key!\n");
len = XLookupString(&ev.xkey, buf, 16, &ks, &comp);
if (len > 0 && isprint(buf[0]))
{
buf[len]=0;
printf("String is: %s\n", buf);
}
else
{
printf ("Key is: %d\n", (int)ks);
}
}
}
}
It's not reliable but most of the time it works. (It is showing keys I'm typing into this box right now). You may investigate why it does fail sometimes ;) Also it cannot show hotkeys in principle. Hotkeys are grabbed keys, and only one client can get a grabbed key. Absolutely nothing can be done here, short of loading a special X11 extension designed for this purpose (e.g. XEvIE).
Thanks to n.m.'s answer and parsa's comment, this is my final code:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void* TaskCode(void* parg)
{
int keycode = *((int*)parg);
cout<< "\n\n" << keycode << "\n\n";
if(keycode == XKeysymToKeycode(XOpenDisplay(0),'a'))
system("espeak -v en " "\"a\"");
delete (int*)parg;
return 0;
}
void Action(int keycode)
{
pthread_t thread;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setdetachstate(&attrs,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&attrs, 1000);
int* pthread_arg = new int;
*pthread_arg = keycode;
pthread_create(&thread,&attrs, TaskCode, (void*) pthread_arg);
}
int MyX11ErrorHandler(Display *, XErrorEvent *error_event)
{
cout << "\n\n" "An X11-Functions error occured. Probably the focused window was closed.""\n"
"This error will be ignored." "\n";
cout<< "error_code: " << (unsigned)error_event -> error_code << "\n";
cout<< "minor_code: " << (unsigned)error_event -> minor_code << "\n";
cout<< "request_code: " << (unsigned)error_event -> request_code << "\n";
cout<< "resourceid: " << error_event -> resourceid << "\n";
cout<< "serial; " << error_event -> serial << "\n";
cout<< "type: " << error_event -> type << "\n\n";
return 0;
}
int main()
{
Display* display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
Window current_focus_window;
int revert;
XSetErrorHandler(MyX11ErrorHandler);
XGetInputFocus(display, ¤t_focus_window, &revert);
XSelectInput(display,current_focus_window,KeyPressMask | KeyReleaseMask | FocusChangeMask);
while(true)
{
XEvent event;
XNextEvent(display, &event);
switch (event.type)
{
case FocusOut:
if(current_focus_window != root)
XSelectInput(display, current_focus_window, 0);
XGetInputFocus(display, ¤t_focus_window, &revert);
if(current_focus_window == PointerRoot)
current_focus_window = root;
XSelectInput(display, current_focus_window, KeyPressMask|KeyReleaseMask|FocusChangeMask);
break;
case KeyPress:
Action(event.xkey.keycode);
break;
}
}
}
Add these to a Qt Creator's project .pro file:
LIBS += -lX11
LIBS += -lpthread
LIBS += -lXtst
Any improvement suggestions is appreciated.
To archive I also add my final code with grabbing:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
void* TaskCode(void* parg)
{
int keycode = *((int*)parg);
cout<< "\n\n" << keycode << "\n\n";
system("espeak -v en " "\"a\"");
delete (int*)parg;
return 0;
}
void SendKeyEvent(Display *display, XEvent event)
{
Window current_focus_window;
XKeyEvent& xkey = event.xkey;
int current_focus_revert;
XGetInputFocus(display, ¤t_focus_window, ¤t_focus_revert);
xkey.state = Mod2Mask;
XSendEvent(display, InputFocus, True, xkey.type, (XEvent *)(&event));
}
int GrabKey(Display* display, Window grab_window, int keycode)
{
unsigned int modifiers = Mod2Mask; // numlock on
//Window grab_window = DefaultRootWindow(display);
Bool owner_events = True;
int pointer_mode = GrabModeAsync;
int keyboard_mode = GrabModeAsync;
XGrabKey(display, keycode, modifiers, grab_window, owner_events, pointer_mode, keyboard_mode);
return keycode;
}
void UngrabKey(Display* display, Window grab_window, int keycode)
{
unsigned int modifiers = Mod2Mask; // numlock on
// Window grab_window = DefaultRootWindow(display);
XUngrabKey(display,keycode,modifiers,grab_window);
}
void Action(int keycode)
{
pthread_t thread;
int* pthread_arg = new int;
*pthread_arg = keycode;
pthread_create(&thread,0, TaskCode, (void*) pthread_arg);
}
int main()
{
Display* display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
XEvent event;
int keycode = XKeysymToKeycode(display,'a');
GrabKey(display,root,keycode);
XSelectInput(display, root, KeyPressMask | KeyReleaseMask);
while(true)
{
XNextEvent(display, &event);
switch(event.type)
{
case KeyPress:
Action(event.xkey.keycode);
case KeyRelease:
SendKeyEvent(display,event);
default:
break;
}
}
XCloseDisplay(display);
}
Everything is good except that, unlike the code in question, it ignores language layout. Pressing a types a whatever regradless of language layout!
As an alternative to listening to X events, it's also possible to listen to Linux input events directly: https://stackoverflow.com/a/27693340/21501
This has the benefit that it's possible to modify the event stream in-flight, and block, edit or generate input events.
The proper way to listen to all events is using the X Record Extension Library, part of libXtst, apparently installed on pretty much every X system. It is documented here, but as the docs are patchy, you will need to browse previous implementations of this. Here is a nice working demo, and here is a more capable and complete implementation.
A simplified version of the first example is included below.
#include <stdio.h>
#include <X11/XKBlib.h>
#include <X11/extensions/record.h>
void key_pressed_cb(XPointer arg, XRecordInterceptData *d);
int scan(int verbose) {
XRecordRange* rr;
XRecordClientSpec rcs;
XRecordContext rc;
Display *dpy = XOpenDisplay(NULL);
rr = XRecordAllocRange();
rr->device_events.first = KeyPress;
rr->device_events.last = ButtonReleaseMask;
rcs = XRecordAllClients;
rc = XRecordCreateContext (dpy, 0, &rcs, 1, &rr, 1);
XFree (rr);
XRecordEnableContext(dpy, rc, key_pressed_cb, NULL);
}
void key_pressed_cb(XPointer arg, XRecordInterceptData *d) {
if (d->category != XRecordFromServer)
return;
int key = ((unsigned char*) d->data)[1];
int type = ((unsigned char*) d->data)[0] & 0x7F;
int repeat = d->data[2] & 1;
if(!repeat) {
switch (type) {
case KeyPress:
printf("key press %d\n", key);
break;
case KeyRelease:
printf("key release %d\n", key);
break;
case ButtonPress:
printf("button press %d\n", key);
break;
case ButtonRelease:
printf("button release %d\n", key);
break;
default:
break;
}
}
XRecordFreeData (d);
}
int main() {
scan(True);
return 0;
}
gcc -o x1 x1.c -lX11 -lXtst
I am trying to use ncurses to get non-blocking input.
#include <iostream>
#include <ncurses.h>
int main()
{
char ch;
nodelay(stdscr, TRUE);
while(1)
{
ch= getch();
if (ch == ERR) {
printf("here \n");
usleep(100000);
}
else {
printf("---------------\n");
}
}
}
However when I run this code, irrespective of what I press I always just get "here" printed.
Sample output:
Latitude-E6430:~$ ./try
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
here
dhere
ddhere
dhere
here
The d's and the spaces are not detected at all.
Can someone tell me why?
Thanks.
Finally I found the answer to the question.
I need to do initscr();
After that I am able to print out correctly (the formatting is not-as-expected though).
Correct code:
#include <iostream>
#include <ncurses.h>
int main()
{
char ch;
initscr();
nodelay(stdscr, TRUE);
while(1)
{
ch= getch();
if (ch == ' ') {
// printf("here \n");
usleep(100000);
}
else {
printf("---------------\n");
}
}
}
it need a way to call function whose name is stored in a string similar to eval. Can you help?
C++ doesn't have reflection so you must hack it, i. e.:
#include <iostream>
#include <map>
#include <string>
#include <functional>
void foo() { std::cout << "foo()"; }
void boo() { std::cout << "boo()"; }
void too() { std::cout << "too()"; }
void goo() { std::cout << "goo()"; }
int main() {
std::map<std::string, std::function<void()>> functions;
functions["foo"] = foo;
functions["boo"] = boo;
functions["too"] = too;
functions["goo"] = goo;
std::string func;
std::cin >> func;
if (functions.find(func) != functions.end()) {
functions[func]();
}
return 0;
}
There are at least 2 alternatives:
The command pattern.
On windows, you can use GetProcAddress to get a callback by name, and dlopen + dlsym on *nix.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
double eval( string expression );
int main( int argc, char *argv[] )
{
string expression = "";
for ( int i = 1; i < argc; i++ )
{
expression = expression + argv[i];
}
cout << "Expression [ " << expression << " ] = " << endl;
eval( expression );
}
double eval( string expression )
{
string program = "";
program = program + "#include <cmath>\n";
program = program + "#include <iostream>\n";
program = program + "using namespace std;\n";
program = program + "int main()\n";
program = program + "{\n";
program = program + " cout << ";
program = program + expression;
program = program + " << endl;\n";
program = program + "}";
ofstream out( "abc.cpp" );
out << program;
out.close();
system( "g++ -o abc.exe abc.cpp" );
system( "abc" );
}
You could try to adopt an existing scripting engine, expose the functions you like to this and then use this to evaluate your statements. One such enging could be the V8 engine: https://developers.google.com/v8/intro but there are many alternatives and different languages to choose from.
Here are some examples:
Boost Python
V8
LUA
AngelScript
Except using the function map in the program and hack it on the Makefile, you can access it through ELF.
I think this method is better as it did not need to write duplicate code and compile it every time on different machine.
Here is my demo C/C++ equivalent of eval(“function(arg1, arg2)”)
#include<stdio.h>
#include<stdlib.h>
#include<elf.h>
#include<libelf.h>
#include<unistd.h>
#include<fcntl.h>
#include<gelf.h>
#include<string.h>
void my_fun()
{
int a = 19;
printf("my_fun is excute, a is %d \n", a);
}
void my_fun2()
{
printf("my_fun2 is excute\n");
return;
}
void my_fun3()
{
return;
}
void excute_fun(char *program_name, char *function_name)
{
int i, count;
Elf32_Ehdr *ehdr;
GElf_Shdr shdr;
Elf *elf;
Elf_Scn *scn = NULL;
Elf_Data *data;
int flag = 0;
int fd = open(program_name, O_RDONLY);
if(fd < 0) {
perror("open\n");
exit(1);
}
if(elf_version(EV_CURRENT) == EV_NONE) {
perror("elf_version == EV_NONE");
exit(1);
}
elf = elf_begin(fd, ELF_C_READ, (Elf *) NULL);
if(!elf) {
perror("elf error\n");
exit(1);
}
/* Elf32_Off e_shoff; */
/* if ((ehdr = elf32_getehdr(elf)) != 0) { */
/* e_shoff = ehdr->e_shoff; */
/* } */
/* scn = elf_getscn(elf, 0); */
/* printf("e_shoff is %u\n", e_shoff); */
/* scn += e_shoff; */
while ((scn = elf_nextscn(elf, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
if (shdr.sh_type == SHT_SYMTAB) {
/* found a symbol table. */
break;
}
}
data = elf_getdata(scn, NULL);
if(!shdr.sh_entsize)
count = 0;
else
count = shdr.sh_size / shdr.sh_entsize;
for (i = 0; i < count; ++i) {
GElf_Sym sym;
gelf_getsym(data, i, &sym);
char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
if(sym_name != NULL && sym_name[0] != '_' && sym_name[0] != '\0' && sym_name[0] != ' ' && sym.st_value != 0)
{
/* printf("sym_name is %s\n", sym_name); */
/* printf("%s = %X\n", elf_strptr(elf, shdr.sh_link, sym.st_name), sym.st_value); */
if(!strcmp(sym_name, function_name)) {
void (*fun)(void) = (void*)sym.st_value;
(*fun)();
flag = 1;
}
}
}
if(!flag)
printf("can not find this function\n");
elf_end(elf);
close(fd);
}
int main(int argc, char *argv[])
{
char *input = (char*)malloc(100);
for(;;) {
printf("input function_name to excute: ");
scanf("%s", input);
excute_fun(argv[0], input);
memset(input, 0, sizeof(input));
printf("\n");
}
free(input);
return 0;
}
This implementation is based on Example of Printing the ELF Symbol Table