xenocara/app/fvwm/extras/FvwmScript/FvwmScript.c

757 lines
20 KiB
C
Raw Normal View History

/* Copyright May 1996, Frederic Cordier. No guarantees or warantees are
* provided or implied in any way whatsoever. Use this program at your own
* risk. Permission to use, modify, and redistribute this program is hereby
* given, provided that this copyright is kept intact.
*/
#include "types.h"
#ifdef MEMDEBUG /* For debugging */
#include <unchecked.h>
#endif
/* Variables utilise par l'analyseur syntaxique */
extern ScriptProp *scriptprop;
extern int nbobj; /* Nombre d'objets */
extern int numligne; /* Numero de ligne */
extern TabObj *tabobj; /* Tableau d'objets, limite=100 */
extern char **TabVVar; /* Tableau des variables du sript */
extern int TabIdObj[101];
extern Bloc **TabIObj;
extern CaseObj *TabCObj;
#ifdef MEMDEBUG
extern int __bounds_debug_no_checking;
#endif
/* Constante de couleurs utilise dans le tableau TabColor */
#define black 0
#define white 1
#define back 2
#define fore 3
#define shad 4
#define li 5
/* Variables globales */
char *ScriptName; /* Nom du fichier contenat le script decrivant le GUI */
char *ScriptPath;
char *ModuleName;
int fd[2]; /* pipe pair */
int fd_err;
int x_fd; /* fd for X */
Window ref;
extern void (*TabCom[30]) (int NbArg,long *TabArg);
X11base *x11base; /* Pour le serveur X */
TypeBuffSend BuffSend; /* Pour les communication entre script */
int grab_server = 0;
struct XObj *tabxobj[100];
char *Scrapt;
Atom propriete,type;
static Atom wm_del_win;
char *pixmapPath = NULL;
extern void InitCom();
void Debug()
{
int i,j;
for (j=1;j<=nbobj;j++)
for (i=0;i<=TabCObj[TabIdObj[j]].NbCase;i++)
{
/* Execution du bloc d'instruction */
fprintf(stderr,"Id de l'objet %d\n",TabIdObj[j]);
fprintf(stderr,"Nb Instruction %d\n",TabIObj[TabIdObj[j]][i].NbInstr);
}
}
/* Lecture du fichier contenant le scipt */
void ReadConfig (char *ScriptName)
{
extern FILE *yyin;
char s[255];
sprintf(s,"%s/%s",ScriptPath,ScriptName);
yyin=fopen(s,"r");
if (yyin == NULL)
{
fprintf(stderr,"Can't open the script %s",s);
exit(1);
}
/* On ne redefini pas yyout qui est la sortie standard */
/* Application de l'analyseur syntaxique et lexical */
yyparse();
/* Fermeture du script */
fclose(yyin);
}
/* Quitter par l'option Delete du bouton de la fenetre */
void DeadPipe(int nonsense)
{
Quit (0,NULL);
}
/* Lecture du fichier system.fvwmrc ou .fvwmrc */
void ParseOptions(void)
{
char *tline;
GetConfigLine(fd,&tline);
while(tline != (char *)0)
{
if((strlen(&tline[0])>1)&&(strncasecmp(tline,"PixmapPath",10)==0))
{
CopyString(&pixmapPath,&tline[10]);
}
if((strlen(&tline[0])>1)&&(strncasecmp(tline,"*FvwmScriptPath",15)==0))
{
CopyString(&ScriptPath,&tline[15]);
}
GetConfigLine(fd,&tline);
}
}
/* Procedure d'initialisation du serveur X et des variables globales*/
void Xinit(int IsFather)
{
char *name;
Atom myatom;
int i=16;
/* Connextion au serveur X */
#ifdef MEMDEBUG
__bounds_debug_no_checking=True;
#endif
x11base->display=XOpenDisplay(NULL);
if (x11base->display==NULL)
{
fprintf(stderr,"Enable to open display.\n");
exit(1);
}
#ifdef MEMDEBUG
__bounds_debug_no_checking=False;
#endif
if (IsFather)
{
name=(char*)calloc(sizeof(char),strlen("FvwmScript")+5);
do
{
sprintf(name,"%c%xFvwmScript",161,i);
i++;
myatom=XInternAtom(x11base->display,name,False);
}
while (XGetSelectionOwner(x11base->display,myatom)!=None);
x11base->TabScriptId[1]=name;
x11base->TabScriptId[0]=NULL;
}
x11base->NbChild=0;
x11base->screen=DefaultScreen(x11base->display);
x11base->WhitePix=WhitePixel(x11base->display,x11base->screen);
x11base->BlackPix=BlackPixel(x11base->display,x11base->screen);
x11base->depth=XDefaultDepth(x11base->display,x11base->screen);
x11base->colormap = DefaultColormap(x11base->display,x11base->screen);
x11base->root = RootWindow(x11base->display,x11base->screen);
x_fd = XConnectionNumber(x11base->display);
}
/***********************/
/* Lecture d'un icone */
/***********************/
void LoadIcon(struct XObj *xobj)
{
char *path = NULL;
XWindowAttributes root_attr;
XpmAttributes xpm_attributes;
if ((xobj->icon)!=NULL)
{
path = (char*)findIconFile(xobj->icon, pixmapPath,4);
if(path == NULL)return;
XGetWindowAttributes(xobj->display,RootWindow(xobj->display,DefaultScreen(xobj->display)),&root_attr);
xpm_attributes.colormap = root_attr.colormap;
xpm_attributes.valuemask = XpmSize | XpmReturnPixels|XpmColormap;
if(XpmReadFileToPixmap(xobj->display, RootWindow(xobj->display,DefaultScreen(xobj->display)),
path,
&xobj->iconPixmap,
&xobj->icon_maskPixmap,
&xpm_attributes) == XpmSuccess)
{
xobj->icon_w = xpm_attributes.width;
xobj->icon_h = xpm_attributes.height;
}
else
{
fprintf(stderr,"Enable to load pixmap %s\n",xobj->icon);
xobj->iconPixmap=None;
xobj->icon_maskPixmap=None;
}
free(path);
}
}
int MyAllocNamedColor(Display *display,Colormap colormap,char* colorname,XColor* color)
{
static XColor TempColor;
if (colorname[0]=='#')
{
if (XParseColor(display,colormap,colorname,color))
return XAllocColor(display,colormap,color);
else
return 0;
}
else
{
if (XLookupColor(display,colormap,colorname,&TempColor,color))
return XAllocColor(display,colormap,color);
else
return 0;
}
return 0;
}
/* Ouvre une fenetre pour l'affichage du GUI */
void OpenWindow ()
{
XTextProperty Name;
XWMHints *IndicWM;
XSizeHints *IndicNorm;
unsigned long mask;
XSetWindowAttributes Attr;
/* Allocation des couleurs */
MyAllocNamedColor(x11base->display,x11base->colormap,x11base->forecolor,&x11base->TabColor[fore]);
MyAllocNamedColor(x11base->display,x11base->colormap,x11base->backcolor,&x11base->TabColor[back]);
MyAllocNamedColor(x11base->display,x11base->colormap,x11base->shadcolor,&x11base->TabColor[shad]);
MyAllocNamedColor(x11base->display,x11base->colormap,x11base->licolor,&x11base->TabColor[li]);
MyAllocNamedColor(x11base->display,x11base->colormap,"#000000",&x11base->TabColor[black]);
MyAllocNamedColor(x11base->display,x11base->colormap,"#FFFFFF",&x11base->TabColor[white]);
/* Definition des caracteristiques de la fentre */
mask=0;
mask|=CWBackPixel;
Attr.background_pixel=x11base->TabColor[back].pixel;
x11base->win=XCreateWindow(x11base->display,
DefaultRootWindow(x11base->display),
x11base->size.x,
x11base->size.y,
x11base->size.width,
x11base->size.height,0,
CopyFromParent,
InputOutput,
CopyFromParent,
mask,&Attr);
XSetWindowColormap(x11base->display,x11base->win,x11base->colormap);
x11base->gc=XCreateGC(x11base->display,x11base->win,0,NULL);
/* Choix des evts recus par la fenetre */
XSelectInput(x11base->display,x11base->win,KeyPressMask|ButtonPressMask|
ExposureMask|ButtonReleaseMask|EnterWindowMask|LeaveWindowMask|ButtonMotionMask);
XSelectInput(x11base->display,x11base->root,PropertyChangeMask);
/* Specification des parametres utilises par le gestionnaire de fenetre */
if (XStringListToTextProperty(&x11base->title,1,&Name)==0)
fprintf(stderr,"Can't use icon name\n");
IndicNorm=XAllocSizeHints();
if (x11base->size.x!=-1)
{
IndicNorm->x=x11base->size.x;
IndicNorm->y=x11base->size.y;
IndicNorm->flags=PSize|PMinSize|PMaxSize|PResizeInc|PBaseSize|PPosition;
}
else
IndicNorm->flags=PSize|PMinSize|PMaxSize|PResizeInc|PBaseSize;
IndicNorm->width=x11base->size.width;
IndicNorm->height=x11base->size.height;
IndicNorm->min_width=x11base->size.width;
IndicNorm->min_height=x11base->size.height;
IndicNorm->max_width=x11base->size.width;
IndicNorm->max_height=x11base->size.height;
IndicWM=XAllocWMHints();
IndicWM->input=True;
IndicWM->initial_state=NormalState;
IndicWM->flags=InputHint|StateHint;
XSetWMProperties(x11base->display,x11base->win,&Name,
&Name,NULL,0,IndicNorm,IndicWM,NULL);
Scrapt=(char*)calloc(sizeof(char),1);
/* Construction des atomes pour la communication inter-application */
propriete=XInternAtom(x11base->display,"Prop_selection",False);
wm_del_win = XInternAtom(x11base->display,"WM_DELETE_WINDOW",False);
XSetWMProtocols(x11base->display,x11base->win,&wm_del_win,1);
}
/***********************************************/
/* Execution d'une sequence d'instruction */
/***********************************************/
void ExecBloc(Bloc *bloc)
{
int i;
for (i=0;i<=bloc->NbInstr;i++)
{
TabCom[bloc->TabInstr[i].Type](bloc->TabInstr[i].NbArg,bloc->TabInstr[i].TabArg);
}
}
/* Construction de l'interface graphique */
void BuildGUI(int IsFather)
{
int i;
if (scriptprop->font==NULL)
x11base->font=strdup("fixed");
else
x11base->font=scriptprop->font;
if (scriptprop->forecolor==NULL)
x11base->forecolor=strdup("black");
else
x11base->forecolor=scriptprop->forecolor;
if (scriptprop->backcolor==NULL)
x11base->backcolor=strdup("white");
else
x11base->backcolor=scriptprop->backcolor;
if (scriptprop->shadcolor==NULL)
x11base->shadcolor=strdup("black");
else
x11base->shadcolor=scriptprop->shadcolor;
if (scriptprop->licolor==NULL)
x11base->licolor=strdup("black");
else
x11base->licolor=scriptprop->licolor;
x11base->icon=scriptprop->icon;
x11base->size.x=scriptprop->x;
x11base->size.y=scriptprop->y;
x11base->size.width=scriptprop->width;
x11base->size.height=scriptprop->height;
x11base->title=scriptprop->titlewin;
/* Initialisation du serveur X et de la fenetre */
Xinit(IsFather);
OpenWindow();
/* Parcour de tous les objets graphiques */
nbobj++;
for (i=0;i<nbobj;i++)
{
tabxobj[i]=(struct XObj*)calloc(1,sizeof(struct XObj));
tabxobj[i]->id=(*tabobj)[i].id;
tabxobj[i]->x=(*tabobj)[i].x;
tabxobj[i]->y=(*tabobj)[i].y;
tabxobj[i]->width=(*tabobj)[i].width;
tabxobj[i]->height=(*tabobj)[i].height;
if (tabxobj[i]->width==0) tabxobj[i]->width=1;
if (tabxobj[i]->height==0) tabxobj[i]->height=1;
tabxobj[i]->value=(*tabobj)[i].value;
tabxobj[i]->value2=(*tabobj)[i].value2;
tabxobj[i]->value3=(*tabobj)[i].value3;
tabxobj[i]->flags[0]=(*tabobj)[i].flags[0];
tabxobj[i]->flags[1]=(*tabobj)[i].flags[1];
tabxobj[i]->flags[2]=(*tabobj)[i].flags[2];
tabxobj[i]->icon=(*tabobj)[i].icon;
tabxobj[i]->swallow=(*tabobj)[i].swallow;
if ((*tabobj)[i].title==NULL)
tabxobj[i]->title=(char*)calloc(1,200);
else
tabxobj[i]->title=(*tabobj)[i].title;
if ((*tabobj)[i].font==NULL)
tabxobj[i]->font=(char*)strdup(x11base->font);
else
tabxobj[i]->font=(*tabobj)[i].font;
if ((*tabobj)[i].forecolor==NULL)
tabxobj[i]->forecolor=(char*)strdup(x11base->forecolor);
else
tabxobj[i]->forecolor=(*tabobj)[i].forecolor;
if ((*tabobj)[i].backcolor==NULL)
tabxobj[i]->backcolor=(char*)strdup(x11base->backcolor);
else
tabxobj[i]->backcolor=(*tabobj)[i].backcolor;
if ((*tabobj)[i].shadcolor==NULL)
tabxobj[i]->shadcolor=(char*)strdup(x11base->shadcolor);
else
tabxobj[i]->shadcolor=(*tabobj)[i].shadcolor;
if ((*tabobj)[i].licolor==NULL)
tabxobj[i]->licolor=strdup(x11base->licolor);
else
tabxobj[i]->licolor=(*tabobj)[i].licolor;
ChooseFunction(tabxobj[i],(*tabobj)[i].type);
tabxobj[i]->gc=x11base->gc;
tabxobj[i]->display=x11base->display;
tabxobj[i]->ParentWin=&(x11base->win);
tabxobj[i]->Screen=x11base->screen;
tabxobj[i]->colormap=&(x11base->colormap);
tabxobj[i]->iconPixmap=None;
tabxobj[i]->icon_maskPixmap=None;
LoadIcon(tabxobj[i]); /* Chargement de l'icone du widget */
tabxobj[i]->InitObj(tabxobj[i]);
}
/* Enregistrement du bloc de taches periodic */
x11base->periodictasks=scriptprop->periodictasks;
/*Si un bloc d'initialisation du script existe, on l'execute ici */
if (scriptprop->initbloc!=NULL)
{
ExecBloc(scriptprop->initbloc);
free(scriptprop->initbloc->TabInstr);
free(scriptprop->initbloc);
}
free(tabobj);
free(scriptprop);
XMapRaised(x11base->display,x11base->win);
for (i=0;i<nbobj;i++)
if (tabxobj[i]->flags[0]!=True)
XMapWindow(x11base->display,tabxobj[i]->win);
}
/***********************************************/
/* Fonction de traitement des msg entre objets */
/***********************************************/
void SendMsg(struct XObj *xobj,int TypeMsg)
{
int i;
for (i=0;i<=TabCObj[TabIdObj[xobj->id]].NbCase;i++)
if (TabCObj[TabIdObj[xobj->id]].LstCase[i]==TypeMsg)
{
/* Execution du bloc d'instruction */
ExecBloc(&TabIObj[TabIdObj[xobj->id]][i]);
}
}
/*******************************************/
/* Appeler lors d'une demande de selection */
/*******************************************/
void SendMsgToScript(XEvent event)
{
Atom Sender,Receiver=None;
static XEvent evnt_sel;
int i;
Sender=XInternAtom(x11base->display,x11base->TabScriptId[1],True);
if (event.xselectionrequest.selection==Sender)
{
i=0;
while ((i<BuffSend.NbMsg)&&(event.xselectionrequest.target!=Receiver))
{
Receiver=XInternAtom(x11base->display,BuffSend.TabMsg[i].R,True);
i++;
}
i--;
evnt_sel.type=SelectionNotify;
evnt_sel.xselection.requestor=event.xselectionrequest.requestor;
evnt_sel.xselection.selection=event.xselectionrequest.selection;
evnt_sel.xselection.target=Receiver;
evnt_sel.xselection.time=event.xselectionrequest.time;
if (event.xselectionrequest.target==Receiver) /* On a trouve le recepteur */
{
evnt_sel.xselection.property=event.xselectionrequest.property;
XChangeProperty(x11base->display,evnt_sel.xselection.requestor,
evnt_sel.xselection.property,
evnt_sel.xselection.target,
8,PropModeReplace,BuffSend.TabMsg[i].Msg,strlen(BuffSend.TabMsg[i].Msg)+1);
BuffSend.NbMsg--;
free(BuffSend.TabMsg[i].Msg);
if (BuffSend.NbMsg>0)
{
memmove(&BuffSend.TabMsg[i],&BuffSend.TabMsg[i+1],(BuffSend.NbMsg-i)*sizeof(TypeName));
}
}
else
{ /* Cas ou le recepteur demande un message et qu'il n'y en a pas */
evnt_sel.xselection.property=None;
}
XSendEvent(x11base->display,evnt_sel.xselection.requestor,False,0,&evnt_sel);
}
}
/* read an X event */
void ReadXServer ()
{
static XEvent event,evnt_sel;
int i;
char *octet;
while (XEventsQueued(x11base->display, QueuedAfterReading))
{
XNextEvent(x11base->display, &event);
switch (event.type)
{
case Expose:
if (event.xexpose.count==0)
for (i=0;i<nbobj;i++)
tabxobj[i]->DrawObj(tabxobj[i]);
break;
case KeyPress:
/* Touche presse dans un objet */
if (event.xkey.subwindow!=0)
{
/* Envoi de l'evt <20> l'objet */
for (i=0;i<nbobj;i++)
if (tabxobj[i]->win==event.xkey.subwindow)
tabxobj[i]->EvtKey(tabxobj[i],&event.xkey);
}
break;
case ButtonPress:
/* Clique dans quel fenetre? */
if (event.xbutton.subwindow!=0)
{
i=0;
while ((tabxobj[i]->win!=event.xbutton.subwindow)&&(i<nbobj-1))
i++;
tabxobj[i]->EvtMouse(tabxobj[i],&event.xbutton);
}
break;
case ButtonRelease:
break;
case EnterNotify:
break;
case LeaveNotify:
break;
case MotionNotify:
break;
case MappingNotify:
XRefreshKeyboardMapping((XMappingEvent*)&event);
break;
case SelectionRequest:
if (event.xselectionrequest.selection==XA_PRIMARY)
{
evnt_sel.type=SelectionNotify;
evnt_sel.xselection.requestor=event.xselectionrequest.requestor;
evnt_sel.xselection.selection=event.xselectionrequest.selection;
evnt_sel.xselection.target=event.xselectionrequest.target;
evnt_sel.xselection.time=event.xselectionrequest.time;
evnt_sel.xselection.property=event.xselectionrequest.property;
switch (event.xselectionrequest.target)
{
case XA_STRING:
XChangeProperty(x11base->display,evnt_sel.xselection.requestor,
evnt_sel.xselection.property,
evnt_sel.xselection.target,
8,PropModeReplace,Scrapt,strlen(Scrapt)+1);
break;
default:evnt_sel.xselection.property=None;
}
XSendEvent(x11base->display,evnt_sel.xselection.requestor,False,0,&evnt_sel);
}
else
SendMsgToScript(event);
break;
case SelectionClear:
if (event.xselectionclear.selection==XA_PRIMARY)
UnselectAllTextField(tabxobj);
break;
case ClientMessage:
if ((event.xclient.format==32) && (event.xclient.data.l[0]==wm_del_win))
DeadPipe(1);
break;
case PropertyNotify:
if (event.xproperty.atom==XA_CUT_BUFFER0)
octet=XFetchBuffer(x11base->display,&i,0);
else if (event.xproperty.atom==XA_CUT_BUFFER1)
octet=XFetchBuffer(x11base->display,&i,1);
else if (event.xproperty.atom==XA_CUT_BUFFER2)
octet=XFetchBuffer(x11base->display,&i,2);
else if (event.xproperty.atom==XA_CUT_BUFFER3)
octet=XFetchBuffer(x11base->display,&i,3);
else if (event.xproperty.atom==XA_CUT_BUFFER4)
octet=XFetchBuffer(x11base->display,&i,4);
else if (event.xproperty.atom==XA_CUT_BUFFER5)
octet=XFetchBuffer(x11base->display,&i,5);
else if (event.xproperty.atom==XA_CUT_BUFFER6)
octet=XFetchBuffer(x11base->display,&i,6);
else if (event.xproperty.atom==XA_CUT_BUFFER7)
octet=XFetchBuffer(x11base->display,&i,7);
else break;
if (i>0)
{
Scrapt=(char*)realloc((void*)Scrapt,sizeof(char)*(i+1));
Scrapt=strcpy(Scrapt,octet);
}
break;
}
}
}
/* main event loop */
void MainLoop ()
{
fd_set in_fdset;
unsigned long header[HEADER_SIZE];
unsigned long *body;
int count,i;
struct timeval tv;
int res;
while (1)
{
FD_ZERO(&in_fdset);
FD_SET(x_fd,&in_fdset);
FD_SET(fd[1],&in_fdset);
XFlush(x11base->display);
tv.tv_sec = 1;
tv.tv_usec = 0;
if (x11base->periodictasks!=NULL)
res=select(32, SELECT_TYPE_ARG234 &in_fdset, NULL, NULL, &tv);
else
res=select(32, SELECT_TYPE_ARG234 &in_fdset, NULL, NULL, NULL);
if (res > 0)
{
if (FD_ISSET(x_fd, &in_fdset))
ReadXServer();
if(FD_ISSET(fd[1], &in_fdset))
{
if((count = ReadFvwmPacket(fd[1], header, &body)) > 0)
{
for (i=0;i<nbobj;i++)
tabxobj[i]->ProcessMsg(tabxobj[i],header[1],body);
free(body);
}
}
}
if (x11base->periodictasks!=NULL) /* Execution des taches periodics */
ExecBloc(x11base->periodictasks);
}
}
void ReadFvwmScriptArg(int argc, char **argv,int IsFather)
{
int i;
Atom myatom;
int FisrtArg;
BuffSend.NbMsg=0; /* Aucun message dans le buffer */
for (i=2;i<98;i++)
x11base->TabScriptId[i]=NULL;
if (IsFather) /* Cas du pere */
{
myatom=XInternAtom(x11base->display,x11base->TabScriptId[1],True);
XSetSelectionOwner(x11base->display,myatom,x11base->win,CurrentTime);
FisrtArg=9;
}
else
{ /* Cas du fils */
x11base->TabScriptId[0]=(char*)calloc(sizeof(char),strlen(argv[7]));
x11base->TabScriptId[0]=strncpy(x11base->TabScriptId[0],argv[7],strlen("FvwmScript")+3);
x11base->TabScriptId[1]=argv[7];
myatom=XInternAtom(x11base->display,x11base->TabScriptId[1],True);
XSetSelectionOwner(x11base->display,myatom,x11base->win,CurrentTime);
FisrtArg=8;
}
}
/* main procedure */
int main (int argc, char **argv)
{
int IsFather;
int i;
/* we get rid of the path from program name */
ModuleName = argv[0];
/* On determine si le script a un pere */
if (argc>=8)
IsFather=(argv[7][0]!=(char)161);
else
IsFather=1;
signal (SIGPIPE, DeadPipe);
signal (SIGINT, DeadPipe); /* cleanup on other ways of closing too */
signal (SIGHUP, DeadPipe);
signal (SIGQUIT, DeadPipe);
signal (SIGTERM, DeadPipe);
if (argc < 6)
{
fprintf(stderr,"%s must be started by Fvwm.\n", ModuleName);
exit(1);
}
else
if(argc>=7)
{
ScriptName = argv[6];
ref = strtol(argv[4], NULL, 16);
if (ref == 0) ref = None;
fd[0] = atoi(argv[1]);
fd[1] = atoi(argv[2]);
SetMessageMask(fd, M_NEW_DESK | M_END_WINDOWLIST|
M_MAP| M_RES_NAME| M_RES_CLASS| M_CONFIG_INFO|
M_END_CONFIG_INFO| M_WINDOW_NAME);
/* Enregistrement des arguments du script */
x11base=(X11base*) calloc(1,sizeof(X11base));
x11base->TabArg[0]=ModuleName;
for (i=8-IsFather;i<argc;i++)
x11base->TabArg[i-7+IsFather]=argv[i];
}
else
{
fprintf(stderr,"%s requires only the path of the script.\n", ModuleName);
exit(1);
}
ParseOptions();
SendText(fd,"Send_WindowList",0);
ReadConfig(ScriptName); /* Lecture et analyse du script */
InitCom(); /* Fonction d'initialisation de TabCom et TabFunc */
BuildGUI(IsFather); /* Construction des boutons et de la fenetre */
ReadFvwmScriptArg(argc,argv,IsFather);
MainLoop();
return 0;
}