/* -*-c-*- */
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Start ;-) button handling */
#include "config.h"
#include <X11/Xlib.h>
#include <stdio.h>
#include "libs/fvwmlib.h"
#include "libs/Flocale.h"
#include "libs/Picture.h"
#include "libs/Module.h"
#include "libs/Parse.h"
#include "libs/Strings.h"
#include "ButtonArray.h"
#include "Mallocs.h"
#include "Start.h"
extern Display *dpy;
extern Window Root, win;
extern FlocaleFont *FButtonFont, *FSelButtonFont;
extern ModuleArgs *module;
extern char *ImagePath;
Button *StartButton;
Bool NoDefaultStartButton = False;
int StartAndLaunchButtonsWidth = 0;
int StartAndLaunchButtonsHeight = 0;
int WindowButtonsLeftMargin = 4; /* default value is 4 */
int WindowButtonsRightMargin = 2; /* default value is 2 */
int StartButtonRightMargin = 0; /* default value is 0 */
int has_wb_left_margin = 0;
int has_wb_right_margin = 0;
Bool StartButtonOpensAboveTaskBar = False;
char *StartName = NULL,
*StartCommand = NULL,
*StartPopup = NULL,
*StartIconName = NULL;
StartAndLaunchButtonItem *First_Start_Button = NULL;
StartAndLaunchButtonItem *Last_Start_Button = NULL;
static char *startopts[] =
{
"StartName",
"StartMenu",
"StartIcon",
"StartCommand",
"NoDefaultStartButton",
"Button",
"WindowButtonsLeftMargin",
"WindowButtonsRightMargin",
"StartButtonRightMargin",
NULL
};
Bool StartButtonParseConfig(char *tline)
{
char *rest;
char *option;
int i, j, k;
int titleRecorded = 0, iconRecorded = 0;
char *tokens[100]; /* This seems really big */
char *strtok_ptr;
StartAndLaunchButtonItem *tempPtr;
int mouseButton;
char **tmpStrPtr;
option = tline + module->namelen+1;
i = GetTokenIndex(option, startopts, -1, &rest);
while (*rest && *rest != '\n' && isspace(*rest))
{
rest++;
}
switch(i)
{
case 0: /* StartName */
if (First_Start_Button == NULL)
{
First_Start_Button = Last_Start_Button =
(StartAndLaunchButtonItem*)safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(First_Start_Button);
First_Start_Button->isStartButton = True;
}
else if (First_Start_Button->isStartButton == False)
{
/* shortcut button has been declared before start
* button */
tempPtr = (StartAndLaunchButtonItem*)safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(tempPtr);
tempPtr->tail = First_Start_Button;
First_Start_Button = tempPtr;
First_Start_Button->isStartButton = True;
}
else if (First_Start_Button->buttonCaption != NULL)
{
/* declarin caption twice, ignore */
break;
}
CopyString(&(First_Start_Button->buttonCaption), rest);
break;
case 1: /* StartMenu */
rest = ParseButtonOptions(rest, &mouseButton);
if (First_Start_Button == NULL)
{
First_Start_Button = Last_Start_Button =
(StartAndLaunchButtonItem*)safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(First_Start_Button);
First_Start_Button->isStartButton = True;
}
else if (First_Start_Button->isStartButton == False)
{
/* shortcut button has been declared before start
* button */
tempPtr = (StartAndLaunchButtonItem*) safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(tempPtr);
tempPtr->tail = First_Start_Button;
First_Start_Button = tempPtr;
First_Start_Button->isStartButton = True;
}
tmpStrPtr = (mouseButton ?
&(First_Start_Button->buttonCommands[mouseButton-1])
:
&(First_Start_Button->buttonCommand));
if (*tmpStrPtr)
{
/* declaring command twice, ignore */
break;
}
CopyString(tmpStrPtr, rest);
break;
case 2: /* StartIcon */
if (First_Start_Button == NULL)
{
First_Start_Button = Last_Start_Button =
(StartAndLaunchButtonItem*)safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(First_Start_Button);
First_Start_Button->isStartButton = True;
}
else if (First_Start_Button->isStartButton == False)
{
/* shortcut button has been declared before start
* button */
tempPtr = (StartAndLaunchButtonItem*) safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(tempPtr);
tempPtr->tail = First_Start_Button;
First_Start_Button = tempPtr;
First_Start_Button->isStartButton = True;
}
else if (First_Start_Button->buttonIconFileName != NULL)
{
/* declaring icon twice, ignore */
break;
}
CopyString(&(First_Start_Button->buttonIconFileName), rest);
break;
case 3: /* StartCommand */
rest = ParseButtonOptions(rest, &mouseButton);
if (First_Start_Button == NULL)
{
First_Start_Button = Last_Start_Button =
(StartAndLaunchButtonItem*)safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(First_Start_Button);
First_Start_Button->isStartButton = True;
}
else if (First_Start_Button->isStartButton == False)
{
/* shortcut button has been declared before start
* button */
tempPtr = (StartAndLaunchButtonItem*)safemalloc(
sizeof(StartAndLaunchButtonItem));
StartAndLaunchButtonItemInit(tempPtr);
tempPtr->tail = First_Start_Button;
First_Start_Button = tempPtr;
First_Start_Button->isStartButton = True;
}
tmpStrPtr =
(mouseButton ?
&(First_Start_Button->buttonStartCommands[mouseButton-1]) :
&(First_Start_Button->buttonStartCommand));
if (*tmpStrPtr)
{
/* declaring command twice, ignore */
break;
}
CopyString(tmpStrPtr, rest);
break;
case 4: /* NoDefaultStartButton */
NoDefaultStartButton = True;
break;
case 5: /* Button */
if (Last_Start_Button == NULL)
{
First_Start_Button = Last_Start_Button =
(StartAndLaunchButtonItem*)safemalloc(
sizeof(StartAndLaunchButtonItem));
}
else
{
Last_Start_Button->tail =
(StartAndLaunchButtonItem*) safemalloc(
sizeof(StartAndLaunchButtonItem));
Last_Start_Button = Last_Start_Button->tail;
}
StartAndLaunchButtonItemInit(Last_Start_Button);
j=0;
titleRecorded = iconRecorded = 0;
tokens[j++] = strtok_r(rest, ",", &strtok_ptr);
while((tokens[j++] = strtok_r(NULL, ",", &strtok_ptr)))
{
while(isspace(*(tokens[j-1])))
{
tokens[j-1]+=sizeof(char);
}
}
j--;
for(k=0;k<j;k++)
{
if (strncasecmp(tokens[k], "Title", 5)==0)
{
tokens[j+1] = tokens[k] + ((sizeof(char))*5);
while(*(tokens[j+1])==' ')
tokens[j+1]+=sizeof(char);
CopyString(
&(Last_Start_Button->buttonCaption),
tokens[j+1]);
titleRecorded=1;
}
else if (strncasecmp(tokens[k], "Icon", 4)==0)
{
tokens[j+1] = tokens[k] + ((sizeof(char))*4);
while(*(tokens[j+1])==' ')
tokens[j+1]+=sizeof(char);
CopyString(
&(Last_Start_Button->buttonIconFileName),
tokens[j+1] );
iconRecorded = 1;
}
else if (strncasecmp(tokens[k], "Action", 6)==0)
{
rest = tokens[k] + ((sizeof(char))*6);
rest = ParseButtonOptions(rest, &mouseButton);
tokens[j+1] = rest;
if (mouseButton)
{
tmpStrPtr =
&(Last_Start_Button->
buttonStartCommands
[mouseButton-1]);
}
else
{
tmpStrPtr =
&(Last_Start_Button->
buttonStartCommand);
}
if (!(*tmpStrPtr))
{
/* don't let them set the same action
* twice */
CopyString(tmpStrPtr, tokens[j+1]);
}
}
}
if (titleRecorded==0)
{
CopyString(&(Last_Start_Button->buttonCaption), "\0");
}
if (iconRecorded==0)
{
CopyString(
&(Last_Start_Button->buttonIconFileName),
"\0");
}
break;
case 6: /* WindowButtonsLeftMargin */
if(atoi(rest)>=0)
{
WindowButtonsLeftMargin = atoi(rest);
has_wb_left_margin = 1;
}
break;
case 7: /* WindowButtonsRightMargin */
if(atoi(rest)>=0)
{
WindowButtonsRightMargin = atoi(rest);
has_wb_right_margin = 1;
}
break;
case 8: /* StartButtonRightMargin */
if(atoi(rest)>=0)
{
StartButtonRightMargin = atoi(rest);
}
break;
default:
/* unknown option */
return False;
} /* switch */
return True;
}
/* Parse and set options for this taskbar button (start or launcher). This
* will check for a string of the form (<opt1>,<opt2>...), similar to options
* for an FvwmButtons button. The return value is a pointer to the rest of the
* config line.
*
* Currently this sets just one option, mouseButton. If no "Mouse <n>" option
* is found, mouseButton will be set to 0.
*/
char *ParseButtonOptions(char *pos, int *mouseButton)
{
char *token = NULL;
char *rest;
int i;
static char *buttonOptions[] = {"Mouse", NULL};
*mouseButton = 0;
while (*pos && isspace(*pos))
pos++;
if (*pos != '(')
return pos;
pos++;
while (*pos && isspace(*pos))
pos++;
while (*pos && *pos != ')')
{
pos = GetNextToken(pos, &token);
if (!token)
break;
i = GetTokenIndex(token, buttonOptions, 0, NULL);
switch (i)
{
case 0: /* Mouse */
*mouseButton = strtol(pos, &rest, 10);
pos = rest;
if (*mouseButton < 1 || *mouseButton > NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
{
fprintf(stderr,"%s: Invalid mouse button %d", module->name,
*mouseButton);
*mouseButton = 0;
}
break;
default:
fprintf(stderr,"%s: Invalid taskbar button option '%s'", module->name,
token);
}
while (*pos && *pos != ',' && *pos != ')')
pos++;
if (*pos == ',') {
pos++;
while (*pos && *pos != ',' && *pos != ')')
pos++;
}
free(token);
}
if (*pos)
pos++;
while (*pos && isspace(*pos))
pos++;
return pos;
}
void StartButtonInit(int height)
{
FvwmPicture *p = NULL;
int pw;
FvwmPictureAttributes fpa;
StartAndLaunchButtonItem *tempPtr;
fpa.mask = FPAM_NO_ALLOC_PIXELS;
/* if no start button params were specified, trick the program into
* thinking that they were */
if (First_Start_Button == NULL && !NoDefaultStartButton)
{
StartButtonParseConfig("*FvwmTaskBarStartName Start");
StartButtonParseConfig("*FvwmTaskBarStartMenu RootMenu");
StartButtonParseConfig("*FvwmTaskBarStartIcon mini.start.xpm");
}
/* some defaults */
if (First_Start_Button && First_Start_Button->isStartButton == True)
{
if (First_Start_Button->buttonCaption == NULL)
UpdateString(&(First_Start_Button->buttonCaption), "Start");
if (First_Start_Button->buttonIconFileName == NULL)
UpdateString(&(First_Start_Button->buttonIconFileName), "mini-start.xpm");
}
tempPtr = First_Start_Button;
while(tempPtr != NULL)
{
p = PGetFvwmPicture(
dpy, win, ImagePath, tempPtr->buttonIconFileName, fpa);
if (p != NULL && strlen(tempPtr->buttonCaption) != 0)
{
/* icon and title */
pw = p->width + 12;
}
else if (p != NULL)
{
/* just icon */
pw = p->width + 8;
}
else
{
/* just title */
pw = 10;
}
tempPtr->buttonItem = (Button *)ButtonNew(
tempPtr->buttonCaption, p, BUTTON_UP,0);
if (tempPtr->isStartButton)
{
StartButton = tempPtr->buttonItem;
tempPtr->width = FlocaleTextWidth(
FSelButtonFont, tempPtr->buttonCaption,
strlen(tempPtr->buttonCaption)) + pw;
}
else
{
tempPtr->width = FlocaleTextWidth(
FButtonFont, tempPtr->buttonCaption,
strlen(tempPtr->buttonCaption)) + pw;
}
tempPtr->height = height;
StartAndLaunchButtonsWidth += tempPtr->width;
tempPtr=tempPtr->tail;
PFreeFvwmPictureData(p); /* should not destroy of course */
}
if (First_Start_Button)
{
StartAndLaunchButtonsWidth += StartButtonRightMargin;
First_Start_Button->height = height;
StartAndLaunchButtonsHeight = First_Start_Button->height;
}
else
{
StartAndLaunchButtonsWidth = 0;
StartButtonRightMargin = 0;
if (has_wb_left_margin == 0)
{
WindowButtonsLeftMargin = 0;
}
if (has_wb_right_margin == 0)
{
WindowButtonsRightMargin = 0;
}
}
}
int StartButtonUpdate(const char *title, int index, int state)
{
int i=0;
StartAndLaunchButtonItem *tempPtr = First_Start_Button;
#if 0
if (title != NULL)
ConsoleMessage("Updating StartTitle not supported yet...\n");
if(index != -1)
{
for(i=0; i<index; i++)
tempPtr = tempPtr->tail;
ButtonUpdate(tempPtr->buttonItem, title, state);
}
else
while(tempPtr != NULL)
{
ButtonUpdate(tempPtr->buttonItem, title, state);
tempPtr = tempPtr->tail;
}
#else
if (!First_Start_Button)
{
return 0;
}
if(index != -1)
{
for(i=0; i<index; i++)
tempPtr = tempPtr->tail;
ButtonUpdate(tempPtr->buttonItem, title, state);
}
else
while(tempPtr != NULL)
{
ButtonUpdate(tempPtr->buttonItem, title, state);
tempPtr = tempPtr->tail;
}
#endif
tempPtr = First_Start_Button;
while(tempPtr != NULL)
{
if (tempPtr->buttonItem->needsupdate)
return 1;
tempPtr = tempPtr->tail;
}
return 0;
}
void StartButtonDraw(int force, XEvent *evp)
{
int tempsum, j, i = 0;
StartAndLaunchButtonItem *tempPtr = First_Start_Button;
StartAndLaunchButtonItem *tempPtr2 = First_Start_Button;
if (!First_Start_Button)
{
return;
}
while(tempPtr != NULL)
{
if(tempPtr->buttonItem->needsupdate || force)
{
tempsum = 0;
j=0;
tempPtr2 = First_Start_Button;
while((tempPtr2 != NULL) && (j<i))
{
tempsum+=tempPtr2->width;
tempPtr2 = tempPtr2->tail;
j++;
}
if (!(tempPtr->isStartButton))
ButtonDraw(
tempPtr->buttonItem,
tempsum+StartButtonRightMargin, 0,
tempPtr->width,
First_Start_Button->height, evp);
else
ButtonDraw(
tempPtr->buttonItem,
tempsum, 0, tempPtr->width,
First_Start_Button->height, evp);
}
tempPtr = tempPtr->tail;
i++;
}
}
/* Returns 1 if in the start or a minibutton, 0 if not; index of button
* pressed put in startButtonPressed */
int MouseInStartButton(int x, int y, int *whichButton,
Bool *startButtonPressed, int *button_x)
{
int i = 0;
int tempsum = 0;
StartAndLaunchButtonItem *tempPtr = First_Start_Button;
*startButtonPressed = False;
while(tempPtr != NULL)
{
if (x >= tempsum && x < tempsum+tempPtr->width && y > 0 && y < First_Start_Button->height)
{
*whichButton = i;
if (button_x)
{
*button_x = tempsum;
}
if(tempPtr->isStartButton)
*startButtonPressed = True;
return 1;
}
tempsum += tempPtr->width;
tempPtr = tempPtr->tail;
i++;
}
*whichButton = -1;
return 0;
}
void getButtonCommand(int whichButton, char *tmp, int mouseButton)
{
int i=0;
StartAndLaunchButtonItem *tempPtr = First_Start_Button;
if (!First_Start_Button)
{
return;
}
for(i=0; i<whichButton; i++)
tempPtr = tempPtr->tail;
mouseButton--;
if (mouseButton < NUMBER_OF_EXTENDED_MOUSE_BUTTONS &&
tempPtr->buttonCommands[mouseButton])
sprintf(tmp, "Popup %s rectangle $widthx$height+$left+$top 0 -100m",
tempPtr->buttonCommands[mouseButton]);
else if (mouseButton < NUMBER_OF_EXTENDED_MOUSE_BUTTONS &&
tempPtr->buttonStartCommands[mouseButton])
sprintf(tmp, "%s", tempPtr->buttonStartCommands[mouseButton]);
else if (tempPtr->buttonCommand)
sprintf(tmp, "Popup %s rectangle $widthx$height+$left+$top 0 -100m",
tempPtr->buttonCommand);
else if (tempPtr->buttonStartCommand)
sprintf(tmp, "%s", tempPtr->buttonStartCommand);
else if (tempPtr->isStartButton)
sprintf(tmp, "Popup StartMenu");
else
sprintf(tmp, "Nop");
}
void StartAndLaunchButtonItemInit(StartAndLaunchButtonItem *item)
{
int i;
item->head = NULL;
item->tail = NULL;
item->index = 0;
item->width = 0;
item->height = 0;
item->isStartButton = False;
item->buttonItem = NULL;
item->buttonCommand = NULL;
item->buttonStartCommand = NULL;
item->buttonCaption = NULL;
item->buttonIconFileName = NULL;
item->buttonToolTip = NULL;
for (i=0; i < NUMBER_OF_EXTENDED_MOUSE_BUTTONS; i++)
{
item->buttonCommands[i] = NULL;
item->buttonStartCommands[i] = NULL;
}
}
syntax highlighted by Code2HTML, v. 0.9.1