dockapps/wmcdplay/wmcdplay.cc
Doug Torrance bd69f80f59 wmcdplay: Add spaces between macro and string literals for C++11
We may get compile errors (e.g., [1]) otherwise.

[1] https://clang.debian.net/logs/2020-02-24-9.0.1/
    wmcdplay_1.1-2_unstable_clang9.0.1.log
2020-04-29 16:10:05 +01:00

838 lines
26 KiB
C++

// wmcdplay - A cd player designed for WindowMaker
// Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>
// This software comes with ABSOLUTELY NO WARRANTY
// This software is free software, and you are welcome to redistribute it
// under certain conditions
// See the README file for a more complete notice.
// Defines, includes and global variables
// --------------------------------------
// User defines - standard
#define WINDOWMAKER false
#define USESHAPE false
#define AFTERSTEP false
#define NORMSIZE 64
#define ASTEPSIZE 56
#define NAME "wmcdplay"
#define CLASS "WMCDPlay"
// User defines - custom
#define CDDEV "/dev/cdrom"
#define BACKCOLOR "#282828"
#define LEDCOLOR "green"
#define POSRELABS 0 // 0=relative position, 1=absolute position
#define UINTERVAL_N 1 // 20ths of a second
#define UINTERVAL_E 20 // 20ths of a second
// Includes - standard
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// Includes - custom
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "cdctl_freebsd.h"
#else
#include "cdctl.h"
#endif
// X-Windows includes - standard
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/xpm.h>
#include <X11/extensions/shape.h>
// Pixmaps - standard
Pixmap pm_tile;
Pixmap pm_disp;
Pixmap pm_mask;
// Pixmaps - artwork
Pixmap pm_cd;
Pixmap pm_cdmask;
Pixmap pm_sym;
Pixmap pm_symmask;
Pixmap pm_led;
Pixmap pm_sled;
Pixmap pm_tled;
// Xpm images - standard
#include "XPM/tile.xpm"
// Xpm images - artwork
#include "XPM/standard.art"
// Variables for command-line arguments - standard
bool wmaker=WINDOWMAKER;
bool ushape=USESHAPE;
bool astep=AFTERSTEP;
char display[256]="";
char position[256]="";
int winsize;
// Variables for command-line arguments - custom
char cddev[256]=CDDEV;
char backcolor[256]=BACKCOLOR;
char ledcolor[256]=LEDCOLOR;
bool artwrk=false;
char artwrkf[256]="";
int tsel=1;
int vol=-1; // -1 means don't set volume
int uinterval_e=UINTERVAL_E;
// X-Windows basics - standard
Atom _XA_GNUSTEP_WM_FUNC;
Atom deleteWin;
Display *d_display;
Window w_icon;
Window w_main;
Window w_root;
Window w_activewin;
// X-Windows basics - custom
GC gc_gc, gc_bitgc;
unsigned long color[4];
// Misc custom global variables
// ----------------------------
// For artwork loading
int **art_btnlist;
int *art_btnptr;
int *art_actptr;
int art_symsize[2];
int art_ledsize[6];
int mode=-1, track=-1, pos=-1;
int tdisplay=POSRELABS;
int ucount=0;
char trackstr[8]="";
char timestr[8]="";
char chrset[]="00112233445566778899 DDAATTNNOOCC--PPEE:;_";
CDCtl *cdctl;
// Procedures and functions
// ------------------------
// Procedures and functions - standard
void initXWin(int argc, char **argv);
void freeXWin();
void createWin(Window *win, int x, int y);
unsigned long getColor(char *colorname);
unsigned long mixColor(char *colorname1, int prop1, char *colorname2, int prop2);
// Procedures and functions - custom
void scanArgs(int argc, char **argv);
void checkStatus(bool forced);
void pressEvent(XButtonEvent *xev);
void repaint();
void update();
void drawText(int x, int y, char *text);
// Procedures and functions - artwork basics
bool readArtwork(char *artfilen);
char *readBlock(FILE *dfile);
int arrayItems(char *buf);
void readArrayInt(char *buf, int *array, int n);
void readArrayBool(char *buf, bool *array, int n);
// Procedures and functions - artwork specials
void createPixmap(const char **data, char *buf, Pixmap *image, Pixmap *mask, int *width, int *height);
void setBtnList(int *bset);
bool inPolygon(int *points, int px, int py);
// Implementation
// --------------
int main(int argc, char **argv)
{
scanArgs(argc, argv);
initXWin(argc, argv);
color[0]=mixColor(ledcolor, 0, backcolor, 100);
color[1]=mixColor(ledcolor, 100, backcolor, 0);
color[2]=mixColor(ledcolor, 60, backcolor, 40);
color[3]=mixColor(ledcolor, 25, backcolor, 75);
if(artwrk)
artwrk=readArtwork(artwrkf);
if(!artwrk){
int w, h;
createPixmap(cdplayer_xpm, NULL, &pm_cd, &pm_cdmask, NULL, NULL);
createPixmap(symbols_xpm, NULL, &pm_sym, &pm_symmask, &w, &h);
art_symsize[0]=(w+1)/11-1;
art_symsize[1]=h;
createPixmap(led_xpm, NULL, &pm_led, NULL, &w, &h);
art_ledsize[0]=(w+1)/strlen(chrset)-1;
art_ledsize[1]=h;
createPixmap(ledsym_xpm, NULL, &pm_sled, NULL, &w, &h);
art_ledsize[2]=(w+1)/6-1;
art_ledsize[3]=h;
createPixmap(ledtsel_xpm, NULL, &pm_tled, NULL, &w, &h);
art_ledsize[4]=(w+1)/5-1;
art_ledsize[5]=h;
art_btnptr=art_btns;
art_actptr=art_actions;
}
setBtnList(art_btnptr);
createPixmap(tile_xpm, NULL, &pm_tile, NULL, NULL, NULL);
pm_disp = XCreatePixmap(d_display, w_root, 64, 64, DefaultDepth(d_display, DefaultScreen(d_display)));
pm_mask = XCreatePixmap(d_display, w_root, 64, 64, 1);
XGCValues gcv;
unsigned long gcm;
gcm=GCGraphicsExposures;
gcv.graphics_exposures=false;
gc_gc=XCreateGC(d_display, w_root, gcm, &gcv);
gc_bitgc=XCreateGC(d_display, pm_mask, gcm, &gcv);
cdctl=new CDCtl(cddev);
if(!cdctl->openOK())
fprintf(stderr, "%s : Unable to open cdrom device '%s'.\n", NAME, cddev);
else{
if(vol!=-1)
cdctl->setVolume(vol, vol);
int tsels[] = { tsNone, tsNext, tsRepeat, tsRepeatCD, tsRandom };
cdctl->setTrackSelection(tsels[tsel]);
checkStatus(true);
XEvent xev;
XSelectInput(d_display, w_activewin, ButtonPress | ExposureMask);
XMapWindow(d_display, w_main);
bool done=false;
while(!done){
while(XPending(d_display)){
XNextEvent(d_display, &xev);
switch(xev.type){
case Expose:
repaint();
break;
case ButtonPress:
pressEvent(&xev.xbutton);
break;
case ClientMessage:
if((Atom) xev.xclient.data.l[0]==deleteWin)
done=true;
break;
}
}
ucount++;
if(ucount>=((mode==ssNoCD || mode==ssTrayOpen) ? uinterval_e : UINTERVAL_N))
checkStatus(false);
XFlush(d_display);
usleep(50000);
}
}
XFreeGC(d_display, gc_gc);
XFreeGC(d_display, gc_bitgc);
XFreePixmap(d_display, pm_tile);
XFreePixmap(d_display, pm_disp);
XFreePixmap(d_display, pm_mask);
XFreePixmap(d_display, pm_cd);
XFreePixmap(d_display, pm_cdmask);
XFreePixmap(d_display, pm_sym);
XFreePixmap(d_display, pm_symmask);
XFreePixmap(d_display, pm_led);
XFreePixmap(d_display, pm_sled);
XFreePixmap(d_display, pm_tled);
freeXWin();
if(artwrk){
free(art_btnptr);
free(art_actptr);
}
free(art_btnlist);
delete cdctl;
return 0;
}
void initXWin(int argc, char **argv){
winsize=astep ? ASTEPSIZE : NORMSIZE;
if((d_display=XOpenDisplay(display))==NULL){
fprintf(stderr,"%s : Unable to open X display '%s'.\n", NAME, XDisplayName(display));
exit(1);
}
_XA_GNUSTEP_WM_FUNC=XInternAtom(d_display, "_GNUSTEP_WM_FUNCTION", false);
deleteWin=XInternAtom(d_display, "WM_DELETE_WINDOW", false);
w_root=DefaultRootWindow(d_display);
XWMHints wmhints;
XSizeHints shints;
shints.x=0;
shints.y=0;
shints.flags=0;
bool pos=(XWMGeometry(d_display, DefaultScreen(d_display), position, NULL, 0, &shints, &shints.x, &shints.y,
&shints.width, &shints.height, &shints.win_gravity) & (XValue | YValue));
shints.min_width=winsize;
shints.min_height=winsize;
shints.max_width=winsize;
shints.max_height=winsize;
shints.base_width=winsize;
shints.base_height=winsize;
shints.flags=PMinSize | PMaxSize | PBaseSize;
createWin(&w_main, shints.x, shints.y);
if(wmaker || astep || pos)
shints.flags |= USPosition;
if(wmaker){
wmhints.initial_state=WithdrawnState;
wmhints.flags=WindowGroupHint | StateHint | IconWindowHint;
createWin(&w_icon, shints.x, shints.y);
w_activewin=w_icon;
wmhints.icon_window=w_icon;
}
else{
wmhints.initial_state=NormalState;
wmhints.flags=WindowGroupHint | StateHint;
w_activewin=w_main;
}
wmhints.window_group=w_main;
XSetWMHints(d_display, w_main, &wmhints);
XSetWMNormalHints(d_display, w_main, &shints);
XSetCommand(d_display, w_main, argv, argc);
XStoreName(d_display, w_main, NAME);
XSetIconName(d_display, w_main, NAME);
XSetWMProtocols(d_display, w_activewin, &deleteWin, 1);
}
void freeXWin(){
XDestroyWindow(d_display, w_main);
if(wmaker)
XDestroyWindow(d_display, w_icon);
XCloseDisplay(d_display);
}
void createWin(Window *win, int x, int y){
XClassHint classHint;
*win=XCreateSimpleWindow(d_display, w_root, x, y, winsize, winsize, 0, 0, 0);
classHint.res_name=const_cast<char *>(NAME);
classHint.res_class=const_cast<char *>(CLASS);
XSetClassHint(d_display, *win, &classHint);
}
unsigned long getColor(char *colorname){
XColor color;
XWindowAttributes winattr;
XGetWindowAttributes(d_display, w_root, &winattr);
color.pixel=0;
XParseColor(d_display, winattr.colormap, colorname, &color);
color.flags=DoRed | DoGreen | DoBlue;
XAllocColor(d_display, winattr.colormap, &color);
return color.pixel;
}
unsigned long mixColor(char *colorname1, int prop1, char *colorname2, int prop2){
XColor color, color1, color2;
XWindowAttributes winattr;
XGetWindowAttributes(d_display, w_root, &winattr);
XParseColor(d_display, winattr.colormap, colorname1, &color1);
XParseColor(d_display, winattr.colormap, colorname2, &color2);
color.pixel=0;
color.red=(color1.red*prop1+color2.red*prop2)/(prop1+prop2);
color.green=(color1.green*prop1+color2.green*prop2)/(prop1+prop2);
color.blue=(color1.blue*prop1+color2.blue*prop2)/(prop1+prop2);
color.flags=DoRed | DoGreen | DoBlue;
XAllocColor(d_display, winattr.colormap, &color);
return color.pixel;
}
void scanArgs(int argc, char **argv){
for(int i=1;i<argc;i++){
if(strcmp(argv[i], "-h")==0 || strcmp(argv[i], "-help")==0 || strcmp(argv[i], "--help")==0){
fprintf(stderr, "wmcdplay - A cd player designed for WindowMaker\nRelease " VERSION "\n");
fprintf(stderr, "Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>\n");
fprintf(stderr, "This software comes with ABSOLUTELY NO WARRANTY\n");
fprintf(stderr, "This software is free software, and you are welcome to redistribute it\n");
fprintf(stderr, "under certain conditions\n");
fprintf(stderr, "See the README file for a more complete notice.\n\n");
fprintf(stderr, "usage:\n\n %s [options]\n\noptions:\n\n",argv[0]);
fprintf(stderr, " -h | -help | --help display this help screen\n");
fprintf(stderr, " -w use WithdrawnState (for WindowMaker)\n");
fprintf(stderr, " -s shaped window\n");
fprintf(stderr, " -a use smaller window (for AfterStep Wharf)\n");
fprintf(stderr, " -f artwork_file load the specified artwork file\n");
fprintf(stderr, " -t track_selection set track selection (between 0 and 4)\n");
fprintf(stderr, " -v volume set the cdrom volume (between 0 and 255)\n");
fprintf(stderr, " -i interval interval in 1/20 seconds between cd polls when empty\n");
fprintf(stderr, " -l led_color use the specified color for led displays\n");
fprintf(stderr, " -b back_color use the specified color for backgrounds\n");
fprintf(stderr, " -d cd_device use specified device (rather than /dev/cdrom)\n");
fprintf(stderr, " -position position set window position (see X manual pages)\n");
fprintf(stderr, " -display display select target display (see X manual pages)\n\n");
exit(0);
}
if(strcmp(argv[i], "-w")==0)
wmaker=!wmaker;
if(strcmp(argv[i], "-s")==0)
ushape=!ushape;
if(strcmp(argv[i], "-a")==0)
astep=!astep;
if(strcmp(argv[i], "-t")==0){
if(i<argc-1){
i++;
sscanf(argv[i], "%i", &tsel);
}
continue;
}
if(strcmp(argv[i], "-v")==0){
if(i<argc-1){
i++;
sscanf(argv[i], "%i", &vol);
}
continue;
}
if(strcmp(argv[i], "-i")==0){
if(i<argc-1){
i++;
sscanf(argv[i], "%i", &uinterval_e);
}
continue;
}
if(strcmp(argv[i], "-f")==0){
artwrk=true;
if(i<argc-1){
i++;
sprintf(artwrkf, "%s", argv[i]);
}
continue;
}
if(strcmp(argv[i], "-d")==0){
if(i<argc-1){
i++;
sprintf(cddev, "%s", argv[i]);
}
continue;
}
if(strcmp(argv[i], "-l")==0){
if(i<argc-1){
i++;
sprintf(ledcolor, "%s", argv[i]);
}
continue;
}
if(strcmp(argv[i], "-b")==0){
if(i<argc-1){
i++;
sprintf(backcolor, "%s", argv[i]);
}
continue;
}
if(strcmp(argv[i], "-position")==0){
if(i<argc-1){
i++;
sprintf(position, "%s", argv[i]);
}
continue;
}
if(strcmp(argv[i], "-display")==0){
if(i<argc-1){
i++;
sprintf(display, "%s", argv[i]);
}
continue;
}
}
}
void checkStatus(bool forced){
ucount=0;
int oldmode=mode;
int oldpos=pos;
int oldtrack=track;
cdctl->doStatus();
mode=cdctl->getStatusState();
track=cdctl->getStatusTrack();
if(mode==ssStopped){
if(tdisplay==0)
pos=0;
if(tdisplay==1)
pos=cdctl->getTrackStart(track);
}
if(mode==ssPlaying || mode==ssPaused){
if(tdisplay==0)
pos=cdctl->getStatusPosRel();
if(tdisplay==1)
pos=cdctl->getStatusPosAbs();
}
bool umode=mode!=oldmode || forced;
bool utrack=umode || (!(mode==ssNoCD || mode==ssTrayOpen) && track!=oldtrack);
bool utimer=utrack || ((mode==ssPlaying || mode==ssPaused || mode==ssStopped) && (int)(pos/75)!=(int)(oldpos/75));
if(utimer){
if(umode)
update();
if(utrack){
if(mode==ssNoCD || mode==ssTrayOpen)
sprintf(trackstr, " ");
else
sprintf(trackstr, "%2d", cdctl->getStatusTrack());
if(art_showled[1])
drawText(art_ledpos[1][0], art_ledpos[1][1], trackstr);
}
if(mode==ssPlaying || mode==ssPaused || mode==ssStopped){
int remain = 0;
if(tdisplay==0)
remain=cdctl->getTrackLen(cdctl->getStatusTrack())-pos;
if(tdisplay==1)
remain=cdctl->getCDLen()-pos;
if(remain<2250)
sprintf(timestr, " -;%02d", remain/75);
else
sprintf(timestr, "%2d:%02d", (pos/75)/60, (pos/75)%60);
}
if(art_showled[0])
drawText(art_ledpos[0][0], art_ledpos[0][1], timestr);
repaint();
}
}
void pressEvent(XButtonEvent *xev){
int x=xev->x-(winsize/2-32);
int y=xev->y-(winsize/2-32);
int btn=-1;
for(int i=0;i<art_nbtns;i++){
if(inPolygon(&art_btnlist[i][2], x, y))
btn=i;
}
if(btn==-1){
if(art_showled[3]){
if(x>=art_ledpos[3][0] && y>=art_ledpos[3][1] && x<=art_ledpos[3][0]+art_ledsize[4] && y<=art_ledpos[3][1]+art_ledsize[5]){
int tsels[] = { tsNone, tsNext, tsRepeat, tsRepeatCD, tsRandom };
tsel++;
if(tsel>=5)
tsel=0;
cdctl->setTrackSelection(tsels[tsel]);
XCopyArea(d_display, pm_tled, pm_disp, gc_gc, (art_ledsize[4]+1)*tsel, 0, art_ledsize[4], art_ledsize[5], art_ledpos[3][0], art_ledpos[3][1]);
repaint();
return;
}
}
if(art_showled[0]){
if(x>=art_ledpos[0][0] && y>=art_ledpos[0][1] && x<=art_ledpos[0][0]+(art_ledsize[0]+1)*9-1 && y<=art_ledpos[0][1]+art_ledsize[1]){
tdisplay++;
if(tdisplay>=2)
tdisplay=0;
checkStatus(false);
return;
}
}
}
else{
int action=art_actptr[6*btn+mode];
int acmds[]={ acStop, acPlay, acPause, acResume, acPrev, acNext, acRewd, acFFwd, acEject, acClose };
if(action>0){
int acmd=acmds[action-1];
cdctl->doAudioCommand(acmd);
checkStatus(false);
}
}
}
void repaint(){
XCopyArea(d_display, pm_disp, w_activewin, gc_gc, 0, 0, 64, 64, winsize/2-32, winsize/2-32);
XEvent xev;
while(XCheckTypedEvent(d_display, Expose, &xev));
}
void update(){
if(mode==ssData)
sprintf(timestr, "DA_TA");
if(mode==ssNoCD)
sprintf(timestr, "NO;CD");
if(mode==ssTrayOpen)
sprintf(timestr, "OP_EN");
XPoint mply[art_nbtns];
if(pm_cdmask!=None){
XSetForeground(d_display, gc_bitgc, 0);
XCopyArea(d_display, pm_cdmask, pm_mask, gc_bitgc, 0, 0, 64, 64, 0, 0);
for(int i=0; i<art_nbtns; i++){
if(art_actptr[6*i+mode]==0 && art_hidebtns){
for(int k=0;k<art_btnlist[i][2];k++){
mply[k].x=art_btnlist[i][k*2+3];
mply[k].y=art_btnlist[i][k*2+4];
}
XFillPolygon(d_display, pm_mask, gc_bitgc, (XPoint *)mply, art_btnlist[i][2], Convex, CoordModeOrigin);
}
}
if(!(wmaker || ushape || astep)){
XCopyArea(d_display, pm_tile, pm_disp, gc_gc, 0, 0, 64, 64, 0, 0);
XSetClipMask(d_display, gc_gc, pm_mask);
}
}
XCopyArea(d_display, pm_cd, pm_disp, gc_gc, 0, 0, 64, 64, 0, 0);
if(pm_symmask!=None){
XSetClipMask(d_display, gc_gc, pm_symmask);
XSetClipMask(d_display, gc_bitgc, pm_symmask);
}
XSetForeground(d_display, gc_bitgc, 1);
for(int i=0;i<art_nbtns;i++){
if(!(art_actptr[6*i+mode]==0 && art_hidebtns)){
int sympos=(art_symsize[0]+1)*(art_actptr[6*i+mode]);
XSetClipOrigin(d_display, gc_gc, art_btnlist[i][0]-sympos, art_btnlist[i][1]);
XSetClipOrigin(d_display, gc_bitgc, art_btnlist[i][0]-sympos, art_btnlist[i][1]);
XCopyArea(d_display, pm_sym, pm_disp, gc_gc, sympos, 0, art_symsize[0], art_symsize[1], art_btnlist[i][0], art_btnlist[i][1]);
XFillRectangle(d_display, pm_mask, gc_bitgc, art_btnlist[i][0], art_btnlist[i][1], art_symsize[0], art_symsize[1]);
}
}
if(wmaker || ushape || astep)
XShapeCombineMask(d_display, w_activewin, ShapeBounding, winsize/2-32, winsize/2-32, pm_mask, ShapeSet);
XSetClipOrigin(d_display, gc_gc, 0, 0);
XSetClipOrigin(d_display, gc_bitgc, 0, 0);
XSetClipMask(d_display, gc_gc, None);
XSetClipMask(d_display, gc_bitgc, None);
if(art_showled[2])
XCopyArea(d_display, pm_sled, pm_disp, gc_gc, (art_ledsize[2]+1)*mode, 0, art_ledsize[2], art_ledsize[3], art_ledpos[2][0], art_ledpos[2][1]);
if(art_showled[3])
XCopyArea(d_display, pm_tled, pm_disp, gc_gc, (art_ledsize[4]+1)*tsel, 0, art_ledsize[4], art_ledsize[5], art_ledpos[3][0], art_ledpos[3][1]);
}
void drawText(int x, int y, char *text){
int drawx=x;
for(size_t i=0;i<strlen(text);i++){
char *chrptr=strchr(chrset,text[i]);
if(chrptr!=NULL){
int chrindex=chrptr-chrset;
int chrwidth=art_ledsize[0];
if(chrset[chrindex+1]==text[i])
chrwidth=2*art_ledsize[0]+1;
XCopyArea(d_display, pm_led, pm_disp, gc_gc, chrindex*(art_ledsize[0]+1), 0, chrwidth, art_ledsize[1], drawx, y);
drawx+=chrwidth+1;
}
}
}
bool readArtwork(char *artfilen){
FILE *artfile;
char artfilenbuf[256];
artfile=fopen(artfilen, "r");
if(artfile==NULL){
if(strchr(artfilen, '/')!=NULL){
fprintf(stderr, "%s : Unable to open artwork file '%s'.\n", NAME, artfilen);
return false;
}
sprintf(artfilenbuf, "%s/.wmcdplay/%s", getenv("HOME"), artfilen);
artfile=fopen(artfilenbuf, "r");
if(artfile==NULL){
sprintf(artfilenbuf, "%s%s", SYSARTDIR, artfilen);
artfile=fopen(artfilenbuf, "r");
if(artfile==NULL){
fprintf(stderr,"%s : Tried to find artwork file, but failed.\n", NAME);
return false;
}
}
}
char buf[256];
bool done=false;
while(!done){
if (fgets(buf, 250, artfile) == NULL) {
fprintf(stderr,"%s : Error reading artwork file.\n", NAME);
return false;
}
done=(feof(artfile)!=0);
if(!done){
int keynum=0;
const char *keystr[]={ "int art_nbtns=",
"bool art_hidebtns=",
"bool art_showled[4]=",
"int art_ledpos[4][2]=",
"int art_btns[]=",
"int art_actions[]=",
"/* XPM */" };
for(int i=0;i<7;i++){
if(strncmp(buf, keystr[i], strlen(keystr[i]))==0){
keynum=i+1;
break;
}
}
if(keynum==1)
sscanf(buf+strlen(keystr[keynum-1]), "%d", &art_nbtns);
if(keynum==2)
art_hidebtns=(strstr(buf+strlen(keystr[keynum-1]), "true")!=NULL);
if(keynum==3)
readArrayBool((char *)buf, (bool *)art_showled, 4);
if(keynum==4)
readArrayInt((char *)buf, (int *)art_ledpos, 8);
if(keynum>=5){
fseek(artfile, -strlen(buf), SEEK_CUR);
char *block=readBlock(artfile);
if(keynum==5){
int items=arrayItems(block);
art_btnptr=(int *)malloc(sizeof(int)*items);
readArrayInt(block, art_btnptr, items);
}
if(keynum==6){
int items=arrayItems(block);
art_actptr=(int *)malloc(sizeof(int)*items);
readArrayInt(block, art_actptr, items);
}
if(keynum==7){
strncpy(buf, strchr(block+strlen(keystr[keynum-1]), '\n')+1, 250);
*strchr(buf, '\n')='\0';
int w,h;
if(strncmp(buf, "static const char * cdplayer_xpm", strlen("static const char * cdplayer_xpm"))==0)
createPixmap(NULL, block, &pm_cd, &pm_cdmask, NULL, NULL);
if(strncmp(buf, "static const char * symbols_xpm", strlen("static const char * symbols_xpm"))==0){
createPixmap(NULL, block, &pm_sym, &pm_symmask, &w, &h);
art_symsize[0]=(w+1)/11-1;
art_symsize[1]=h;
}
if(strncmp(buf, "static const char * led_xpm", strlen("static const char * led_xpm"))==0){
createPixmap(NULL, block, &pm_led, NULL, &w, &h);
art_ledsize[0]=(w+1)/strlen(chrset)-1;
art_ledsize[1]=h;
}
if(strncmp(buf, "static const char * ledsym_xpm", strlen("static const char * ledsym_xpm"))==0){
createPixmap(NULL, block, &pm_sled, NULL, &w, &h);
art_ledsize[2]=(w+1)/6-1;
art_ledsize[3]=h;
}
if(strncmp(buf, "static const char * ledtsel_xpm", strlen("static const char * ledtsel_xpm"))==0){
createPixmap(NULL, block, &pm_tled, NULL, &w, &h);
art_ledsize[4]=(w+1)/5-1;
art_ledsize[5]=h;
}
}
free(block);
}
}
}
fclose(artfile);
return true;
}
char *readBlock(FILE *dfile){
char buf[256];
long bytes=0;
char *block=NULL;
do{
if (fgets(buf, 250, dfile) == NULL) {
fprintf(stderr,"%s : Error reading artwork file.\n", NAME);
return NULL;
}
int buflen=strlen(buf);
block=(char *)realloc(block, sizeof(char)*(bytes+buflen+1));
strcpy(block+bytes, buf);
bytes+=buflen;
} while(strstr(buf, "}")==NULL);
return block;
}
int arrayItems(char *buf){
int items=1;
char *bufptr=buf;
while((bufptr=strstr(bufptr, ","))!=NULL){
bufptr++;
items++;
};
return items;
}
void readArrayInt(char *buf, int *array, int n){
char *bufptr;
bufptr=strtok(buf, "{,}");
for(int i=0;i<n;i++){
bufptr=strtok(NULL, "{,}");
sscanf(bufptr, "%d", &array[i]);
}
}
void readArrayBool(char *buf, bool *array, int n){
char *bufptr;
bufptr=strtok(buf, "{,}");
for(int i=0;i<n;i++){
bufptr=strtok(NULL, "{,}");
array[i]=(strstr(bufptr, "true")!=NULL);
}
}
void createPixmap(const char **data, char *buf, Pixmap *image, Pixmap *mask, int *width, int *height){
XpmAttributes xpmattr;
XpmColorSymbol xpmcsym[4]={
{const_cast<char *>("back_color"), NULL, color[0]},
{const_cast<char *>("led_color_high"), NULL, color[1]},
{const_cast<char *>("led_color_med"), NULL, color[2]},
{const_cast<char *>("led_color_low"), NULL, color[3]}};
xpmattr.numsymbols=4;
xpmattr.colorsymbols=xpmcsym;
xpmattr.exactColors=false;
xpmattr.closeness=40000;
xpmattr.valuemask=XpmColorSymbols | XpmExactColors | XpmCloseness | XpmSize;
if(data!=NULL)
XpmCreatePixmapFromData(d_display, w_root, const_cast<char **>(data),
image, mask, &xpmattr);
else
XpmCreatePixmapFromBuffer(d_display, w_root, buf, image, mask, &xpmattr);
if(width!=NULL)
*width=xpmattr.width;
if(height!=NULL)
*height=xpmattr.height;
}
void setBtnList(int *bset){
// Create a list of pointers to button data.
// So, for example, data for button 2 can be accessed as art_btnlist[2];
// Also, the y co-ordinate of its symbol would be art_btnlist[2][1]
art_btnlist=(int **)malloc(art_nbtns*sizeof(int *));
int curpos=0;
for(int i=0;i<art_nbtns;i++){
art_btnlist[i]=&bset[0+curpos];
curpos+=2*art_btnlist[i][2]+3;
}
}
bool inPolygon(int *points, int px, int py){
int lx=points[1];
int ly=points[2];
int x,y;
for(int i=1;i<=points[0];i++){
if(i==points[0]){
x=points[1];
y=points[2];
}
else{
x=points[i*2+1];
y=points[i*2+2];
}
int a=ly-y;
int b=x-lx;
int c=-a*x-b*y;
if(a*px+b*py+c<0)
return false;
lx=x;
ly=y;
}
return true;
}