/* Copyright (c) 2009 Frode Austvik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include static void win_del(void *data,Evas_Object *obj,void *event_info) { elm_exit(); } Evas_Object* addButtonBox(Evas_Object *win,Evas_Object *vbox) { Evas_Object *box=elm_box_add(win); elm_box_horizontal_set(box,1); elm_box_homogenous_set(box,1); evas_object_size_hint_weight_set(box,1.0,1.0); evas_object_size_hint_align_set(box,-1.0,-1.0); elm_box_pack_end(vbox,box); evas_object_show(box); return box; } static void addButton( Evas_Object *win,Evas_Object *box,char *label, void *clickHandler, void *eventData ) { Evas_Object *button=elm_button_add(win); elm_button_label_set(button,label); // weight here means "expand space horizontally but not vertically" evas_object_size_hint_weight_set(button,1.0,0.0); // align here means fill available space both horizontally and vertically evas_object_size_hint_align_set(button,-1.0,-1.0); elm_box_pack_end(box,button); evas_object_show(button); evas_object_smart_callback_add(button,"clicked",clickHandler,eventData); } static void runGame_click(void *data,Evas_Object *obj,void *event_info) { // Fork off the game so it starts in the background while we exit cleanly. if (fork()==0) { char* path=malloc(strlen((char*)data)+12); *path='\0'; strcat(path,"/usr/games/"); strcat(path,(char*)data); execl(path,(char*)data,NULL); // Could not run it directly - the game is not where we expected? // (It could be some other error, e.g. file not set executable.) // TODO: use errno and strerror to give a better error message. fprintf(stderr,"Execution of %s (%s) failed.\n",(char*)data,path); free(path); // Try to run it via PATH, just in case it works (however unlikely) execlp((char*)data,(char*)data,NULL); // Couldn't run it via PATH either (not really surprising) fprintf(stderr,"Executing %s via PATH also failed.\n",(char*)data); _exit(1); } elm_exit(); } char* getLine(FILE* fh) { char buf[2048]; char *ok; ok=fgets(buf,2048,fh); if (!ok) return NULL; int len=strlen(buf); if (buf[len-1]!='\n') { fprintf(stderr,"Warning: game name too long for buffer. Truncated.\n"); ok=NULL; len++; } else { buf[len-1]='\0'; } char* line=(char*)malloc(len); if (!line) { fprintf(stderr,"Unable to allocate memory for game info.\n"); fprintf(stderr,"Wanted to allocate %i bytes.\n",len); exit(2); } strcpy(line,buf); // If no newline, keep reading until one is found (skip to next line) if (!ok) { do { ok=fgets(buf,2048,fh); } while(ok && strstr(buf,"\n")==NULL); } return line; } static void addGameButtons(Evas_Object *win,Evas_Object *vbox) { // File containing 3 lines (name,executable,description) for each game FILE *fh=fopen("/usr/share/sgt-puzzles/gameinfo","rb"); if (!fh) return; Evas_Object *box=NULL; int i=0; char *name=NULL,*exec=NULL,*desc=NULL; for(i=0; !feof(fh) && !ferror(fh) ;i++) { name=getLine(fh); if (!name) break; exec=getLine(fh); if (!exec) break; desc=getLine(fh); if (desc) free(desc); desc=NULL; if (i%3==0) { // Add a new box for a line of buttons box=addButtonBox(win,vbox); } // Add a button to the line addButton(win,box,name,runGame_click,exec); free(name);name=NULL; exec=NULL; } if (name!=NULL) free(name); if (exec!=NULL) free(exec); if (desc!=NULL) free(desc); if (ferror(fh)) { fprintf(stderr,"Error reading gameinfo file.\n"); } fclose(fh); } EAPI int elm_main(int argc,char** argv) { Evas_Object *win, *bg, *vbox, *box; // Create the window (with a name), and set its title and close handler win=elm_win_add(NULL,"sgt-puzzles-launcher",ELM_WIN_BASIC); elm_win_title_set(win,"Select puzzle to start"); evas_object_smart_callback_add(win,"delete-request",win_del,NULL); // Add a background to the window bg=elm_bg_add(win); evas_object_size_hint_weight_set(bg,1.0,1.0); elm_win_resize_object_add(win,bg); evas_object_show(bg); // Add a vertical box for the button lines vbox=elm_box_add(win); evas_object_size_hint_weight_set(vbox,1.0,1.0); evas_object_size_hint_align_set(vbox,-1.0,-1.0); elm_win_resize_object_add(win,vbox); evas_object_show(vbox); // Add buttons for the games addGameButtons(win,vbox); // Add quit button //addButton(win,vbox,"Quit",win_del,NULL); // Set a decent initial size for the window //evas_object_resize(win,480,550); // Show the window evas_object_show(win); // Run the main loop elm_run(); elm_shutdown(); return 0; } ELM_MAIN()