dockapps/wmmenu/options.c

303 lines
7.3 KiB
C
Raw Normal View History

/* ANSI */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* POSIX */
#include <getopt.h>
#include "options.h"
#include "version.h"
#include "error.h"
#include "utils.h"
#include "types.h"
#include "menu.h"
#define MAXOPTIONS (20)
#ifndef ETCDIR
#define ETCDIR "/usr/local/etc"
#endif
#define DEFAULTPATH (ETCDIR ":.")
#define BLANKS " \t\f\r\n"
#define SPACES " \t\f"
#define ENDLINE "\r\n"
int TileXSize = 0 ;
int TileYSize = 0 ;
char MenuName [40] = "" ;
static char MyPixmapPath [1024] = "" ;
char * PixmapPath = MyPixmapPath ;
static char MyTilePath [FILENAME_MAX] = "" ;
char * TilePath = MyTilePath ;
static char MyHighlightPath [FILENAME_MAX] = "" ;
char * HighlightPath = MyHighlightPath ;
bool ClickOnly = false ;
bool AutoScale = true ;
bool HighlightBehind = false ;
int HideTimeout = 1 ;
int Options_Argc = 0 ;
char * Options_Argv [MAXOPTIONS] ;
static void Usage (void)
{
printf("Usage: wmmenu [<options>...][-- <dockoptions>...]\n");
printf("Normal options:\n");
printf("-m MENUNAME set the name of the menu file to load from ~/.wmmenu\n");
printf("-g WxH force width and height of tile\n");
printf("-l XPMFILE set the pixmap used to highlight icon under cursor\n");
printf("-t XPMFILE set the pixmap used as button bar background\n");
printf("-O click bar is only triggered by clicks on the tile, not moves\n");
printf("-O noautoscale disable automatic pixmap scaling to tile size\n");
printf("-O behind draw highlight pixmap behind icon, not above\n");
printf("-O hide=N set bar hiding timeout to N ms (default one)\n");
printf("-r ROWS set number of menu rows (default one)\n");
printf("-v print version information\n");
printf("-h print this help message\n");
printf("Note:\n");
printf(" -t, -l and '-O behind' can also be specified with the defaults file.\n");
}
static void SetGeometry (const char * val)
{
if (sscanf (val, "%dx%d", &TileXSize, &TileYSize) != 2)
error ("bad tile geometry \"%s\"", val) ;
else
if (64 < TileXSize || TileXSize < 0)
error ("incorrect tile width %d", TileXSize) ;
else
if (64 < TileYSize || TileYSize < 0)
error ("incorrect tile height %d", TileYSize) ;
}
static void SetTilePath (const char * value)
{
char *ptrToFree = NULL ;
if (value != NULL && value[0] == '!')
{
ptrToFree = File_ReadOutputFromCommand (value+1) ;
if ((value = ptrToFree) == NULL)
value = "" ;
}
sprintf (MyTilePath, "%.*s", (int)(sizeof MyTilePath)-1, value) ;
if (ptrToFree != NULL)
free (ptrToFree) ;
}
static void SetHighlightPath (const char * value)
{
sprintf (MyHighlightPath, "%.*s", (int)(sizeof MyHighlightPath)-1, value) ;
}
static void SetHideTimeout (const char * value)
{
HideTimeout = atoi (value) ;
if (HideTimeout <= 0)
{
warn ("hide_timeout must be a strictly positive integer") ;
HideTimeout = 1 ;
}
/* no maximum -- for players */
}
static void AddPixmapPath (const char * value)
{
int curLen ;
int szLeft ;
curLen = strlen (MyPixmapPath) ;
szLeft = (sizeof MyPixmapPath) - curLen ;
/* don't forget to count space for ':' and ending EOS */
sprintf (MyPixmapPath+curLen, ":%.*s", szLeft-2, value) ;
}
static void InitDefaults (void)
{
char dftPixmapPath [FILENAME_MAX] ;
const char * home ;
if ((home = getenv ("HOME")) != NULL && home[0] != EOS)
{
sprintf (dftPixmapPath, "%.*s/.wmmenu",
(int)(sizeof dftPixmapPath)-10, home) ;
}
else
{
strcpy (dftPixmapPath, ".") ;
}
strcpy (MyPixmapPath, dftPixmapPath) ;
}
static void ParseDefaults (char * text)
{
char * p ;
const char * name ;
const char * value ;
assert (text != NULL) ;
p = text ;
p += strspn (p, BLANKS) ;
while (*p != EOS) switch (*p++)
{
case '#' :
p += strcspn (p, ENDLINE) ;
p += strspn (p, BLANKS) ;
break ;
default :
name = p-1 ;
p += strcspn (p, SPACES) ;
*p++ = EOS ;
p += strspn (p, SPACES) ;
value = p ;
p += strcspn (p, ENDLINE) ;
*p++ = EOS ;
p += strspn (p, BLANKS) ;
if (streq (name, "geometry")) SetGeometry (value) ;
else
if (streq (name, "xpmpath"))
{
AddPixmapPath (value) ;
}
else
if (streq (name, "tile"))
{
SetTilePath (value) ;
}
else
if (streq (name, "highlight"))
{
SetHighlightPath (value) ;
}
else
if (streq (name, "highlight_behind"))
{
HighlightBehind = true ;
}
else
if (streq (name, "hide_timeout"))
{
SetHideTimeout (value) ;
}
else error ("unknown setting \"%s\"", name) ;
break ;
}
}
extern void Options_ParseDefaults (void)
{
char pathList [1000] ;
char path [FILENAME_MAX] ;
const char * home ;
FILE * f ;
if ((home = getenv ("HOME")) != NULL && *home != EOS)
{
sprintf (pathList, "%s/.wmmenu:%s", home, DEFAULTPATH) ;
}
else
{
strcpy (pathList, DEFAULTPATH) ;
}
if (File_FindInPath (path, sizeof path, pathList, "defaults") &&
(f = fopen (path, "r")) != NULL)
{
char * text ;
text = File_ReadAll (f) ;
fclose (f) ;
InitDefaults () ;
ParseDefaults (text) ;
free (text) ;
}
}
extern void Options_Parse (int argc, char ** argv)
{
int opt ;
assert (argv != NULL) ;
assert (argc > 0) ;
Options_Argc = 0 ;
Options_Argv[Options_Argc++] = MenuName ;
while ((opt = getopt (argc, argv, "hg:l:m:r:t:vO:")) != EOF) switch (opt)
{
case 'g' :
SetGeometry (optarg) ;
break ;
case 'm' :
sprintf (MenuName, "%.*s", (int)(sizeof MenuName)-1, optarg) ;
break ;
case 'r' :
Menu_SetNbRows (optarg) ;
break ;
case 't' :
SetTilePath (optarg) ;
break ;
case 'l' :
sprintf (MyHighlightPath, "%.*s",
(int)(sizeof MyHighlightPath)-1, optarg) ;
break ;
case 'O' :
if (streq (optarg, "click")) ClickOnly = true ;
else if (streq (optarg, "noautoscale")) AutoScale = false ;
else if (streq (optarg, "behind")) HighlightBehind = true ;
else if (streql (optarg, "hide=", 5)) SetHideTimeout (optarg+5) ;
else printf ("ignoring unknown feature \"%s\"\n", optarg) ;
break ;
case 'v' :
printf ("wmmenu (c) F.COUTANT v%s\n", VERSION) ;
exit (EXIT_SUCCESS) ;
break ;
case 'h' :
Usage () ;
exit (EXIT_SUCCESS) ;
break ;
case '?' :
Usage () ;
exit (EXIT_FAILURE) ;
break ;
}
if (MenuName[0] == EOS)
error ("no menu file name specified") ;
if (MyTilePath[0] == EOS)
warn ("no tile pixmap specified, using internal default") ;
while (optind < argc && Options_Argc < MAXOPTIONS)
Options_Argv[Options_Argc++] = argv[optind++] ;
}
extern void Options_SetMenuName (const char * name)
{
sprintf (MenuName, "%.*s", (int)(sizeof MenuName)-1, name) ;
}