/****************************************************************************
* This module is mostly all new
* by Rob Nation
* Copyright 1993 Robert Nation. No restrictions are placed on this code,
* as long as the copyright notice is preserved
****************************************************************************
* slightly modified for BowMan
* by Bo Yang
*
* slightly modified for AfterStep
* by Frank Fejes
*
****************************************************************************
*
* Configure.c: reads the .steprc or system.steprc file, interprets it,
* and sets up menus, bindings, colors, and fonts as specified
*
***************************************************************************/
#include "../configure.h"
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#ifdef I18N
#include <X11/Xlocale.h>
#endif
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#ifdef M4
#include <X11/Xmu/SysUtil.h>
#endif
#include "afterstep.h"
#include "menus.h"
#include "misc.h"
#include "parse.h"
#include "screen.h"
#include "../version.h"
#define AFTER_BUTTONS 1
#define AFTER_ICONS 1
#include "asbuttons.h"
#ifdef XPM
#include <X11/xpm.h>
char *PixmapPath=AFTER_ICONDIR;
#endif
char *IconPath = AFTER_ICONDIR;
char *ModulePath = AFTERDIR;
char *white = "white";
char *black = "black";
char *grey = "SlateGrey";
char *Menuback;
char *Menufore;
char *Menustipple;
char *Stdback;
char *Stdfore;
char *Stickyback;
char *Stickyfore;
char *Hiback;
char *Hifore;
#ifndef NO_PAGER
char *Pagerback;
char *Pagerfore;
#endif
void GetColors(void);
Pixel GetColor(char *);
MenuRoot *NewMenuRoot(char *name);
char *stripcpy(char *);
char *stripcpy2(char *,int, Bool);
char *stripcpy3(char *, Bool);
#ifndef NO_PAGER
void initialize_pager(int x, int y);
#endif
void bad_binding(int num);
void nofont(char *name);
void nocolor(char *note, char *name);
int contexts;
int mods,func,func_val_1,func_val_2;
#ifndef NO_PAGER
int pager_x=10000,pager_y=10000;
#endif
#ifdef ENABLE_TEXTURE
#include "stepgfx.h"
char *TitleStyle=NULL;
char *TexTypes=NULL;
char *TexMaxcols=NULL;
char *TColor=NULL, *IColor=NULL, *MColor=NULL, *UColor=NULL, *SColor=NULL;
char *TGColor=NULL;
char *TPixmap=NULL,*UPixmap=NULL,*SPixmap=NULL;
extern void InitTextureData(TextureInfo *info, char *title, char*utitle,
char *mtitle, char *menu, char *sticky, char *text);
int IconTexType = TEXTURE_BUILTIN;
char *IconBgColor;
char *IconTexColor;
int IconMaxColors = 16;
char *IconPixmapFile;
int IconTexFlags = 0;
#endif
unsigned PopupCount = 0;
MenuRoot *PopupTable[MAXPOPUPS];
int dummy;
char *config_file = ".steprc";
extern XContext MenuContext; /* context for afterstep menus */
extern Bool DoHandlePageing;
/* value for the rubberband XORing */
unsigned long XORvalue;
int have_the_colors = 0;
/*
* Order is important here! if one keyword is the same as the first part of
* another keyword, the shorter one must come first!
*/
struct config main_config[] =
{
{"OpaqueResize", SetFlag, (char **)OpaqueResize,(int *)0},
{"StubbornIcons", SetFlag, (char **)StubbornIcons,(int *)0},
{"StubbornPlacement", SetFlag, (char **)StubbornPlacement,(int *)0},
{"StubbornIconPlacement", SetFlag, (char **)StubbornIconPlacement,
(int *)0},
{"Font", assign_string, &Scr.StdFont.name, (int *)0},
{"WindowFont", assign_string, &Scr.WindowFont.name, (int *)0},
{"MenuForeColor", assign_string, &Menufore, (int *)0},
{"MenuBackColor", assign_string, &Menuback, (int *)0},
{"MenuStippleColor", assign_string, &Menustipple, (int *)0},
{"StdForeColor", assign_string, &Stdfore, (int *)0},
{"StdBackColor", assign_string, &Stdback, (int *)0},
#ifdef XPM
{"PixmapPath", assign_string, &PixmapPath, (int *)0},
#endif
{"StickyForeColor", assign_string, &Stickyfore, (int *)0},
{"StickyBackColor", assign_string, &Stickyback, (int *)0},
{"HiForeColor", assign_string, &Hifore, (int *)0},
{"HiBackColor", assign_string, &Hiback, (int *)0},
{"IconPath", assign_string, &IconPath, (int *)0},
{"IconBox", SetBox, (char **)0, (int *)0},
{"StickyIcons", SetFlag, (char **)StickyIcons, (int *)0},
{"IconFont", assign_string, &Scr.IconFont.name, (int *)0},
{"IconTitle", SetFlag, (char **)IconTitle, (int*)0},
#ifndef PRUNE
{"Icon", SetOneStyle, (char **)&Scr.TheList,(int *)ICON_FLAG},
#endif
{"KeepIconWindows", SetFlag, (char **)KeepIconWindows, (int *)0},
/*
{"MWMDecorHints", SetFlag, (char **)MWMDecorHints, (int *)0},
{"MWMFunctionHints", SetFlag, (char **)MWMFunctionHints, (int *)0},
{"MWMHintOverride", SetFlag, (char **)MWMHintOverride, (int *)0},
*/
/* {"Lenience", SetFlag, (char **)Lenience, (int *)0},
*/
{"NoPPosition", SetFlag, (char **)NoPPosition, (int *)0},
{"CirculateSkipIcons",SetFlag, (char **)CirculateSkipIcons, (int *)0},
#ifndef PRUNE
{"NoFocus", SetOneStyle, (char **)&Scr.TheList,
(int *)NOFOCUS_FLAG},
{"NoTitle", SetOneStyle, (char **)&Scr.TheList,
(int *)NOTITLE_FLAG},
{"NoBorder", SetOneStyle, (char **)&Scr.TheList,
(int *)NOBORDER_FLAG},
{"Sticky", SetOneStyle, (char **)&Scr.TheList,
(int *)STICKY_FLAG},
{"StaysOnTop", SetOneStyle, (char **)&Scr.TheList,
(int *)STAYSONTOP_FLAG},
{"StartsOnDesk", SetOneStyle, (char **)&Scr.TheList,
(int *)STAYSONDESK_FLAG},
{"CirculateSkip", SetOneStyle, (char **)&Scr.TheList,
(int *)CIRCULATESKIP_FLAG},
{"WindowListSkip", SetOneStyle, (char **)&Scr.TheList,
(int *)LISTSKIP_FLAG},
#endif
{"Style", ParseStyle, (char **)0, (int *)0},
{"EdgeScroll", SetInts, (char **)&Scr.EdgeScrollX,
&Scr.EdgeScrollY},
{"RandomPlacement", SetFlag, (char **)RandomPlacement, (int *)0},
{"SmartPlacement", SetFlag, (char **)SMART_PLACEMENT, (int *)0},
#ifndef PRUNE
{"SuppressIcons", SetFlag, (char **)SuppressIcons, (int *)0},
#endif
{"DontMoveOff", SetFlag, (char **)DontMoveOff, (int *)0},
{"DecorateTransients",SetFlag, (char **)DecorateTransients, (int *)0},
{"CenterOnCirculate", SetFlag, (char **)CenterOnCirculate, (int *)0},
{"AutoRaise", SetInts, (char **)&Scr.AutoRaiseDelay,&dummy},
#ifndef NO_PAGER
{"PagerBackColor", assign_string, &Pagerback, (int *)0},
{"PagerForeColor", assign_string, &Pagerfore, (int *)0},
{"PagerFont", assign_string, &Scr.PagerFont.name, (int *)0},
{"Pager", SetInts, (char **)&pager_x, &pager_y},
#endif
{"DeskTopScale", SetInts, (char **)&Scr.VScale, &dummy},
{"DeskTopSize", SetInts, (char **)&Scr.VxMax, &Scr.VyMax},
{"ClickTime", SetInts, (char **)&Scr.ClickTime, &dummy},
{"OpaqueMove", SetInts, (char **)&Scr.OpaqueSize, &dummy},
#ifndef PRUNE
{"BoundaryWidth", SetInts, (char **)&Scr.BoundaryWidth,&dummy},
{"NoBoundaryWidth", SetInts, (char **)&Scr.NoBoundaryWidth,&dummy},
#endif
{"XorValue", SetInts, (char **)&XORvalue, &dummy},
{"Mouse", ParseMouseEntry,(char **)1, (int *)0},
{"Popup", ParsePopupEntry,(char **)1, (int *)0},
{"Function", ParsePopupEntry,(char **)1, (int *)0},
{"Key", ParseKeyEntry, (char **)1, (int *)0},
{"ClickToFocus", SetFlag, (char **)ClickToFocus,
(int *)EatFocusClick},
{"ClickToRaise", SetButtonList, (char **)&Scr.RaiseButtons, (int*)0},
{"MenusHigh", SetFlag, (char **)MenusHigh,(int *)0},
{"SloppyFocus", SetFlag, (char **)SloppyFocus,(int *)0},
{"Cursor", SetCursor, (char **)0, (int *)0},
{"PagingDefault", SetInts, (char **)&DoHandlePageing, &dummy},
{"EdgeResistance", SetInts, (char **)&Scr.ScrollResistance,
&Scr.MoveResistance},
{"BackingStore", SetFlag, (char **)BackingStore, (int *)0},
{"AppsBackingStore", SetFlag, (char **)AppsBackingStore, (int *)0},
{"SaveUnders", SetFlag, (char **)SaveUnders, (int *)0},
{"ModulePath", assign_string, &ModulePath, (int *)0},
#ifndef PRUNE
{"Module", executeModule, (char **)0, (int *)0},
#endif
#ifdef ENABLE_TEXTURE
{"TitleBarStyle", assign_string, &TitleStyle, (int *)0},
{"TextureTypes", assign_string, &TexTypes, (int *)0},
{"TextureMaxColors", assign_string, &TexMaxcols, (int *)0},
{"TitleTextureColor", assign_string, &TColor, (int*)0}, /* title */
{"MenuTextureColor", assign_string, &IColor, (int*)0}, /* menu items */
{"UTitleTextureColor", assign_string, &UColor, (int*)0}, /*unfocused title*/
{"MTitleTextureColor", assign_string, &MColor, (int*)0}, /* menu title */
{"STitleTextureColor", assign_string, &SColor, (int*)0}, /* sticky title */
{"TitlePixmap", assign_string, &TPixmap, (int*)0}, /* title pixmap */
{"UTitlePixmap", assign_string, &UPixmap, (int*)0}, /* title pixmap */
{"STitlePixmap", assign_string, &SPixmap, (int*)0}, /* title pixmap */
{"TextGradientColor", assign_string, &TGColor, (int*)0}, /* title text */
{"TexturedHandle", SetTextureFlag, (char **)TexturedHandle, (int *)0},
{"TitlebarNoPush", SetTextureFlag, (char **)TitlebarNoPush, (int *)0},
{"GradientText", SetTextureFlag, (char **)GradientText, (int *)0},
{"ButtonTextureType", SetInts, (char **)&IconTexType, &dummy},
{"ButtonBgColor", assign_string, &IconBgColor, (int *)0},
{"ButtonTextureColor",assign_string, &IconTexColor, (int *)0},
{"ButtonMaxColors", SetInts, (char **)&IconMaxColors, &dummy},
{"ButtonPixmap", assign_string, &IconPixmapFile, (int *)0},
{"ButtonNoBorder", SetIconFlag, (char **)IconNoBorder, (int *)0},
#endif
{"TitleTextAlign", SetInts, (char **)&Scr.TitleTextAlign, &dummy},
{"TitleButton", SetTitleButton, (char **)1, (int *)0},
{"", 0, (char **)0, (int *)0}
};
struct config func_config[] =
{
{"Nop", set_func,(char **)F_NOP},
{"Title", set_func,(char **)F_TITLE},
{"Beep", set_func,(char **)F_BEEP},
{"Quit", set_func,(char **)F_QUIT},
{"Refresh", set_func,(char **)F_REFRESH},
{"Move", set_func,(char **)F_MOVE},
{"Iconify", set_func,(char **)F_ICONIFY},
{"Maximize", set_func,(char **)F_MAXIMIZE},
{"Shade", set_func,(char **)F_SHADE},
{"Resize", set_func,(char **)F_RESIZE},
{"RaiseLower", set_func,(char **)F_RAISELOWER},
{"Raise", set_func,(char **)F_RAISE},
{"PutOnTop", set_func,(char **)F_PUTONTOP},
{"Lower", set_func,(char **)F_LOWER},
{"Delete", set_func,(char **)F_DELETE},
{"Close", set_func,(char **)F_CLOSE},
{"Destroy", set_func,(char **)F_DESTROY},
{"PopUp", set_func,(char **)F_POPUP},
{"Function", set_func,(char **)F_FUNCTION},
{"CursorMove", set_func,(char **)F_MOVECURSOR},
{"Stick", set_func,(char **)F_STICK},
{"CirculateUp", set_func,(char **)F_CIRCULATE_UP},
{"CirculateDown",set_func,(char **)F_CIRCULATE_DOWN},
{"Wait", set_func,(char **)F_WAIT},
{"Warp", set_func,(char **)F_WARP},
{"Desk", set_func,(char **)F_DESK},
{"WindowsDesk", set_func,(char **)F_CHANGE_WINDOWS_DESK},
{"Focus", set_func,(char **)F_FOCUS},
{"Module", set_func,(char **)F_MODULE},
{"Quickie", set_func,(char **)F_QUICKIE},
{"Send_WindowList",set_func, (char **)F_SEND_WINDOW_LIST},
#ifndef NON_VIRTUAL
{"Scroll", set_func,(char **)F_SCROLL},
{"GotoPage", set_func,(char **)F_GOTO_PAGE},
{"TogglePage", set_func,(char **)F_TOGGLE_PAGE},
#endif
{"Exec", set_func,(char **)F_EXEC},
{"Restart", set_func,(char **)F_RESTART},
#ifndef NO_WINDOWLIST
{"WindowList", set_func,(char **)F_WINDOWLIST},
#endif
{"", 0,(char **)0}
};
struct charstring
{
char key;
int value;
};
/* The keys musat be in lower case! */
struct charstring win_contexts[]=
{
{'w',C_WINDOW},
{'t',C_TITLE},
{'i',C_ICON},
{'r',C_ROOT},
{'f',C_FRAME},
{'s',C_SIDEBAR},
{'1',C_L1},
{'2',C_R1},
{'3',C_L2},
{'4',C_R2},
{'5',C_L3},
{'6',C_R3},
{'7',C_L4},
{'8',C_R4},
{'9',C_L5},
{'0',C_R5},
{'a',C_WINDOW|C_TITLE|C_ICON|C_ROOT|C_FRAME|C_SIDEBAR|
C_L1|C_L2|C_L3|C_L4|C_L5|C_R1|C_R2|C_R3|C_R4|C_R5},
{0,0}
};
/* The keys musat be in lower case! */
struct charstring key_modifiers[]=
{
{'s',ShiftMask},
{'c',ControlMask},
{'m',Mod1Mask},
{'1',Mod1Mask},
{'2',Mod2Mask},
{'3',Mod3Mask},
{'4',Mod4Mask},
{'5',Mod5Mask},
{'a',AnyModifier},
{'n',0},
{0,0}
};
void find_context(char *, int *, struct charstring *);
char *orig_tline;
FILE *config_fd = (FILE *)0;
/* we'll let modules get the afterstep_file that configuration was based on
* for consistency */
char *afterstep_file;
#ifdef M4
static char *m4_defs(Display*, const char*, char*, char*);
#endif
/***************************************************************
*
* Read a XPM file
*
**************************************************************/
Pixmap GetXPMTile(char *file)
{
XWindowAttributes root_attr;
XpmAttributes xpm_attributes;
extern char *PixmapPath;
char *path = NULL;
Pixmap pix, mask;
#ifdef XPM
path = findIconFile(file, PixmapPath,R_OK);
if(path == NULL)return None;
XGetWindowAttributes(dpy,Scr.Root,&root_attr);
xpm_attributes.colormap = root_attr.colormap;
xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
xpm_attributes.valuemask = XpmReturnPixels | XpmColormap | XpmCloseness;
if (XpmReadFileToPixmap(dpy, Scr.Root, path,
&pix, &mask,
&xpm_attributes) != XpmSuccess ) {
free(path);
return None;
}
free(path);
if (mask!=None)
XFreePixmap(dpy,mask);
#else
pix = None;
#endif
return pix;
}
/*****************************************************************************
*
* This routine is responsible for reading and parsing the config file
*
****************************************************************************/
void MakeMenus(const char *display_name, char *m4_options)
{
char *system_file;
char *home_file;
char line[256],*tline;
char *Home; /* the HOME environment variable */
int HomeLen; /* length of Home */
#ifdef I18N
char *Lang;
#endif
#ifdef ENABLE_TEXTURE
int icol, mcol, ucol, tcol, scol; /* texture colors */
int defcol;
#endif
#ifdef M4
extern int m4_enable;
#endif
XORvalue = (((unsigned long) 1) << Scr.d_depth) - 1;
Menuback = white;
Menufore = black;
Menustipple = grey;
Stdback = white;
Stdfore = black;
Stickyback = NULL;
Stickyfore = NULL;
Hiback = white;
Hifore = black;
#ifndef NO_PAGER
Pagerback = white;
Pagerfore = black;
#endif
/* initialize some lists */
Scr.MouseButtonRoot = NULL;
Scr.FuncKeyRoot.next = NULL;
Scr.TheList = NULL;
Scr.DefaultIcon = NULL;
/* find the home directory to look in */
Home = getenv("HOME");
if (Home == NULL)
Home = "./";
HomeLen = strlen(Home);
if(config_file[0] == '/')
{
home_file = safemalloc(strlen(config_file)+1);
strcpy(home_file,config_file);
}
else if(strncmp(config_file,"~/",2)==0)
{
home_file = safemalloc(HomeLen + strlen(&config_file[2])+3);
strcpy(home_file,Home);
strcat(home_file,"/");
strcat(home_file,&config_file[2]);
}
else
{
#ifdef I18N
if ((Lang = setlocale(LC_CTYPE, NULL)) != NULL) {
home_file = safemalloc(HomeLen+strlen(Lang)+strlen(config_file)+4);
strcpy(home_file,Home);
strcat(home_file,"/");
strcat(home_file,Lang);
strcat(home_file,"/");
strcat(home_file,config_file);
config_fd = fopen(home_file,"r");
if (config_fd == (FILE *)NULL) {
free(home_file);
home_file = safemalloc(HomeLen+strlen(config_file)+3);
strcpy(home_file,Home);
strcat(home_file,"/");
strcat(home_file,config_file);
}
else
fclose(config_fd);
}
else {
home_file = safemalloc(HomeLen+strlen(config_file)+3);
strcpy(home_file,Home);
strcat(home_file,"/");
strcat(home_file,config_file);
}
#else
home_file = safemalloc(HomeLen+strlen(config_file)+3);
strcpy(home_file,Home);
strcat(home_file,"/");
strcat(home_file,config_file);
#endif
}
afterstep_file = home_file;
config_fd = fopen(home_file,"r");
#ifdef I18N
if (config_fd == (FILE *)NULL && Lang != NULL) {
system_file = safemalloc(strlen(STEPRC) + strlen(Lang) + 2);
sprintf(system_file, "%s.%s", STEPRC, Lang);
afterstep_file = system_file;
config_fd = fopen(system_file,"r");
}
#endif
if(config_fd == (FILE *)NULL)
{
#ifdef I18N
free(system_file);
#endif
system_file = STEPRC;
afterstep_file = system_file;
config_fd = fopen(system_file,"r");
}
if(config_fd == (FILE *)NULL)
{
afterstep_err("can't open %s or %s",system_file,home_file,NULL);
exit(1);
}
if(afterstep_file != home_file)
free(home_file);
#ifdef M4
if (m4_enable)
{
/*
* Process the config file through m4 and save the
* results in a temp file.
*/
afterstep_file = m4_defs(dpy, display_name, m4_options, afterstep_file);
fclose(config_fd);
config_fd = fopen(afterstep_file, "r");
if (config_fd == (FILE *) 0)
{
perror("Cannot open m4-processed config file\n");
exit(1);
}
}
#endif /* M4 */
tline = fgets(line,(sizeof line)-1,config_fd);
orig_tline = tline;
while(tline != (char *)0)
{
while(isspace((unsigned char)*tline))tline++;
if((strlen(&tline[0])>1)&&(tline[0]!='#')&&(tline[0]!='*'))
match_string(main_config,tline,"error in config:",config_fd);
tline = fgets(line,(sizeof line)-1,config_fd);
orig_tline = tline;
}
fclose(config_fd);
config_fd = (FILE *)NULL;
#ifdef ENABLE_TEXTURE
if (!TexTypes) {
Textures.Ttype = 0;
Textures.Itype = 0;
Textures.Utype = 0;
Textures.Mtype = 0;
Textures.Stype = 0;
} else {
scol=tcol=ucol=mcol=icol=-1;
sscanf(TexTypes, "%i %i %i %i %i",&tcol, &ucol, &scol, &mcol,&icol);
Textures.Ttype = (tcol >= 0 ? tcol : 0);
Textures.Itype = (icol >= 0 ? icol : 0);
Textures.Utype = (ucol >= 0 ? ucol : 0);
Textures.Mtype = (mcol >= 0 ? mcol : 0);
Textures.Stype = (scol >= 0 ? scol : 0);
}
if (Scr.d_depth > 8) {
defcol = 32;
} else {
defcol = 10;
}
if (!TexMaxcols) {
Textures.Tmaxcols = defcol;
Textures.Imaxcols = defcol;
Textures.Mmaxcols = defcol;
Textures.Umaxcols = defcol;
Textures.Smaxcols = defcol;
} else {
scol=tcol=ucol=mcol=icol=-1;
sscanf(TexMaxcols, "%i %i %i %i %i",&tcol, &ucol, &scol, &mcol, &icol);
Textures.Tmaxcols = (tcol >= 0 ? tcol : defcol);
Textures.Imaxcols = (icol >= 0 ? icol : defcol);
Textures.Umaxcols = (ucol >= 0 ? ucol : defcol);
Textures.Mmaxcols = (mcol >= 0 ? mcol : defcol);
Textures.Smaxcols = (scol >= 0 ? scol : defcol);
}
InitTextureData(&Textures, TColor, UColor, MColor, IColor, SColor,
TGColor);
/* load titlebar pixmaps */
if (Textures.Ttype==TEXTURE_PIXMAP) {
if (TPixmap==NULL)
Textures.Ttype=0;
else {
if ((Scr.ForeTitle=GetXPMTile(TPixmap))==None) {
printf("couldn't load Titlebar tile pixmap\n");
Textures.Ttype = 0;
}
}
}
if (Textures.Utype==TEXTURE_PIXMAP) {
if (UPixmap==NULL)
Textures.Utype=0;
else {
if ((Scr.BackTitle=GetXPMTile(UPixmap))==None) {
printf("couldn't load unfocused Titlebar tile pixmap\n");
Textures.Utype = 0;
}
}
}
if (Textures.Stype==TEXTURE_PIXMAP) {
if (SPixmap==NULL)
Textures.Stype=0;
else {
if ((Scr.StickyTitle=GetXPMTile(SPixmap))==None) {
printf("couldn't load sticky Titlebar tile pixmap\n");
Textures.Stype = 0;
}
}
}
/* cache textures for ideal cases (types 2 and 3) */
if (Textures.Ttype==2 || Textures.Ttype==3) {
Scr.ForeTitle = XCreatePixmap(dpy, Scr.Root, Scr.MyDisplayWidth-1,
NS_TITLE_HEIGHT, Scr.d_depth);
if (Scr.ForeTitle!=None) {
if (!DrawHGradient(dpy, Scr.ForeTitle, 0, 0,
Scr.MyDisplayWidth-1, NS_TITLE_HEIGHT,
Textures.Tfrom, Textures.Tto, 1,
Textures.Tmaxcols, Textures.Ttype-2)) {
XFreePixmap(dpy, Scr.ForeTitle);
Scr.ForeTitle = None;
Textures.Ttype = 0;
}
} else {
Textures.Ttype = 0;
}
}
if (Textures.Ttype!=0) {
unsigned long light, dark;
XGCValues gcv;
if (MakeShadowColors(dpy, Textures.Tfrom, Textures.Tto,
&dark, &light)) {
gcv.foreground=light;
Scr.BevelReliefGC = XCreateGC(dpy, Scr.Root, GCForeground, &gcv);
gcv.foreground=dark;
Scr.BevelShadowGC = XCreateGC(dpy, Scr.Root, GCForeground, &gcv);
} else {
Scr.BevelReliefGC = Scr.BevelShadowGC = None;
}
} else {
Scr.BevelReliefGC = Scr.BevelShadowGC = None;
}
if (Textures.flags & GradientText) {
Scr.TitleGradient=XCreatePixmap(dpy,Scr.Root,Scr.MyDisplayWidth-1,
Scr.WindowFont.height, Scr.d_depth);
if (!DrawHGradient(dpy, Scr.TitleGradient, 0, 0,
Scr.MyDisplayWidth-1, Scr.WindowFont.height,
Textures.TGfrom, Textures.TGto, 0, 6, 0)) {
XFreePixmap(dpy,Scr.TitleGradient);
Scr.TitleGradient=None;
Textures.flags &= ~GradientText;
}
}
if (Textures.Utype==2 || Textures.Utype==3) {
Scr.BackTitle = XCreatePixmap(dpy, Scr.Root, Scr.MyDisplayWidth-1,
NS_TITLE_HEIGHT, Scr.d_depth);
if (Scr.BackTitle!=None) {
if (!DrawHGradient(dpy, Scr.BackTitle, 0, 0,
Scr.MyDisplayWidth-1, NS_TITLE_HEIGHT,
Textures.Ufrom, Textures.Uto, 1,
Textures.Umaxcols, Textures.Utype-2)) {
XFreePixmap(dpy, Scr.BackTitle);
Scr.BackTitle = None;
Textures.Utype = 0;
}
} else
Textures.Utype = 0;
}
if (Textures.Stype==2 || Textures.Stype==3) {
Scr.StickyTitle = XCreatePixmap(dpy, Scr.Root, Scr.MyDisplayWidth-1,
NS_TITLE_HEIGHT, Scr.d_depth);
if (Scr.StickyTitle!=None) {
if (!DrawHGradient(dpy, Scr.StickyTitle, 0, 0,
Scr.MyDisplayWidth-1, NS_TITLE_HEIGHT,
Textures.Sfrom, Textures.Sto, 1,
Textures.Smaxcols, Textures.Stype-2)) {
XFreePixmap(dpy, Scr.StickyTitle);
Scr.StickyTitle = None;
Textures.Stype=0;
}
} else
Textures.Stype=0;
}
#endif /* ENABLE_TEXTURE */
/* create pixmaps for buttons */
ButtonStyle();
/* If no edge scroll line is provided in the setup file, use
* a default */
if(Scr.EdgeScrollX == -100000)
Scr.EdgeScrollX = 25;
if(Scr.EdgeScrollY == -100000)
Scr.EdgeScrollY = Scr.EdgeScrollX;
/* if edgescroll >1000 and < 100000m
* wrap at edges of desktop (a "spherical" desktop) */
if (Scr.EdgeScrollX >= 1000)
{
Scr.EdgeScrollX /= 1000;
Scr.flags |= EdgeWrapX;
}
if (Scr.EdgeScrollY >= 1000)
{
Scr.EdgeScrollY /= 1000;
Scr.flags |= EdgeWrapY;
}
Scr.EdgeScrollX=Scr.EdgeScrollX*Scr.MyDisplayWidth/100;
Scr.EdgeScrollY=Scr.EdgeScrollY*Scr.MyDisplayHeight/100;
Scr.VxMax = Scr.VxMax*Scr.MyDisplayWidth - Scr.MyDisplayWidth;
Scr.VyMax = Scr.VyMax*Scr.MyDisplayHeight - Scr.MyDisplayHeight;
if(Scr.VxMax <0)
Scr.VxMax = 0;
if(Scr.VyMax <0)
Scr.VyMax = 0;
if (Scr.VxMax == 0)
Scr.flags &= ~EdgeWrapX;
if (Scr.VyMax == 0)
Scr.flags &= ~EdgeWrapY;
GetColors();
/* create pixmap for icon button background */
IconStyle();
#ifndef NO_PAGER
if(pager_x < 10000)initialize_pager(pager_x,pager_y);
#endif
if ((Scr.flags & ClickToRaise) && (Scr.AutoRaiseDelay == 0))
Scr.AutoRaiseDelay = -1;
return;
}
/*****************************************************************************
*
* Copies a text string from the config file to a specified location
*
****************************************************************************/
void assign_string(char *text, FILE *fd, char **arg, int *junk)
{
*arg = stripcpy(text);
}
/*****************************************************************************
*
* read the button pixmaps
*
****************************************************************************/
void ButtonStyle()
{
XWindowAttributes root_attr;
XpmAttributes xpm_attributes;
Pixmap mask;
XGetWindowAttributes(dpy, Scr.Root, &root_attr);
xpm_attributes.colormap = root_attr.colormap;
xpm_attributes.closeness = 4000;
xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|XpmCloseness;
if (!Scr.button_pixmap[2]) {
if( XpmCreatePixmapFromData(dpy, Scr.Root, closebutton_xpm,
&Scr.button_pixmap[2], &mask,
&xpm_attributes) != XpmSuccess ) {
afterstep_err("Can not read closebutton_xpm to buttonstyles",NULL, NULL, NULL);
return;
}
Scr.button_width[2] = xpm_attributes.width;
Scr.button_height[2] = xpm_attributes.height;
Scr.button_style[2] = XPM_BUTTON_STYLE;
if (mask!=None)
XFreePixmap(dpy,mask);
}
if (!Scr.button_pixmap[1]) {
if ( XpmCreatePixmapFromData(dpy, Scr.Root, minbutton_xpm,
&Scr.button_pixmap[1], &mask,
&xpm_attributes) != XpmSuccess ) {
afterstep_err("Can not read minbutton_xpm to buttonstyles",NULL, NULL, NULL);
return;
}
Scr.button_width[1] = xpm_attributes.width;
Scr.button_height[1] = xpm_attributes.height;
Scr.button_style[1] = XPM_BUTTON_STYLE;
if (mask!=None)
XFreePixmap(dpy,mask);
}
}
/****************************************************************************
*
* Read Titlebar pixmap button
*
****************************************************************************/
void SetTitleButton(char *tline,FILE *fd, char **junk,int *junk2)
{
#ifdef XPM
XWindowAttributes root_attr;
XpmAttributes xpm_attributes;
extern char *PixmapPath;
char *path = NULL;
Pixmap mask;
int num;
char file[256];
int n;
n = sscanf(tline,"%d %s",&num,file);
if (n != 2) {
printf("wrong number of parameters given with TitleButton\n");
}
if (num < 0 || num > 9) {
printf("invalid Titlebar button number: %d\n", num);
}
path = findIconFile(file,PixmapPath,R_OK);
if(path == NULL) {
printf("couldn't find Titlebar button %s\n", file);
return;
}
XGetWindowAttributes(dpy,Scr.Root,&root_attr);
xpm_attributes.colormap = root_attr.colormap;
xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|XpmCloseness;
if (XpmReadFileToPixmap(dpy, Scr.Root, path,
&Scr.button_pixmap[num], &mask,
&xpm_attributes) != XpmSuccess ) {
printf("couldn't read Titlebar button pixmap %s\n", path);
free(path);
return;
}
Scr.button_width[num] = xpm_attributes.width;
Scr.button_height[num] = xpm_attributes.height;
Scr.button_style[num] = XPM_BUTTON_STYLE;
free(path);
if (mask!=None)
XFreePixmap(dpy,mask);
#endif /* XPM */
}
/****************************************************************************
*
* Use builtin pixmap for iconized window background (aka Buttons)
*
****************************************************************************/
static void SetBuiltInIconBg()
{
#ifdef XPM
XWindowAttributes root_attr;
XpmAttributes xpm_attributes;
XGetWindowAttributes(dpy,Scr.Root,&root_attr);
xpm_attributes.colormap = root_attr.colormap;
xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
if(XpmCreatePixmapFromData(dpy, Scr.Root, button_xpm,
&Scr.IconBgPixmap, &Scr.IconBgMask,
&xpm_attributes) == XpmSuccess ) {
Scr.IconBgWidth = xpm_attributes.width;
Scr.IconBgHeight = xpm_attributes.height;
Scr.IconBgDepth = Scr.d_depth;
} else {
afterstep_err("couldn't create background icon pixmap.",NULL, NULL, NULL);
exit(1);
}
#endif /* XPM */
}
/****************************************************************************
*
* Giv'em that raised look ... the eazy way :-)
*
****************************************************************************/
static void DrawOutline(Drawable d, int w, int h)
{
if (IconTexFlags & IconNoBorder)
return;
/* top */
XDrawLine( dpy, d, Scr.NormalGC, 0, 0, w-1, 0);
XDrawLine( dpy, d, Scr.StdReliefGC, 0, 1, w-1, 1);
/* bottom */
XFillRectangle(dpy, d, Scr.StdShadowGC, 0,h-2,w-1,h-1);
/* left */
XDrawLine( dpy, d, Scr.NormalGC, 0, 1, 0, h-1);
XDrawLine( dpy, d, Scr.StdReliefGC, 1, 2, 1, h-2);
/* right */
XDrawLine( dpy, d, Scr.StdShadowGC, w-1, 1, w-1, h-1);
XDrawLine( dpy, d, Scr.StdShadowGC, w-2, 2, w-2, h-2);
}
/***************************************************************
*
* Read a XPM Icon Background from file
*
**************************************************************/
static int GetXPMIconFile(char *file)
{
#ifdef XPM
XWindowAttributes root_attr;
XpmAttributes xpm_attributes;
extern char *PixmapPath;
char *path = NULL;
path = findIconFile(file, PixmapPath,R_OK);
if(path == NULL) return False;
XGetWindowAttributes(dpy,Scr.Root,&root_attr);
xpm_attributes.colormap = root_attr.colormap;
xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
if (XpmReadFileToPixmap(dpy, Scr.Root, path,
&Scr.IconBgPixmap, &Scr.IconBgMask,
&xpm_attributes) != XpmSuccess ) {
free(path);
return False;
}
free(path);
Scr.IconBgWidth = xpm_attributes.width;
Scr.IconBgHeight = xpm_attributes.height;
Scr.IconBgDepth = Scr.d_depth;
DrawOutline(Scr.IconBgPixmap,Scr.IconBgWidth,Scr.IconBgHeight);
return True;
#else
return False;
#endif
}
/*******************************************************************
*
* Make a gradient pixmap for iconized windows background (aka Buttons)
*
*******************************************************************/
static int GetXPMGradient(int from[3], int to[3], int maxcols, int type)
{
Scr.IconBgPixmap = XCreatePixmap(dpy,Scr.Root,64,64,Scr.d_depth);
Scr.IconBgMask = None;
Scr.IconBgWidth = 64;
Scr.IconBgHeight = 64;
Scr.IconBgDepth = Scr.d_depth;
switch (type) {
case TEXTURE_GRADIENT:
if (!DrawDegradeRelief(dpy, Scr.IconBgPixmap, 0,0,64,64,
from, to, 0, maxcols)) {
XFreePixmap(dpy, Scr.IconBgPixmap);
return 0;
}
break;
case TEXTURE_HGRADIENT:
case TEXTURE_HCGRADIENT:
if (!DrawHGradient(dpy, Scr.IconBgPixmap, 0, 0, 64,64,
from, to, 0, maxcols, type-TEXTURE_HGRADIENT)) {
XFreePixmap(dpy, Scr.IconBgPixmap);
return 0;
}
break;
case TEXTURE_VGRADIENT:
case TEXTURE_VCGRADIENT:
if (!DrawVGradient(dpy, Scr.IconBgPixmap, 0, 0, 64,64,
from, to, 0, maxcols, type-TEXTURE_VGRADIENT)) {
XFreePixmap(dpy, Scr.IconBgPixmap);
return 0;
}
break;
default:
return 0;
}
DrawOutline(Scr.IconBgPixmap,64,64);
return 1;
}
/*******************************************************************
*
* Make a solid color pixmap for iconized windows background (aka Buttons)
*
*******************************************************************/
static int GetSolidXPM(Pixel pixel)
{
GC gc;
XGCValues gcv;
gcv.foreground = pixel;
gc = XCreateGC(dpy,Scr.Root,GCForeground, &gcv);
Scr.IconBgPixmap = XCreatePixmap(dpy,Scr.Root,64,64, Scr.d_depth);
Scr.IconBgMask = None;
Scr.IconBgWidth = 64;
Scr.IconBgHeight = 64;
Scr.IconBgDepth = Scr.d_depth;
XFillRectangle(dpy,Scr.IconBgPixmap,gc,0,0,64,64);
XFreeGC(dpy,gc);
DrawOutline(Scr.IconBgPixmap,64,64);
return 1;
}
/*****************************************************************************
*
* Create pixmap for icon background
*
****************************************************************************/
void IconStyle()
{
#ifdef ENABLE_TEXTURE
int FromColor[3] = {0x4000,0x4000,0x4000};
int ToColor[3] = {0x8000,0x8000,0x8000};
Pixel BgColor;
#endif /* ENABLE_TEXTURE */
#ifdef XPM
/* Free resources if this is a restart */
if (Scr.IconBgPixmap != None)
XFreePixmap(dpy,Scr.IconBgPixmap);
if (Scr.IconBgMask != None)
XFreePixmap(dpy,Scr.IconBgMask);
#endif /* XPM */
#ifdef ENABLE_TEXTURE
switch (IconTexType) {
case TEXTURE_PIXMAP:
if (IconPixmapFile == NULL) {
fprintf(stderr,"No Icon background pixmap defined. Using default.\n");
SetBuiltInIconBg();
} else if (!GetXPMIconFile(IconPixmapFile)){
fprintf(stderr,"Unable to load %s. Using default.\n", IconPixmapFile);
SetBuiltInIconBg();
}
break;
case TEXTURE_GRADIENT:
case TEXTURE_HGRADIENT:
case TEXTURE_HCGRADIENT:
case TEXTURE_VGRADIENT:
case TEXTURE_VCGRADIENT:
if (IconTexColor) {
if (!ParseColor(IconTexColor, FromColor, ToColor)) {
afterstep_err("Invalid ButtonTextureColor %s\n",IconTexColor,NULL,NULL);
}
}
if (!GetXPMGradient(FromColor, ToColor, IconMaxColors, IconTexType)) {
afterstep_err("couldn't create Textured Button. Using default.\n",NULL,NULL,NULL);
SetBuiltInIconBg();
}
break;
case TEXTURE_SOLID:
if (IconBgColor) {
BgColor=GetColor(IconBgColor);
} else {
BgColor=GetColor("grey");
}
if (!GetSolidXPM(BgColor)) {
afterstep_err("couldn't create Solid Button. Using default.\n",NULL,NULL,NULL);
SetBuiltInIconBg();
}
break;
case TEXTURE_BUILTIN:
default:
SetBuiltInIconBg();
}
#else /* ENABLE_TEXTURE */
SetBuiltInIconBg();
#endif /* ENABLE_TEXTURE */
/* if the the user want icon titles, draw the titlebar into the
* pixmap, so that there's less flickering */
if (Scr.flags & IconTitle) {
XSetForeground(dpy, Scr.IconGC, Scr.HiColors.back);
XFillRectangle(dpy, Scr.IconBgPixmap, Scr.IconGC, 1, 1,
Scr.IconBgWidth-2,Scr.IconFont.height+2);
}
}
/*****************************************************************************
*
* Changes a cursor def.
*
****************************************************************************/
void SetCursor(char *text, FILE *fd, char **arg,int *junk)
{
int num,cursor_num,cursor_style;
num = sscanf(text,"%d %d",&cursor_num, &cursor_style);
if((num != 2)||(cursor_num >= MAX_CURSORS)||(cursor_num<0))
{
afterstep_err("Bad cursor in line %s",orig_tline,NULL,NULL);
return;
}
Scr.ASCursors[cursor_num] = XCreateFontCursor(dpy,cursor_style);
}
/*****************************************************************************
*
* Sets a boolean flag to true
*
****************************************************************************/
/* void SetFlag(char *text, FILE *fd, char **arg,int *junk) */
void SetFlag(char *text, FILE *fd, char **arg, int *another)
{
Scr.flags |= (unsigned long)arg;
if (another) {
long i = strtol(text, NULL, 0);
if (i)
Scr.flags |= (unsigned long) another;
}
}
void SetTextureFlag(char *text, FILE *fd, char **arg,int *junk)
{
Textures.flags |= (unsigned long)arg;
}
void SetIconFlag(char *text, FILE *fd, char **arg,int *junk)
{
IconTexFlags |= (unsigned long)arg;
}
/*****************************************************************************
*
* Reads in one or two integer values
*
****************************************************************************/
void SetInts(char *text, FILE *fd, char **arg1, int *arg2)
{
sscanf(text,"%d%*c%d",(int *)arg1,(int *)arg2);
}
/*****************************************************************************
*
* Reads in a list of mouse button numbers
*
****************************************************************************/
void SetButtonList(char *text, FILE* fd, char **arg1, int *arg2)
{
int i, b;
char* next;
for (i = 0; i < MAX_BUTTONS; i++)
{
b = (int)strtol(text, &next, 0);
if(next == text) break;
text = next;
if (*text == ',') text++;
if((b > 0) && (b <= MAX_BUTTONS))
Scr.RaiseButtons |= 1<<b;
}
Scr.flags |= ClickToRaise;
}
/*****************************************************************************
*
* Reads Dimensions for an icon box from the config file
*
****************************************************************************/
void SetBox(char *text, FILE *fd, char **arg,int *junk)
{
int num;
if(Scr.NumBoxes < MAX_BOXES)
{
/* Standard X11 geometry string */
num = sscanf(text,"%d%d%d%d",&Scr.IconBoxes[Scr.NumBoxes][0],
&Scr.IconBoxes[Scr.NumBoxes][1],
&Scr.IconBoxes[Scr.NumBoxes][2],
&Scr.IconBoxes[Scr.NumBoxes][3]);
/* check for negative locations */
if(Scr.IconBoxes[Scr.NumBoxes][0] < 0)
Scr.IconBoxes[Scr.NumBoxes][0] += Scr.MyDisplayWidth;
if(Scr.IconBoxes[Scr.NumBoxes][1] < 0)
Scr.IconBoxes[Scr.NumBoxes][1] += Scr.MyDisplayHeight;
if(Scr.IconBoxes[Scr.NumBoxes][2] < 0)
Scr.IconBoxes[Scr.NumBoxes][2] += Scr.MyDisplayWidth;
if(Scr.IconBoxes[Scr.NumBoxes][3] < 0)
Scr.IconBoxes[Scr.NumBoxes][3] += Scr.MyDisplayHeight;
if(num == 4)
Scr.NumBoxes++;
}
}
/****************************************************************************
*
* This routine computes the shadow color from the background color
*
****************************************************************************/
Pixel GetShadow(Pixel background)
{
XColor bg_color;
XWindowAttributes attributes;
unsigned int r,g,b;
XGetWindowAttributes(dpy,Scr.Root,&attributes);
bg_color.pixel = background;
XQueryColor(dpy,attributes.colormap,&bg_color);
r = bg_color.red % 0xffff;
g = bg_color.green % 0xffff;
b = bg_color.blue % 0xffff;
r = r >>1;
g = g >>1;
b = b >>1;
/* pure black: use gray */
if( r==0 && g== 0 && b==0)
r = g = b = 0x7fff;
bg_color.red = r;
bg_color.green = g;
bg_color.blue = b;
if(!XAllocColor(dpy,attributes.colormap,&bg_color))
{
nocolor("alloc shadow","");
bg_color.pixel = background;
}
return bg_color.pixel;
}
/****************************************************************************
*
* This routine computes the hilight color from the background color
*
****************************************************************************/
Pixel GetHilite(Pixel background)
{
XColor bg_color, white_p;
XWindowAttributes attributes;
XGetWindowAttributes(dpy,Scr.Root,&attributes);
bg_color.pixel = background;
XQueryColor(dpy,attributes.colormap,&bg_color);
white_p.pixel = GetColor(white);
XQueryColor(dpy,attributes.colormap,&white_p);
#ifndef min
#define min(a,b) (((a)<(b)) ? (a) : (b))
#define max(a,b) (((a)>(b)) ? (a) : (b))
#endif
/* pure black: use gray */
if( bg_color.red==0 && bg_color.green== 0 && bg_color.blue==0)
bg_color.red = bg_color.green = bg_color.blue = 0xbfff;
else {
bg_color.red = max((white_p.red/5), bg_color.red);
bg_color.green = max((white_p.green/5), bg_color.green);
bg_color.blue = max((white_p.blue/5), bg_color.blue);
bg_color.red = min(white_p.red, (bg_color.red*140)/100);
bg_color.green = min(white_p.green, (bg_color.green*140)/100);
bg_color.blue = min(white_p.blue, (bg_color.blue*140)/100);
}
#undef min
#ifdef max
#undef max
#endif
if(!XAllocColor(dpy,attributes.colormap,&bg_color))
{
nocolor("alloc hilight","");
bg_color.pixel = background;
}
return bg_color.pixel;
}
/****************************************************************************
*
* This routine loads all needed colors, and fonts,
* and creates the GC's
*
***************************************************************************/
#ifndef NO_PAGER
Pixel PagerBackColor;
Pixel PagerForeColor;
#endif
void GetColors(void)
{
#ifdef I18N
XFontSetExtents *fset_extents;
XFontStruct **fs_list;
char **ml;
int mc;
char *ds;
char *fn_tmp;
int fn_tmp_length;
#endif
extern MyFont *IconFont;
if(have_the_colors) return;
if(Stickyback == NULL)
Stickyback = Stdback;
if(Stickyfore == NULL)
Stickyfore = Stdfore;
have_the_colors = 1;
/* setup default colors */
if(Scr.d_depth < 2)
{
/* black and white - override user choices */
Scr.MenuColors.back = GetColor(white);
Scr.MenuColors.fore = GetColor(black);
Scr.MenuStippleColors.back = GetColor(white);
Scr.MenuStippleColors.fore = GetColor(black);
Scr.MenuRelief.back = GetColor(black);
Scr.MenuRelief.fore = GetColor(white);
Scr.StdColors.back = GetColor(white);
Scr.StdColors.fore = GetColor(black);
Scr.StickyColors.back = GetColor(white);
Scr.StickyColors.fore = GetColor(black);
Scr.HiColors.back = GetColor(white);
Scr.HiColors.fore = GetColor(black);
Scr.StdRelief.back = GetColor(black);
Scr.StdRelief.fore = GetColor(white);
Scr.StickyRelief.back = GetColor(black);
Scr.StickyRelief.fore = GetColor(white);
Scr.HiRelief.back = GetColor(black);
Scr.HiRelief.fore = GetColor(white);
#ifndef NO_PAGER
PagerBackColor = GetColor(white);
PagerForeColor = GetColor(black);
#endif
}
else
{
/* color - accept user choices */
Scr.MenuColors.back = GetColor(Menuback);
Scr.MenuColors.fore = GetColor(Menufore);
Scr.MenuStippleColors.back = GetColor(Menuback);
Scr.MenuStippleColors.fore = GetColor(Menustipple);
Scr.MenuRelief.back = GetShadow(Scr.MenuColors.back);
Scr.MenuRelief.fore = GetHilite(Scr.MenuColors.back);
Scr.StdColors.back = GetColor(Stdback);
Scr.StdColors.fore = GetColor(Stdfore);
Scr.StickyColors.back = GetColor(Stickyback);
Scr.StickyColors.fore = GetColor(Stickyfore);
Scr.HiColors.back = GetColor(Hiback);
Scr.HiColors.fore = GetColor(Hifore);
Scr.StdRelief.back = GetShadow(Scr.StdColors.back);
Scr.StdRelief.fore = GetHilite(Scr.StdColors.back);
Scr.StickyRelief.back = GetShadow(Scr.StickyColors.back);
Scr.StickyRelief.fore = GetHilite(Scr.StickyColors.back);
Scr.HiRelief.back = GetShadow(Scr.HiColors.back);
Scr.HiRelief.fore = GetHilite(Scr.HiColors.back);
#ifndef NO_PAGER
PagerBackColor = GetColor(Pagerback);
PagerForeColor = GetColor(Pagerfore);
#endif
}
/* load the font */
#ifdef I18N
if ((Scr.StdFont.fontset = XCreateFontSet(dpy, Scr.StdFont.name, &ml,
&mc, &ds)) == NULL) {
nofont(Scr.StdFont.name);
fn_tmp_length = strlen(Scr.StdFont.name) + strlen(",-*--14-*");
fn_tmp = malloc(fn_tmp_length + 1);
strcpy(fn_tmp,Scr.StdFont.name);
strcat(fn_tmp,",-*--14-*");
fprintf(stderr,"Trying... %s\n",fn_tmp);
if ((Scr.StdFont.fontset = XCreateFontSet(dpy, fn_tmp,
&ml, &mc, &ds)) == NULL) {
nofont(fn_tmp);
fprintf(stderr,"Trying... fixed,-*--14-*\n");
if ((Scr.StdFont.fontset = XCreateFontSet(dpy, "fixed,-*--14-*",
&ml, &mc, &ds)) == NULL) {
fprintf(stderr,"ERROR: no fontset available\n");
exit(1);
}
}
}
XFontsOfFontSet(Scr.StdFont.fontset, &fs_list, &ml);
Scr.StdFont.font = fs_list[0];
fset_extents = XExtentsOfFontSet(Scr.StdFont.fontset);
Scr.StdFont.height = fset_extents->max_logical_extent.height;
Scr.StdFont.y = Scr.StdFont.font->ascent;
Scr.EntryHeight = Scr.StdFont.height + HEIGHT_EXTRA +2;
#else
if ((Scr.StdFont.font = XLoadQueryFont(dpy, Scr.StdFont.name)) == NULL)
{
nofont(Scr.StdFont.name);
if ((Scr.StdFont.font = XLoadQueryFont(dpy, "fixed")) == NULL)
exit(1);
}
Scr.StdFont.height = Scr.StdFont.font->ascent + Scr.StdFont.font->descent;
Scr.StdFont.y = Scr.StdFont.font->ascent;
Scr.EntryHeight = Scr.StdFont.height + HEIGHT_EXTRA +2;
#endif
/* load the window-title font */
#ifdef I18N
if ((Scr.WindowFont.fontset = XCreateFontSet(dpy, Scr.WindowFont.name, &ml,
&mc, &ds)) == NULL) {
nofont(Scr.WindowFont.name);
fn_tmp_length = strlen(Scr.WindowFont.name) + strlen(",-*--14-*");
fn_tmp = malloc(fn_tmp_length + 1);
strcpy(fn_tmp,Scr.WindowFont.name);
strcat(fn_tmp,",-*--14-*");
fprintf(stderr,"Trying... %s\n",fn_tmp);
if ((Scr.WindowFont.fontset = XCreateFontSet(dpy, fn_tmp,
&ml, &mc, &ds)) == NULL) {
nofont(fn_tmp);
fprintf(stderr,"Trying... fixed,-*--14-*\n");
if ((Scr.WindowFont.fontset = XCreateFontSet(dpy, "fixed,-*--14-*",
&ml, &mc, &ds)) == NULL) {
fprintf(stderr,"ERROR: no fontset available\n");
exit(1);
}
}
}
XFontsOfFontSet(Scr.WindowFont.fontset, &fs_list, &ml);
Scr.WindowFont.font = fs_list[0];
fset_extents = XExtentsOfFontSet(Scr.WindowFont.fontset);
Scr.WindowFont.height = fset_extents->max_logical_extent.height;
Scr.WindowFont.y = Scr.WindowFont.font->ascent;
#else
if ((Scr.WindowFont.font = XLoadQueryFont(dpy, Scr.WindowFont.name)) == NULL)
{
nofont(Scr.WindowFont.name);
if ((Scr.WindowFont.font = XLoadQueryFont(dpy, "fixed")) == NULL)
exit(1);
}
Scr.WindowFont.height=
Scr.WindowFont.font->ascent+Scr.WindowFont.font->descent;
Scr.WindowFont.y = Scr.WindowFont.font->ascent;
#endif
/* load the pager-label font */
#ifndef NO_PAGER
if(Scr.PagerFont.name != NULL)
{
#ifdef I18N
if ((Scr.PagerFont.fontset = XCreateFontSet(dpy, Scr.PagerFont.name, &ml,
&mc, &ds)) != NULL) {
XFontsOfFontSet(Scr.PagerFont.fontset, &fs_list, &ml);
Scr.PagerFont.font = fs_list[0];
fset_extents = XExtentsOfFontSet(Scr.PagerFont.fontset);
Scr.PagerFont.height = fset_extents->max_logical_extent.height;
Scr.PagerFont.y = Scr.PagerFont.font->ascent;
}
#else
if ((Scr.PagerFont.font = XLoadQueryFont(dpy, Scr.PagerFont.name))!=NULL)
{
Scr.PagerFont.height=
Scr.PagerFont.font->ascent+Scr.PagerFont.font->descent;
Scr.PagerFont.y = Scr.PagerFont.font->ascent;
}
#endif
else
nofont(Scr.PagerFont.name);
}
#endif
IconFont = &Scr.StdFont;
if(Scr.IconFont.name != NULL) {
#ifdef I18N
if ((Scr.IconFont.fontset = XCreateFontSet(dpy, Scr.IconFont.name, &ml,
&mc, &ds)) == NULL) {
nofont(Scr.IconFont.name);
fn_tmp_length = strlen(Scr.IconFont.name) + strlen(",-*--14-*");
fn_tmp = malloc(fn_tmp_length + 1);
strcpy(fn_tmp,Scr.IconFont.name);
strcat(fn_tmp,",-*--14-*");
fprintf(stderr,"Trying... %s\n",fn_tmp);
if ((Scr.IconFont.fontset = XCreateFontSet(dpy, fn_tmp,
&ml, &mc, &ds)) == NULL) {
nofont(fn_tmp);
fprintf(stderr,"Trying... fixed,-*--14-*\n");
if ((Scr.IconFont.fontset = XCreateFontSet(dpy, "fixed,-*--14-*",
&ml, &mc, &ds)) == NULL) {
fprintf(stderr,"ERROR: no fontset available\n");
exit(1);
}
}
}
XFontsOfFontSet(Scr.IconFont.fontset, &fs_list, &ml);
Scr.IconFont.font = fs_list[0];
fset_extents = XExtentsOfFontSet(Scr.IconFont.fontset);
Scr.IconFont.height = fset_extents->max_logical_extent.height;
Scr.IconFont.y = Scr.IconFont.font->ascent;
IconFont = &Scr.IconFont;
#else
if ((Scr.IconFont.font = XLoadQueryFont(dpy, Scr.IconFont.name))!=NULL) {
Scr.IconFont.height=
Scr.IconFont.font->ascent+Scr.IconFont.font->descent;
Scr.IconFont.y = Scr.IconFont.font->ascent;
IconFont = &Scr.IconFont;
} else
nofont(Scr.IconFont.name);
#endif
} else {
if ((Scr.IconFont.font = XLoadQueryFont(dpy, "fixed"))!=NULL) {
Scr.IconFont.height=
Scr.IconFont.font->ascent+Scr.IconFont.font->descent;
Scr.IconFont.y = Scr.IconFont.font->ascent;
IconFont = &Scr.IconFont;
} else {
nofont("fixed: that's bad...");
exit(1);
}
}
/* create graphics contexts */
CreateGCs();
XSync(dpy,0);
return;
}
/****************************************************************************
*
* Prints an error message for font loading
*
****************************************************************************/
void nofont(char *name)
{
afterstep_err("can't get font %s", name,NULL,NULL);
}
/****************************************************************************
*
* Processes a menu body definition
*
****************************************************************************/
MenuRoot *ParseMenuBody(char *name,FILE *fd)
{
MenuRoot *mr;
char newline[256];
register char *pline;
char unit_1,unit_2;
int n;
pline = fgets(newline,(sizeof newline)-1,fd);
orig_tline = pline;
if (pline == NULL)
return 0;
mr = NewMenuRoot(name);
GetColors();
while(isspace((unsigned char)*pline))pline++;
while((pline != (char *)0)
&&(mystrncasecmp("End",pline,3)!=0))
{
if((*pline!='#')&&(*pline != 0)&&(*pline!='*'))
{
char *ptr2 = 0;
match_string(func_config,pline, "bad menu body function:",fd);
if((func == F_EXEC)||(func == F_POPUP)||(func == F_RESTART)
||(func == F_FUNCTION)||(func == F_MODULE))
ptr2=stripcpy3(pline,True);
else
ptr2=stripcpy3(pline,False);
func_val_1 = 0;
func_val_2 = 0;
unit_1 = 's';
unit_2 = 's';
if(ptr2 != NULL)
{
n = sscanf(ptr2,"%d %d",&func_val_1,&func_val_2);
if( n < 2)
n = sscanf(ptr2,"%d%c %d%c",&func_val_1,&unit_1,&func_val_2,&unit_2);
}
if( *stripcpy2(pline,1,True))
AddToMenu(mr, stripcpy2(pline,1,True), stripcpy2(pline,2,True),
ptr2, func,func_val_1,func_val_2, unit_1, unit_2);
}
pline = fgets(newline,(sizeof newline)-1,fd);
if(pline == (char *)0)return NULL;
orig_tline = pline;
while(isspace((unsigned char)*pline))pline++;
}
MakeMenu(mr);
return mr;
}
/****************************************************************************
*
* Parses a popup definition
*
****************************************************************************/
void ParsePopupEntry(char *tline,FILE *fd, char **junk,int *junk2)
{
MenuRoot *mr=0;
mr = ParseMenuBody(stripcpy2(tline,0,True),fd);
if (PopupCount < MAXPOPUPS)
{
PopupTable[PopupCount] = mr;
PopupCount++;
if(strcmp(mr->name,"InitFunction")==0)
{
Scr.InitFunction = mr;
}
else if(strcmp(mr->name,"RestartFunction")==0)
{
Scr.RestartFunction = mr;
}
}
else
{
fprintf(stderr,"Popup/Function %s ignored, you have more than %u\n",
mr->name,MAXPOPUPS);
free(mr);
}
}
/****************************************************************************
*
* Parses a mouse binding
*
****************************************************************************/
void ParseMouseEntry(char *tline,FILE *fd, char **junk,int *junk2)
{
char context[256],modifiers[256],function[256],*ptr;
MenuRoot *mr=0;
MenuItem *mi=0;
MouseButton *temp;
int button,i,j;
int n;
char unit_1, unit_2;
unit_1 = 's';
unit_2 = 's';
func_val_1 = 0;
func_val_2 = 0;
n = sscanf(tline,"%d %s %s %s %d %d",&button,context,modifiers,function,
&func_val_1,&func_val_2);
if(n < 6)
n = sscanf(tline,"%d %s %s %s %d%c %d%c",&button,context,modifiers,function,
&func_val_1,&unit_1,&func_val_2,&unit_2);
find_context(context,&contexts,win_contexts);
if((contexts != C_ALL) && (contexts & C_LALL))
{
/* check for nr_left_buttons */
i=0;
j=(contexts &C_LALL)/C_L1;
while(j>0)
{
i++;
j=j>>1;
}
if(Scr.nr_left_buttons <i)
Scr.nr_left_buttons = i;
}
if((contexts != C_ALL) && (contexts & C_RALL))
{
/* check for nr_right_buttons */
i=0;
j=(contexts&C_RALL)/C_R1;
while(j>0)
{
i++;
j=j>>1;
}
if(Scr.nr_right_buttons <i)
Scr.nr_right_buttons = i;
}
find_context(modifiers,&mods,key_modifiers);
if((contexts & C_WINDOW)&&(((mods==0)||mods == AnyModifier)))
{
Scr.buttons2grab &= ~(1<<(button-1));
}
func = F_NOP;
match_string(func_config,function,"bad mouse function:",fd);
if((func == F_POPUP)||(func == F_FUNCTION))
{
unsigned i;
ptr = stripcpy2(tline,0,True);
if(ptr != NULL)
for (i = 0; i < PopupCount; i++)
if (mystrcasecmp(PopupTable[i]->name,ptr) == 0)
{
mr = PopupTable[i];
break;
}
if (!mr)
{
no_popup(ptr);
func = F_NOP;
}
if(ptr != NULL)
free(ptr);
}
else if((func == F_EXEC)||(func == F_RESTART)||
(func == F_CIRCULATE_UP)||(func == F_CIRCULATE_DOWN)||
(func == F_WARP)||(func == F_MODULE))
{
mi = (MenuItem *)safemalloc(sizeof(MenuItem));
mi->next = (MenuItem *)NULL;
mi->prev = (MenuItem *)NULL;
mi->item_num = 0;
if((func == F_EXEC)||(func == F_RESTART)||(func== F_MODULE))
{
mi->item = stripcpy2(tline,0,True);
mi->action = stripcpy3(tline,True);
}
else
{
mi->item = stripcpy2(tline,0,False);
mi->action = stripcpy3(tline,False);
}
mi->state = 0;
mi->func = func;
mi->strlen = strlen(mi->item);
mi->val1 = 0;
mi->val2 = 0;
mi->val1_unit = 1;
mi->val2_unit = 1;
}
temp = Scr.MouseButtonRoot;
Scr.MouseButtonRoot = (MouseButton *)safemalloc(sizeof(MouseButton));
Scr.MouseButtonRoot->func = func;
Scr.MouseButtonRoot->menu = mr;
Scr.MouseButtonRoot->item = mi;
Scr.MouseButtonRoot->Button = button;
Scr.MouseButtonRoot->Context = contexts;
Scr.MouseButtonRoot->Modifier = mods;
Scr.MouseButtonRoot->NextButton = temp;
Scr.MouseButtonRoot->val1 = func_val_1;
Scr.MouseButtonRoot->val2 = func_val_2;
if((unit_1 == 'p')||(unit_1 == 'P'))
Scr.MouseButtonRoot->val1_unit = 100;
else
Scr.MouseButtonRoot->val1_unit = Scr.MyDisplayWidth;
if((unit_2 == 'p')||(unit_2 == 'P'))
Scr.MouseButtonRoot->val2_unit = 100;
else
Scr.MouseButtonRoot->val2_unit = Scr.MyDisplayHeight;
return;
}
void no_popup(char *ptr)
{
if((ptr)&&(orig_tline))
fprintf(stderr,"Popup '%s' not defined in line %s",ptr,orig_tline);
}
/****************************************************************************
*
* Processes a line with a key binding
*
****************************************************************************/
void ParseKeyEntry(char *tline, FILE *fd,char **junk,int *junk2)
{
char context[256],modifiers[256],function[256],*ptr;
char name[256];
MenuRoot *mr = 0;
char unit_1, unit_2;
int n;
ptr = NULL;
func_val_1 = 0;
func_val_2 = 0;
unit_1 = 's';
unit_2 = 's';
n = sscanf(tline,"%s %s %s %s %d %d",name,context,modifiers,function,
&func_val_1,&func_val_2);
if(n < 6)
n = sscanf(tline,"%s %s %s %s %d%c %d%c",name,context,modifiers,function,
&func_val_1,&unit_1,&func_val_2,&unit_2);
find_context(context,&contexts,win_contexts);
find_context(modifiers,&mods,key_modifiers);
match_string(func_config,function,"bad key function:",fd);
/* Make CirculateUp and CirculateDown take args. by Y.NOMURA */
if ((func == F_CIRCULATE_UP) || (func == F_CIRCULATE_DOWN)||
(func == F_WARP))
ptr = stripcpy3(tline,False);
/* End of addition */
if((func == F_EXEC)||(func == F_RESTART)||(func == F_MODULE))
{
ptr = stripcpy3(tline,True);
}
else if((func == F_POPUP)||(func == F_FUNCTION))
{
unsigned i;
ptr = stripcpy2(tline,0,True);
if(ptr != NULL)
{
for (i = 0; i < PopupCount; i++)
if (mystrcasecmp(PopupTable[i]->name,ptr) == 0)
{
mr = PopupTable[i];
break;
}
}
if (!mr)
{
no_popup(ptr);
func = F_NOP;
}
}
AddFuncKey(name,contexts,mods,func,ptr,func_val_1,func_val_2,mr, unit_1,unit_2);
}
/****************************************************************************
*
* Sets menu/keybinding/mousebinding function to specified value
*
****************************************************************************/
void set_func(char *text, FILE *fd, char **value,int *junk)
{
func = (unsigned long)value;
}
/****************************************************************************
*
* Turns a string context of context or modifier values into an array of
* true/false values (bits)
*
****************************************************************************/
void find_context(char *string, int *output, struct charstring *table)
{
int i=0,j=0;
Bool matched;
char tmp1;
*output=0;
i=0;
while(i<strlen(string))
{
j=0;
matched = FALSE;
while((!matched)&&(table[j].key != 0))
{
/* in some BSD implementations, tolower(c) is not defined
* unless isupper(c) is true */
tmp1=string[i];
if(isupper(tmp1))
tmp1=tolower(tmp1);
/* end of ugly BSD patch */
if(tmp1 == table[j].key)
{
*output |= table[j].value;
matched = TRUE;
}
j++;
}
if(!matched)
{
fprintf(stderr,"afterstep: bad entry %c in line %s",
string[i],orig_tline);
}
i++;
}
return;
}
/****************************************************************************
*
* Matches text from config to a table of strings, calls routine
* indicated in table.
*
****************************************************************************/
void match_string(struct config *table, char *text, char *error_msg, FILE *fd)
{
int j;
Bool matched;
j=0;
matched = FALSE;
while((!matched)&&(strlen(table[j].keyword)>0))
{
if(mystrncasecmp(text,table[j].keyword,strlen(table[j].keyword))==0)
{
matched=TRUE;
/* found key word */
table[j].action(&text[strlen(table[j].keyword)],
fd,table[j].arg,table[j].arg2);
}
else
j++;
}
if(!matched)
{
afterstep_err("%s %s in line %s",error_msg,text,orig_tline);
}
}
/****************************************************************************
*
* Generates the window for a menu
*
****************************************************************************/
void MakeMenu(MenuRoot *mr)
{
MenuItem *cur;
unsigned long valuemask;
XSetWindowAttributes attributes;
int y;
/* lets first size the window accordingly */
mr->width += 15;
if(mr->width2 > 0)
mr->width += 5;
/* allow two pixels for top border */
for (y=0, cur = mr->first; cur != NULL; cur = cur->next)
{
cur->y_offset = y;
cur->x = 5;
if(cur->func==F_TITLE)
/* Title */
cur->y_height = Scr.EntryHeight;
else if(cur->func==F_NOP && *cur->item==0)
/* Separator */
cur->y_height = HEIGHT_SEPARATOR;
else
/* Normal text entry */
cur->y_height = Scr.EntryHeight;
y += cur->y_height;
if(mr->width2 == 0)
{
cur->x2 = cur->x;
}
else
{
cur->x2 = mr->width -5;
}
}
mr->in_use = 0;
mr->height = y;
#ifndef NO_SAVEUNDERS
valuemask = (CWBackPixel | CWEventMask | CWCursor | CWSaveUnder);
#else
valuemask = (CWBackPixel | CWEventMask | CWCursor);
#endif
attributes.background_pixel = Scr.MenuColors.back;
attributes.event_mask = (ExposureMask | EnterWindowMask);
attributes.cursor = Scr.ASCursors[MENU];
#ifndef NO_SAVEUNDERS
attributes.save_under = TRUE;
#endif
mr->width = mr->width + mr->width2;
mr->w = XCreateWindow (dpy, Scr.Root, 0, 0, (unsigned int) (mr->width),
(unsigned int) mr->height, (unsigned int) 0,
CopyFromParent, (unsigned int) InputOutput,
(Visual *) CopyFromParent,
valuemask, &attributes);
XSaveContext(dpy,mr->w,MenuContext,(caddr_t)mr);
return;
}
/***********************************************************************
* Procedure:
* scanForHotkeys - Look for hotkey markers in a MenuItem
* (pete@tecc.co.uk)
*
* Inputs:
* it - MenuItem to scan
* which - +1 to look in it->item1 and -1 to look in it->item2.
*
***********************************************************************/
void scanForHotkeys(MenuItem *it, int which)
{
char *start, *txt;
start = (which > 0) ? it->item : it->item2; /* Get start of string */
for (txt = start; *txt != '\0'; txt++)
{ /* Scan whole string */
if (*txt == '&')
{ /* A hotkey marker? */
if (txt[1] == '&')
{ /* Just an escaped & */
char *tmp; /* Copy the string down over it */
for (tmp = txt; *tmp != '\0'; tmp++) tmp[0] = tmp[1];
continue; /* ...And skip to the key char */
}
/* It's a hot key marker - work out the offset value */
it->hotkey = txt[1];
for (; txt[1] != '\0'; txt++)
txt[0] = txt[2]; /* Copy down.. */
return; /* Only one hotkey per item... */
}
}
it->hotkey = 0; /* No hotkey found. Set offset to zero */
}
/***********************************************************************
*
* Procedure:
* AddToMenu - add an item to a root menu
*
* Returned Value:
* (MenuItem *)
*
* Inputs:
* menu - pointer to the root menu to add the item
* item - the text to appear in the menu
* action - the string to possibly execute
* func - the numeric function
*
***********************************************************************/
void AddToMenu(MenuRoot *menu, char *item, char *item2, char *action,int func,
long func_val_1,long func_val_2, char unit_1, char unit_2)
{
MenuItem *tmp;
int width;
if(item == NULL)
return;
tmp = (MenuItem *)safemalloc(sizeof(MenuItem));
if (menu->first == NULL)
{
menu->first = tmp;
tmp->prev = NULL;
}
else
{
menu->last->next = tmp;
tmp->prev = menu->last;
}
menu->last = tmp;
tmp->item = item;
if (item != (char *)0)
{
scanForHotkeys(tmp, 1); /* pete@tecc.co.uk */
tmp->strlen = strlen(item);
}
else
tmp->strlen = 0;
tmp->item2 = item2;
if (item2 != (char *)0)
{
if (tmp->hotkey == 0) scanForHotkeys(tmp, -1); /* pete@tecc.co.uk */
tmp->strlen2 = strlen(item2);
}
else
tmp->strlen2 = 0;
tmp->menu = 0;
if((func == F_POPUP)||(func == F_FUNCTION))
{
unsigned i;
if(action != (char *)0)
{
for (i = 0; i < PopupCount; i++)
if (mystrcasecmp(PopupTable[i]->name,action) == 0)
{
tmp->menu = PopupTable[i];
break;
}
}
if(tmp->menu == (MenuRoot *)0)
{
no_popup(action);
func = F_NOP;
}
}
tmp->action = action;
tmp->next = NULL;
tmp->state = 0;
tmp->func = func;
tmp->val1 = func_val_1;
tmp->val2 = func_val_2;
if((unit_1 == 'p')||(unit_1 == 'P'))
tmp->val1_unit = 100;
else
tmp->val1_unit = Scr.MyDisplayWidth;
if((unit_2 == 'p')||(unit_2 == 'P'))
tmp->val2_unit = 100;
else
tmp->val2_unit = Scr.MyDisplayHeight;
if(func==F_TITLE)
width = XTextWidth(Scr.WindowFont.font, item, tmp->strlen);
else
width = XTextWidth(Scr.StdFont.font, item, tmp->strlen);
if(tmp->func == F_POPUP || tmp->hotkey)
width += 15;
if (width <= 0)
width = 1;
if (width > menu->width)
menu->width = width;
width = XTextWidth(Scr.StdFont.font, item2, tmp->strlen2);
if (width < 0)
width = 0;
if (width > menu->width2)
menu->width2 = width;
if((width==0)&&(tmp->strlen2>0))
menu->width2 = 1;
tmp->item_num = menu->items++;
}
/***********************************************************************
*
* Procedure:
* NewMenuRoot - create a new menu root
*
* Returned Value:
* (MenuRoot *)
*
* Inputs:
* name - the name of the menu root
*
***********************************************************************/
MenuRoot *NewMenuRoot(char *name)
{
MenuRoot *tmp;
tmp = (MenuRoot *) safemalloc(sizeof(MenuRoot));
tmp->name = name;
tmp->first = NULL;
tmp->last = NULL;
tmp->items = 0;
tmp->width = 0;
tmp->width2 = 0;
#ifdef ENABLE_TEXTURE
tmp->titlebg = None;
tmp->itembg = None;
#endif
tmp->w = None;
return (tmp);
}
/***********************************************************************
*
* Procedure:
* AddFuncKey - add a function key to the list
*
* Inputs:
* name - the name of the key
* cont - the context to look for the key press in
* mods - modifier keys that need to be pressed
* func - the function to perform
* action - the action string associated with the function (if any)
*
***********************************************************************/
void AddFuncKey (char *name, int cont, int mods, int func, char *action,
int val1, int val2,MenuRoot *mr, char unit_1, char unit_2)
{
FuncKey *tmp;
KeySym keysym;
KeyCode keycode;
int i, min, max;
/*
* Don't let a 0 keycode go through, since that means AnyKey to the
* XGrabKey call in GrabKeys().
*/
if ((keysym = XStringToKeysym(name)) == NoSymbol ||
(keycode = XKeysymToKeycode(dpy, keysym)) == 0)
return;
XDisplayKeycodes(dpy, &min, &max);
for (i=min; i<=max; i++)
if (XKeycodeToKeysym(dpy, i, 0) == keysym)
{
tmp = (FuncKey *) safemalloc(sizeof(FuncKey));
tmp->next = Scr.FuncKeyRoot.next;
Scr.FuncKeyRoot.next = tmp;
tmp->name = name;
tmp->keycode = i;
tmp->cont = cont;
tmp->mods = mods;
tmp->func = func;
tmp->action = action;
tmp->val1 = val1;
tmp->val2 = val2;
if((unit_1 == 'p')||(unit_1 == 'P'))
tmp->val1_unit = 100;
else
tmp->val1_unit = Scr.MyDisplayWidth;
if((unit_2 == 'p')||(unit_2 == 'P'))
tmp->val2_unit = 100;
else
tmp->val2_unit = Scr.MyDisplayHeight;
tmp->menu = mr;
}
return;
}
/****************************************************************************
*
* Loads a single color
*
****************************************************************************/
Pixel GetColor(char *name)
{
XColor color;
XWindowAttributes attributes;
XGetWindowAttributes(dpy,Scr.Root,&attributes);
color.pixel = 0;
if (!XParseColor (dpy, attributes.colormap, name, &color))
{
nocolor("parse",name);
}
else if(!XAllocColor (dpy, attributes.colormap, &color))
{
nocolor("alloc",name);
}
return color.pixel;
}
void nocolor(char *note, char *name)
{
afterstep_err("can't %s color %s", note,name,NULL);
}
/****************************************************************************
*
* Copies a string into a new, malloc'ed string
* Strips leading spaces and trailing spaces and new lines
*
****************************************************************************/
char *stripcpy(char *source)
{
char *tmp,*ptr;
int len;
while(isspace((unsigned char)*source))
source++;
len = strlen(source);
tmp = source + len -1;
while(((isspace(*tmp))||(*tmp == '\n'))&&(tmp >=source))
{
tmp--;
len--;
}
ptr = safemalloc(len+1);
strncpy(ptr,source,len);
ptr[len]=0;
return ptr;
}
/****************************************************************************
*
* Copies a string into a new, malloc'ed string
* Strips all data before the first quote and after the second
*
****************************************************************************/
char *stripcpy2(char *source, int tab_sensitive, Bool error)
{
char *ptr;
int count;
while((*source != '"')&&(*source != 0))
source++;
if(*source == 0)
{
if(error)
bad_binding(2);
return 0;
}
source++;
ptr = source;
count = 0;
if(!tab_sensitive)
while((*ptr!='"')&&(*ptr != 0))
{
ptr++;
count++;
}
else if(tab_sensitive==1)
while((*ptr!='"')&&(*ptr != 0)&&(*ptr!='\t'))
{
ptr++;
count++;
}
else if(tab_sensitive==2)
{
while((*ptr!='"')&&(*ptr != 0)&&(*ptr!='\t'))
{
source++;
ptr++;
}
if((*ptr!='"')&&(*ptr != 0))
{
ptr++;
source++;
}
while((*ptr!='"')&&(*ptr != 0))
{
ptr++;
count++;
}
}
ptr = safemalloc(count+1);
strncpy(ptr,source,count);
ptr[count]=0;
return ptr;
}
/****************************************************************************
*
* Copies a string into a new, malloc'ed string
* Strips all data before the second quote. and strips trailing spaces and
* new lines
*
****************************************************************************/
char *stripcpy3(char *source,Bool Warn)
{
while((*source != '"')&&(*source != 0))
source++;
if(*source != 0)
source++;
while((*source != '"')&&(*source != 0))
source++;
if(*source == 0)
{
if(Warn)bad_binding(3);
return 0;
}
source++;
return stripcpy(source);
}
void bad_binding(int num)
{
afterstep_err("bad binding in line %s",orig_tline,NULL,NULL);
return;
}
/***********************************************************************
*
* Procedure:
* CreateGCs - open fonts and create all the needed GC's. I only
* want to do this once, hence the first_time flag.
*
***********************************************************************/
void CreateGCs(void)
{
XGCValues gcv;
unsigned long gcm;
/* create GC's */
gcm = GCLineWidth|GCForeground|GCBackground|GCFunction;
gcv.function = GXcopy;
gcv.line_width = 1;
gcv.foreground = Scr.StdColors.fore;
gcv.background = Scr.StdColors.back;
Scr.LineGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcm = GCFunction|GCLineWidth|GCForeground|GCSubwindowMode;
gcv.function = GXxor;
gcv.line_width = 0;
gcv.foreground = XORvalue;
gcv.subwindow_mode = IncludeInferiors;
Scr.DrawGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcm = GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
GCBackground|GCFont;
gcv.line_width = 0;
gcv.function = GXcopy;
gcv.plane_mask = AllPlanes;
gcv.foreground = Scr.StdColors.fore;
gcv.background = Scr.StdColors.back;
gcv.font = Scr.StdFont.font->fid;
/*
* Prevent GraphicsExpose and NoExpose events. We'd only get NoExpose
* events anyway; they cause BadWindow errors from XGetWindowAttributes
* call in FindScreenInfo (events.c) (since drawable is a pixmap).
*/
gcv.graphics_exposures = False;
Scr.NormalGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
/* GC for pager labels */
Scr.FontGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.fill_style = FillStippled;
gcv.stipple = Scr.gray_bitmap;
gcm = GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
GCBackground|GCFont|GCStipple|GCFillStyle;
Scr.StippleGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcm = GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
GCBackground|GCFont;
Globalgcm = gcm;
Globalgcv = gcv;
gcv.foreground = Scr.HiRelief.fore;
gcv.background = Scr.HiRelief.back;
gcv.fill_style = FillSolid;
Scr.HiReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.HiRelief.back;
gcv.background = Scr.HiRelief.fore;
Scr.HiShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
if (Scr.BevelReliefGC==None)
Scr.BevelReliefGC=Scr.HiReliefGC;
if (Scr.BevelShadowGC==None)
Scr.BevelShadowGC=Scr.HiShadowGC;
gcv.foreground = Scr.MenuColors.fore;
gcv.background = Scr.MenuColors.back;
Scr.MenuGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.StdRelief.fore;
gcv.background = Scr.StdRelief.back;
Scr.ScratchGC1 = XCreateGC(dpy, Scr.Root, gcm, &gcv);
if(Scr.d_depth < 2)
{
gcv.fill_style = FillStippled;
gcv.stipple = Scr.gray_bitmap;
gcm=GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
GCBackground|GCFont|GCStipple|GCFillStyle;
Scr.MenuStippleGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcm=GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
GCBackground|GCFont;
gcv.fill_style = FillSolid;
}
else
{
gcv.foreground = Scr.MenuStippleColors.fore;
gcv.background = Scr.MenuStippleColors.back;
Scr.MenuStippleGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
}
gcv.foreground = Scr.MenuRelief.fore;
gcv.background = Scr.MenuRelief.back;
Scr.MenuReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.MenuRelief.back;
gcv.background = Scr.MenuRelief.fore;
Scr.MenuShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.StdRelief.fore;
gcv.background = Scr.StdRelief.back;
Scr.StdReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.StdRelief.back;
gcv.background = Scr.StdRelief.fore;
Scr.StdShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
Scr.ScratchGC2 = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.StickyRelief.fore;
gcv.background = Scr.StickyRelief.back;
Scr.StickyReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.StickyRelief.back;
gcv.background = Scr.StickyRelief.fore;
Scr.StickyShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
gcv.foreground = Scr.HiColors.fore;
gcv.font = Scr.IconFont.font->fid;
Scr.IconGC = XCreateGC(dpy, Scr.Root, GCForeground|GCFont, &gcv);
}
/***********************************************************************
*
* Procedure:
* SetOneStyle - add a window name to the no title list
*
* Inputs:
* name - a pointer to the name of the window
*
***********************************************************************/
#ifndef PRUNE
void SetOneStyle(char *text, FILE *fd, char **list, int *junk)
{
char *name;
unsigned long new_flags;
char *icon_name = NULL;
int desknumber = 0;
new_flags = (unsigned long)junk;
/* first, see if an entry for this name exists */
if((new_flags & ICON_FLAG) || (new_flags & STAYSONDESK_FLAG))
name = stripcpy2(text,FALSE,TRUE);
else
name = stripcpy(text);
/* in case there was no argument! */
if(name == NULL)
return;
/* capture default icons */
if(strlen(name) == 0)
{
if(new_flags & ICON_FLAG)
Scr.DefaultIcon = stripcpy3(text,TRUE);
free(name);
return;
}
if(new_flags & ICON_FLAG)
{
icon_name = stripcpy3(text,TRUE);
}
else if (new_flags & STAYSONDESK_FLAG)
{
char *p = stripcpy3(text,TRUE);
desknumber = atoi (p);
free (p);
}
AddToList(name,icon_name,new_flags,0,desknumber,0,0,NULL,NULL,0,0);
}
#endif
#ifdef M4
/* For m4... */
#include <X11/Xmu/CharSet.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
/* Code taken and munged from xrdb.c */
#define MAXHOSTNAME 255
#define Resolution(pixels, mm) ((((pixels) * 100000 / (mm)) + 50) / 100)
/* EXTRA should be the length of the strings
"define(" + ", ``" + "'')dnl\n". */
#define EXTRA 50
extern int m4_prefix;
extern char m4_prog[];
extern int m4_default_quotes;
extern char m4_startquote[];
extern char m4_endquote[];
static char *MkDef(char *name, char *def)
{
static char *cp = NULL;
static int maxsize = 0;
int n;
/* The char * storage only lasts for 1 call... */
/* Get space to hold everything, if needed */
n = EXTRA + strlen(name) + strlen(def);
if (n > maxsize) {
maxsize = n;
if (cp == NULL) {
cp = malloc(n);
} else {
cp = realloc(cp, n);
}
}
if (cp == NULL) {
perror("MkDef can't allocate enough space for a macro definition");
exit(0377);
}
/* Create the macro definition, using the appropriate prefix, if any */
if (m4_prefix)
{
strcpy(cp, "m4_define(");
}
else
strcpy(cp, "define(");
strcat(cp, name);
/* Tack on "," and 2 sets of starting quotes */
strcat(cp, ",");
strcat(cp, m4_startquote);
strcat(cp, m4_startquote);
/* The definition itself */
strcat(cp, def);
/* Add 2 sets of closing quotes */
strcat(cp, m4_endquote);
strcat(cp, m4_endquote);
/* End the definition, appropriately */
strcat(cp, ")");
if (m4_prefix)
{
strcat(cp, "m4_");
}
strcat(cp, "dnl\n");
return(cp);
}
static char *MkNum(char *name,int def)
{
char num[20];
sprintf(num, "%d", def);
return(MkDef(name, num));
}
static char *m4_defs(Display *display, const char *host, char *m4_options, char *config_file)
{
Screen *screen;
Visual *visual;
char client[MAXHOSTNAME], server[MAXHOSTNAME], *colon;
char ostype[BUFSIZ];
char options[BUFSIZ];
static char tmp_name[BUFSIZ];
struct hostent *hostname;
char *vc; /* Visual Class */
FILE *tmpf;
struct passwd *pwent;
/* Generate a temporary filename. Honor the TMPDIR environment variable,
if set. Hope nobody deletes this file! */
if ((vc=getenv("TMPDIR"))) {
strcpy(tmp_name, vc);
} else {
strcpy(tmp_name, "/tmp");
}
strcat(tmp_name, "/steprcXXXXX");
mktemp(tmp_name);
if (*tmp_name == '\0')
{
perror("mktemp failed in m4_defs");
exit(0377);
}
/*
* Create the appropriate command line to run m4, and
* open a pipe to the command.
*/
sprintf(options, "%s %s %s > %s\n",
m4_prog,
((m4_prefix == 0) ? "" : "--prefix-builtins"),
m4_options, tmp_name);
tmpf = popen(options, "w");
if (tmpf == NULL) {
perror("Cannot open pipe to m4");
exit(0377);
}
mygethostname(client,MAXHOSTNAME);
mygetostype (ostype, sizeof ostype);
/* Change the quoting characters, if specified */
if (!m4_default_quotes)
{
fprintf(tmpf, "changequote(%s, %s)dnl\n", m4_startquote, m4_endquote);
}
hostname = gethostbyname(client);
strcpy(server, XDisplayName(host));
colon = strchr(server, ':');
if (colon != NULL) *colon = '\0';
if ((server[0] == '\0') || (!strcmp(server, "unix")))
strcpy(server, client); /* must be connected to :0 or unix:0 */
/* TWM_TYPE is afterstep, for completeness */
fputs(MkDef("TWM_TYPE", "afterstep"), tmpf);
/* The machine running the X server */
fputs(MkDef("SERVERHOST", server), tmpf);
/* The machine running the window manager process */
fputs(MkDef("CLIENTHOST", client), tmpf);
if (hostname)
fputs(MkDef("HOSTNAME", (char *)hostname->h_name), tmpf);
else
fputs(MkDef("HOSTNAME", (char *)client), tmpf);
fputs(MkDef("OSTYPE", ostype), tmpf);
pwent=getpwuid(geteuid());
fputs(MkDef("USER", pwent->pw_name), tmpf);
fputs(MkDef("HOME", getenv("HOME")), tmpf);
fputs(MkNum("VERSION", ProtocolVersion(display)), tmpf);
fputs(MkNum("REVISION", ProtocolRevision(display)), tmpf);
fputs(MkDef("VENDOR", ServerVendor(display)), tmpf);
fputs(MkNum("RELEASE", VendorRelease(display)), tmpf);
screen = ScreenOfDisplay(display, Scr.screen);
visual = DefaultVisualOfScreen(screen);
fputs(MkNum("WIDTH", Scr.MyDisplayWidth), tmpf);
fputs(MkNum("HEIGHT", Scr.MyDisplayHeight), tmpf);
fputs(MkNum("X_RESOLUTION",Resolution(screen->width,screen->mwidth)),tmpf);
fputs(MkNum("Y_RESOLUTION",Resolution(screen->height,screen->mheight)),tmpf);
fputs(MkNum("PLANES",DisplayPlanes(display, Scr.screen)), tmpf);
fputs(MkNum("BITS_PER_RGB", visual->bits_per_rgb), tmpf);
switch(visual->class)
{
case(StaticGray):
vc = "StaticGray";
break;
case(GrayScale):
vc = "GrayScale";
break;
case(StaticColor):
vc = "StaticColor";
break;
case(PseudoColor):
vc = "PseudoColor";
break;
case(TrueColor):
vc = "TrueColor";
break;
case(DirectColor):
vc = "DirectColor";
break;
default:
vc = "NonStandard";
break;
}
fputs(MkDef("CLASS", vc), tmpf);
if (visual->class != StaticGray && visual->class != GrayScale)
fputs(MkDef("COLOR", "Yes"), tmpf);
else
fputs(MkDef("COLOR", "No"), tmpf);
fputs(MkDef("AFTER_VERSION", VERSION), tmpf);
/* Add options together */
*options = '\0';
#ifdef SHAPE
strcat(options, "SHAPE ");
#endif
#ifdef XPM
strcat(options, "XPM ");
#endif
strcat(options, "M4 ");
#ifdef NO_PAGER
strcat(options, "NO_PAGER ");
#endif
#ifdef NON_VIRTUAL
strcat(options, "NON_VIRTUAL ");
#endif
#ifdef NO_SAVEUNDERS
strcat(options, "NO_SAVEUNDERS ");
#endif
#ifdef I18N
strcat(options, "I18N ");
#endif
#ifdef NO_WINDOWLIST
strcat(options, "NO_WINDOWLIST ");
#endif
#ifdef PRUNE
strcat(options, "PRUNE ");
#endif
fputs(MkDef("OPTIONS", options), tmpf);
fputs(MkDef("AFTERDIR", AFTERDIR), tmpf);
/*
* At this point, we've sent the definitions to m4. Just include
* the steprc file now.
*/
fprintf(tmpf, "%sinclude(%s%s%s)\n",
(m4_prefix) ? "m4_": "",
m4_startquote,
config_file,
m4_endquote);
pclose(tmpf);
return(tmp_name);
}
#endif /* M4 */
syntax highlighted by Code2HTML, v. 0.9.1