parse_be.c revision b18c2d1e
1/* 2 * Parser backend routines. 3 * 4 * Roughly, these are the routines that the lex/yacc output calls to do 5 * its work. 6 * 7 * This is very similar to the meaning of parse_yacc.c; the two may be 8 * merged at some point. 9 */ 10 11#include "ctwm.h" 12 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16#include <strings.h> 17 18#include <X11/Xatom.h> 19 20#include "ctwm_atoms.h" 21#include "screen.h" 22#include "util.h" 23#include "animate.h" 24#include "functions_defs.h" 25#include "image.h" 26#include "list.h" 27#include "occupation.h" 28#include "parse.h" 29#include "parse_be.h" 30#include "parse_yacc.h" 31#include "r_area.h" 32#include "r_area_list.h" 33#include "r_layout.h" 34#ifdef SOUNDS 35# include "sound.h" 36#endif 37 38#include "gram.tab.h" 39 40 41static int ParseRandomPlacement(const char *s); 42static int ParseButtonStyle(const char *s); 43static int ParseUsePPosition(const char *s); 44static int ParseIconifyStyle(const char *s); 45 46 47 48/********************************************************************** 49 * 50 * Parsing table and routines 51 * 52 ***********************************************************************/ 53 54typedef struct _TwmKeyword { 55 const char *name; 56 int value; 57 int subnum; 58} TwmKeyword; 59 60#define kw0_NoDefaults 1 61#define kw0_AutoRelativeResize 2 62#define kw0_ForceIcons 3 63#define kw0_NoIconManagers 4 64#define kw0_InterpolateMenuColors 6 65//#define kw0_NoVersion 7 66#define kw0_SortIconManager 8 67#define kw0_NoGrabServer 9 68#define kw0_NoMenuShadows 10 69#define kw0_NoRaiseOnMove 11 70#define kw0_NoRaiseOnResize 12 71#define kw0_NoRaiseOnDeiconify 13 72#define kw0_DontMoveOff 14 73#define kw0_NoBackingStore 15 74#define kw0_NoSaveUnders 16 75#define kw0_RestartPreviousState 17 76#define kw0_ClientBorderWidth 18 77#define kw0_NoTitleFocus 19 78#define kw0_DecorateTransients 21 79#define kw0_ShowIconManager 22 80#define kw0_NoCaseSensitive 23 81#define kw0_NoRaiseOnWarp 24 82#define kw0_WarpUnmapped 25 83#define kw0_ShowWorkspaceManager 27 84#define kw0_StartInMapState 28 85#define kw0_NoShowOccupyAll 29 86#define kw0_AutoOccupy 30 87#define kw0_TransientHasOccupation 31 88#define kw0_DontPaintRootWindow 32 89#define kw0_Use3DMenus 33 90#define kw0_Use3DTitles 34 91#define kw0_Use3DIconManagers 35 92#define kw0_Use3DBorders 36 93#define kw0_SunkFocusWindowTitle 37 94#define kw0_BeNiceToColormap 38 95#define kw0_WarpRingOnScreen 40 96#define kw0_NoIconManagerFocus 41 97#define kw0_StayUpMenus 42 98#define kw0_ClickToFocus 43 99#define kw0_BorderResizeCursors 44 100#define kw0_ReallyMoveInWorkspaceManager 45 101#define kw0_ShowWinWhenMovingInWmgr 46 102#define kw0_Use3DWMap 47 103#define kw0_ReverseCurrentWorkspace 48 104#define kw0_DontWarpCursorInWMap 49 105#define kw0_CenterFeedbackWindow 50 106#define kw0_WarpToDefaultMenuEntry 51 107#define kw0_ShrinkIconTitles 52 108#define kw0_AutoRaiseIcons 53 109//#define kw0_use3DIconBorders 54 110#define kw0_UseSunkTitlePixmap 55 111#define kw0_ShortAllWindowsMenus 56 112#define kw0_RaiseWhenAutoUnSqueeze 57 113#define kw0_RaiseOnClick 58 114#define kw0_IgnoreLockModifier 59 115#define kw0_AutoFocusToTransients 60 /* kai */ 116#define kw0_PackNewWindows 61 117#define kw0_IgnoreCaseInMenuSelection 62 118#define kw0_SloppyFocus 63 119#define kw0_NoImagesInWorkSpaceManager 64 120#define kw0_NoWarpToMenuTitle 65 121#define kw0_SaveWorkspaceFocus 66 /* blais */ 122#define kw0_RaiseOnWarp 67 123#define kw0_DontShowWelcomeWindow 68 124#define kw0_AutoPriority 69 125#define kw0_DontToggleWorkspacemanagerState 70 126#define kw0_BackingStore 71 127#define kw0_StartInButtonState 72 128#define kw0_NoSortIconManager 73 129#define kw0_NoRestartPreviousState 74 130#define kw0_NoDecorateTransients 75 131#define kw0_GrabServer 76 132#define kw0_DontNameDecorations 77 133#define kw0_StrictWinNameEncoding 78 134 135#define kws_UsePPosition 1 136#define kws_IconFont 2 137#define kws_ResizeFont 3 138#define kws_MenuFont 4 139#define kws_TitleFont 5 140#define kws_IconManagerFont 6 141#define kws_UnknownIcon 7 142#define kws_IconDirectory 8 143#define kws_MaxWindowSize 9 144#define kws_PixmapDirectory 10 145/* RandomPlacement moved because it's now a string string keyword */ 146#define kws_IconJustification 12 147#define kws_TitleJustification 13 148#define kws_IconRegionJustification 14 149#define kws_IconRegionAlignement 15 150#define kws_SoundHost 16 151#define kws_WMgrButtonStyle 17 152#define kws_WorkSpaceFont 18 153#define kws_IconifyStyle 19 154#define kws_IconSize 20 155#define kws_RplaySoundHost 21 156 157#define kwss_RandomPlacement 1 158 159#define kwn_ConstrainedMoveTime 1 160#define kwn_MoveDelta 2 161#define kwn_XorValue 3 162#define kwn_FramePadding 4 163#define kwn_TitlePadding 5 164#define kwn_ButtonIndent 6 165#define kwn_BorderWidth 7 166#define kwn_IconBorderWidth 8 167#define kwn_TitleButtonBorderWidth 9 168#define kwn_RaiseDelay 10 169#define kwn_TransientOnTop 11 170#define kwn_OpaqueMoveThreshold 12 171#define kwn_OpaqueResizeThreshold 13 172#define kwn_WMgrVertButtonIndent 14 173#define kwn_WMgrHorizButtonIndent 15 174#define kwn_ClearShadowContrast 16 175#define kwn_DarkShadowContrast 17 176#define kwn_WMgrButtonShadowDepth 18 177#define kwn_MaxIconTitleWidth 19 178#define kwn_AnimationSpeed 20 179#define kwn_ThreeDBorderWidth 21 180#define kwn_MoveOffResistance 22 181#define kwn_BorderShadowDepth 23 182#define kwn_TitleShadowDepth 24 183#define kwn_TitleButtonShadowDepth 25 184#define kwn_MenuShadowDepth 26 185#define kwn_IconManagerShadowDepth 27 186#define kwn_MovePackResistance 28 187#define kwn_XMoveGrid 29 188#define kwn_YMoveGrid 30 189#define kwn_OpenWindowTimeout 31 190#define kwn_RaiseOnClickButton 32 191 192#define kwn_BorderTop 33 193#define kwn_BorderBottom 34 194#define kwn_BorderLeft 35 195#define kwn_BorderRight 36 196 197#define kwcl_BorderColor 1 198#define kwcl_IconManagerHighlight 2 199#define kwcl_BorderTileForeground 3 200#define kwcl_BorderTileBackground 4 201#define kwcl_TitleForeground 5 202#define kwcl_TitleBackground 6 203#define kwcl_IconForeground 7 204#define kwcl_IconBackground 8 205#define kwcl_IconBorderColor 9 206#define kwcl_IconManagerForeground 10 207#define kwcl_IconManagerBackground 11 208#define kwcl_MapWindowBackground 12 209#define kwcl_MapWindowForeground 13 210 211#define kwc_DefaultForeground 1 212#define kwc_DefaultBackground 2 213#define kwc_MenuForeground 3 214#define kwc_MenuBackground 4 215#define kwc_MenuTitleForeground 5 216#define kwc_MenuTitleBackground 6 217#define kwc_MenuShadowColor 7 218 219 220/* 221 * The following is sorted alphabetically according to name (which must be 222 * in lowercase and only contain the letters a-z). It is fed to a binary 223 * search to parse keywords. 224 */ 225static const TwmKeyword keytable[] = { 226 { "a", ALTER, 0 }, 227 { "all", ALL, 0 }, 228 { "alter", ALTER, 0 }, 229 { "alwaysontop", ALWAYS_ON_TOP, 0 }, 230 { "alwaysshowwindowwhenmovingfromworkspacemanager", KEYWORD, kw0_ShowWinWhenMovingInWmgr }, 231 { "alwayssqueezetogravity", ALWAYSSQUEEZETOGRAVITY, 0 }, 232 { "animationspeed", NKEYWORD, kwn_AnimationSpeed }, 233 { "autofocustotransients", KEYWORD, kw0_AutoFocusToTransients }, /* kai */ 234 { "autolower", AUTO_LOWER, 0 }, 235 { "autooccupy", KEYWORD, kw0_AutoOccupy }, 236 { "autopopup", AUTO_POPUP, 0 }, 237 { "autopriority", KEYWORD, kw0_AutoPriority }, 238 { "autoraise", AUTO_RAISE, 0 }, 239 { "autoraiseicons", KEYWORD, kw0_AutoRaiseIcons }, 240 { "autorelativeresize", KEYWORD, kw0_AutoRelativeResize }, 241 { "autosqueeze", AUTOSQUEEZE, 0 }, 242 { "backingstore", KEYWORD, kw0_BackingStore }, 243 { "benicetocolormap", KEYWORD, kw0_BeNiceToColormap }, 244 { "borderbottom", NKEYWORD, kwn_BorderBottom }, 245 { "bordercolor", CLKEYWORD, kwcl_BorderColor }, 246 { "borderleft", NKEYWORD, kwn_BorderLeft }, 247 { "borderresizecursors", KEYWORD, kw0_BorderResizeCursors }, 248 { "borderright", NKEYWORD, kwn_BorderRight }, 249 { "bordershadowdepth", NKEYWORD, kwn_BorderShadowDepth }, 250 { "bordertilebackground", CLKEYWORD, kwcl_BorderTileBackground }, 251 { "bordertileforeground", CLKEYWORD, kwcl_BorderTileForeground }, 252 { "bordertop", NKEYWORD, kwn_BorderTop }, 253 { "borderwidth", NKEYWORD, kwn_BorderWidth }, 254 { "button", BUTTON, 0 }, 255 { "buttonindent", NKEYWORD, kwn_ButtonIndent }, 256 { "c", CONTROL, 0 }, 257 { "center", SIJENUM, SIJ_CENTER }, 258 { "centerfeedbackwindow", KEYWORD, kw0_CenterFeedbackWindow }, 259 { "changeworkspacefunction", CHANGE_WORKSPACE_FUNCTION, 0 }, 260 { "clearshadowcontrast", NKEYWORD, kwn_ClearShadowContrast }, 261 { "clicktofocus", KEYWORD, kw0_ClickToFocus }, 262 { "clientborderwidth", KEYWORD, kw0_ClientBorderWidth }, 263 { "color", COLOR, 0 }, 264 { "constrainedmovetime", NKEYWORD, kwn_ConstrainedMoveTime }, 265 { "control", CONTROL, 0 }, 266 { "cursors", CURSORS, 0 }, 267 { "darkshadowcontrast", NKEYWORD, kwn_DarkShadowContrast }, 268 { "decoratetransients", KEYWORD, kw0_DecorateTransients }, 269 { "defaultbackground", CKEYWORD, kwc_DefaultBackground }, 270 { "defaultforeground", CKEYWORD, kwc_DefaultForeground }, 271 { "defaultfunction", DEFAULT_FUNCTION, 0 }, 272 { "deiconifyfunction", DEICONIFY_FUNCTION, 0 }, 273 { "destroy", KILL, 0 }, 274 { "donticonifybyunmapping", DONT_ICONIFY_BY_UNMAPPING, 0 }, 275 { "dontmoveoff", KEYWORD, kw0_DontMoveOff }, 276 { "dontnamedecorations", KEYWORD, kw0_DontNameDecorations }, 277 { "dontpaintrootwindow", KEYWORD, kw0_DontPaintRootWindow }, 278 { "dontsave", DONT_SAVE, 0 }, 279 { "dontsetinactive", DONTSETINACTIVE, 0 }, 280 { "dontshowwelcomewindow", KEYWORD, kw0_DontShowWelcomeWindow }, 281 { "dontsqueezetitle", DONT_SQUEEZE_TITLE, 0 }, 282 { "donttoggleworkspacemanagerstate", KEYWORD, kw0_DontToggleWorkspacemanagerState}, 283 { "dontwarpcursorinwmap", KEYWORD, kw0_DontWarpCursorInWMap }, 284 { "east", GRAVITY, GRAV_EAST }, 285 { "ewmhignore", EWMH_IGNORE, 0 }, 286 { "f", FRAME, 0 }, 287 { "forcefocus", FORCE_FOCUS, 0 }, 288 { "forceicons", KEYWORD, kw0_ForceIcons }, 289 { "frame", FRAME, 0 }, 290 { "framepadding", NKEYWORD, kwn_FramePadding }, 291 { "function", FUNCTION, 0 }, 292 { "grabserver", KEYWORD, kw0_GrabServer }, 293 { "i", ICON, 0 }, 294 { "icon", ICON, 0 }, 295 { "iconbackground", CLKEYWORD, kwcl_IconBackground }, 296 { "iconbordercolor", CLKEYWORD, kwcl_IconBorderColor }, 297 { "iconborderwidth", NKEYWORD, kwn_IconBorderWidth }, 298 { "icondirectory", SKEYWORD, kws_IconDirectory }, 299 { "iconfont", SKEYWORD, kws_IconFont }, 300 { "iconforeground", CLKEYWORD, kwcl_IconForeground }, 301 { "iconifybyunmapping", ICONIFY_BY_UNMAPPING, 0 }, 302 { "iconifyfunction", ICONIFY_FUNCTION, 0 }, 303 { "iconifystyle", SKEYWORD, kws_IconifyStyle }, 304 { "iconjustification", SKEYWORD, kws_IconJustification }, 305 { "iconmanagerbackground", CLKEYWORD, kwcl_IconManagerBackground }, 306 { "iconmanagerdontshow", ICONMGR_NOSHOW, 0 }, 307 { "iconmanagerfont", SKEYWORD, kws_IconManagerFont }, 308 { "iconmanagerforeground", CLKEYWORD, kwcl_IconManagerForeground }, 309 { "iconmanagergeometry", ICONMGR_GEOMETRY, 0 }, 310 { "iconmanagerhighlight", CLKEYWORD, kwcl_IconManagerHighlight }, 311 { "iconmanagers", ICONMGRS, 0 }, 312 { "iconmanagershadowdepth", NKEYWORD, kwn_IconManagerShadowDepth }, 313 { "iconmanagershow", ICONMGR_SHOW, 0 }, 314 { "iconmenudontshow", ICONMENU_DONTSHOW, 0 }, 315 { "iconmgr", ICONMGR, 0 }, 316 { "iconregion", ICON_REGION, 0 }, 317 { "iconregionalignement", SKEYWORD, kws_IconRegionAlignement }, 318 { "iconregionjustification", SKEYWORD, kws_IconRegionJustification }, 319 { "icons", ICONS, 0 }, 320 { "iconsize", SKEYWORD, kws_IconSize }, 321 { "ignorecaseinmenuselection", KEYWORD, kw0_IgnoreCaseInMenuSelection }, 322 { "ignorelockmodifier", KEYWORD, kw0_IgnoreLockModifier }, 323 { "ignoremodifier", IGNOREMODIFIER, 0 }, 324 { "ignoretransient", IGNORE_TRANSIENT, 0 }, 325 { "interpolatemenucolors", KEYWORD, kw0_InterpolateMenuColors }, 326 { "l", LOCK, 0 }, 327 { "left", SIJENUM, SIJ_LEFT }, 328 { "lefttitlebutton", LEFT_TITLEBUTTON, 0 }, 329 { "lock", LOCK, 0 }, 330 { "m", META, 0 }, 331 { "maketitle", MAKE_TITLE, 0 }, 332 { "mapwindowbackground", CLKEYWORD, kwcl_MapWindowBackground }, 333 { "mapwindowcurrentworkspace", MAPWINDOWCURRENTWORKSPACE, 0}, 334 { "mapwindowdefaultworkspace", MAPWINDOWDEFAULTWORKSPACE, 0}, 335 { "mapwindowforeground", CLKEYWORD, kwcl_MapWindowForeground }, 336 { "maxicontitlewidth", NKEYWORD, kwn_MaxIconTitleWidth }, 337 { "maxwindowsize", SKEYWORD, kws_MaxWindowSize }, 338 { "menu", MENU, 0 }, 339 { "menubackground", CKEYWORD, kwc_MenuBackground }, 340 { "menufont", SKEYWORD, kws_MenuFont }, 341 { "menuforeground", CKEYWORD, kwc_MenuForeground }, 342 { "menushadowcolor", CKEYWORD, kwc_MenuShadowColor }, 343 { "menushadowdepth", NKEYWORD, kwn_MenuShadowDepth }, 344 { "menutitlebackground", CKEYWORD, kwc_MenuTitleBackground }, 345 { "menutitleforeground", CKEYWORD, kwc_MenuTitleForeground }, 346 { "meta", META, 0 }, 347 { "mod", META, 0 }, /* fake it */ 348 { "monitorlayout", MONITOR_LAYOUT, 0 }, 349 { "monochrome", MONOCHROME, 0 }, 350 { "move", MOVE, 0 }, 351 { "movedelta", NKEYWORD, kwn_MoveDelta }, 352 { "moveoffresistance", NKEYWORD, kwn_MoveOffResistance }, 353 { "movepackresistance", NKEYWORD, kwn_MovePackResistance }, 354 { "mwmignore", MWM_IGNORE, 0 }, 355 { "nobackingstore", KEYWORD, kw0_NoBackingStore }, 356 { "noborder", NO_BORDER, 0 }, 357 { "nocasesensitive", KEYWORD, kw0_NoCaseSensitive }, 358 { "nodecoratetransients", KEYWORD, kw0_NoDecorateTransients }, 359 { "nodefaults", KEYWORD, kw0_NoDefaults }, 360 { "nograbserver", KEYWORD, kw0_NoGrabServer }, 361 { "nohighlight", NO_HILITE, 0 }, 362 { "noiconmanagerfocus", KEYWORD, kw0_NoIconManagerFocus }, 363 { "noiconmanagers", KEYWORD, kw0_NoIconManagers }, 364 { "noicontitle", NO_ICON_TITLE, 0 }, 365 { "noimagesinworkspacemanager", KEYWORD, kw0_NoImagesInWorkSpaceManager }, 366 { "nomenushadows", KEYWORD, kw0_NoMenuShadows }, 367 { "noopaquemove", NOOPAQUEMOVE, 0 }, 368 { "noopaqueresize", NOOPAQUERESIZE, 0 }, 369 { "noraiseondeiconify", KEYWORD, kw0_NoRaiseOnDeiconify }, 370 { "noraiseonmove", KEYWORD, kw0_NoRaiseOnMove }, 371 { "noraiseonresize", KEYWORD, kw0_NoRaiseOnResize }, 372 { "noraiseonwarp", KEYWORD, kw0_NoRaiseOnWarp }, 373 { "norestartpreviousstate", KEYWORD, kw0_NoRestartPreviousState }, 374 { "north", GRAVITY, GRAV_NORTH }, 375 { "nosaveunders", KEYWORD, kw0_NoSaveUnders }, 376 { "noshowoccupyall", KEYWORD, kw0_NoShowOccupyAll }, 377 { "nosorticonmanager", KEYWORD, kw0_NoSortIconManager }, 378 { "nostackmode", NO_STACKMODE, 0 }, 379 { "notitle", NO_TITLE, 0 }, 380 { "notitlefocus", KEYWORD, kw0_NoTitleFocus }, 381 { "notitlehighlight", NO_TITLE_HILITE, 0 }, 382 { "nowarptomenutitle", KEYWORD, kw0_NoWarpToMenuTitle }, 383 { "occupy", OCCUPYLIST, 0 }, 384 { "occupyall", OCCUPYALL, 0 }, 385 { "ontoppriority", ON_TOP_PRIORITY, 0 }, 386 { "opaquemove", OPAQUEMOVE, 0 }, 387 { "opaquemovethreshold", NKEYWORD, kwn_OpaqueMoveThreshold }, 388 { "opaqueresize", OPAQUERESIZE, 0 }, 389 { "opaqueresizethreshold", NKEYWORD, kwn_OpaqueResizeThreshold }, 390 { "openwindowtimeout", NKEYWORD, kwn_OpenWindowTimeout }, 391 { "packnewwindows", KEYWORD, kw0_PackNewWindows }, 392 { "pixmapdirectory", SKEYWORD, kws_PixmapDirectory }, 393 { "pixmaps", PIXMAPS, 0 }, 394 { "prioritynotswitching", PRIORITY_NOT_SWITCHING, 0 }, 395 { "priorityswitching", PRIORITY_SWITCHING, 0 }, 396 { "r", ROOT, 0 }, 397 { "raisedelay", NKEYWORD, kwn_RaiseDelay }, 398 { "raiseonclick", KEYWORD, kw0_RaiseOnClick }, 399 { "raiseonclickbutton", NKEYWORD, kwn_RaiseOnClickButton }, 400 { "raiseonwarp", KEYWORD, kw0_RaiseOnWarp }, 401 { "raisewhenautounsqueeze", KEYWORD, kw0_RaiseWhenAutoUnSqueeze }, 402 { "randomplacement", SSKEYWORD, kwss_RandomPlacement }, 403 { "reallymoveinworkspacemanager", KEYWORD, kw0_ReallyMoveInWorkspaceManager }, 404 { "resize", RESIZE, 0 }, 405 { "resizefont", SKEYWORD, kws_ResizeFont }, 406 { "restartpreviousstate", KEYWORD, kw0_RestartPreviousState }, 407 { "reversecurrentworkspace", KEYWORD, kw0_ReverseCurrentWorkspace }, 408 { "right", SIJENUM, SIJ_RIGHT }, 409 { "righttitlebutton", RIGHT_TITLEBUTTON, 0 }, 410 { "root", ROOT, 0 }, 411 { "rplaysoundhost", SKEYWORD, kws_RplaySoundHost }, 412 { "rplaysounds", RPLAY_SOUNDS, 0 }, 413 { "s", SHIFT, 0 }, 414 { "savecolor", SAVECOLOR, 0}, 415 { "saveworkspacefocus", KEYWORD, kw0_SaveWorkspaceFocus }, 416 { "schrinkicontitles", KEYWORD, kw0_ShrinkIconTitles }, 417 { "select", SELECT, 0 }, 418 { "shift", SHIFT, 0 }, 419 { "shortallwindowsmenus", KEYWORD, kw0_ShortAllWindowsMenus }, 420 { "showiconmanager", KEYWORD, kw0_ShowIconManager }, 421 { "showworkspacemanager", KEYWORD, kw0_ShowWorkspaceManager }, 422 { "shrinkicontitles", KEYWORD, kw0_ShrinkIconTitles }, 423 { "sloppyfocus", KEYWORD, kw0_SloppyFocus }, 424 { "sorticonmanager", KEYWORD, kw0_SortIconManager }, 425 { "soundhost", SKEYWORD, kws_SoundHost }, 426 { "south", GRAVITY, GRAV_SOUTH }, 427 { "squeezetitle", SQUEEZE_TITLE, 0 }, 428 { "starticonified", START_ICONIFIED, 0 }, 429 { "startinbuttonstate", KEYWORD, kw0_StartInButtonState }, 430 { "startinmapstate", KEYWORD, kw0_StartInMapState }, 431 { "startsqueezed", STARTSQUEEZED, 0 }, 432 { "stayupmenus", KEYWORD, kw0_StayUpMenus }, 433 { "strictwinnameencoding", KEYWORD, kw0_StrictWinNameEncoding }, 434 { "sunkfocuswindowtitle", KEYWORD, kw0_SunkFocusWindowTitle }, 435 { "t", TITLE, 0 }, 436 { "threedborderwidth", NKEYWORD, kwn_ThreeDBorderWidth }, 437 { "title", TITLE, 0 }, 438 { "titlebackground", CLKEYWORD, kwcl_TitleBackground }, 439 { "titlebuttonborderwidth", NKEYWORD, kwn_TitleButtonBorderWidth }, 440 { "titlebuttonshadowdepth", NKEYWORD, kwn_TitleButtonShadowDepth }, 441 { "titlefont", SKEYWORD, kws_TitleFont }, 442 { "titleforeground", CLKEYWORD, kwcl_TitleForeground }, 443 { "titlehighlight", TITLE_HILITE, 0 }, 444 { "titlejustification", SKEYWORD, kws_TitleJustification }, 445 { "titlepadding", NKEYWORD, kwn_TitlePadding }, 446 { "titleshadowdepth", NKEYWORD, kwn_TitleShadowDepth }, 447 { "transienthasoccupation", KEYWORD, kw0_TransientHasOccupation }, 448 { "transientontop", NKEYWORD, kwn_TransientOnTop }, 449 { "unknownicon", SKEYWORD, kws_UnknownIcon }, 450 { "unmapbymovingfaraway", UNMAPBYMOVINGFARAWAY, 0 }, 451 { "usepposition", SKEYWORD, kws_UsePPosition }, 452 { "usesunktitlepixmap", KEYWORD, kw0_UseSunkTitlePixmap }, 453 { "usethreedborders", KEYWORD, kw0_Use3DBorders }, 454 { "usethreediconmanagers", KEYWORD, kw0_Use3DIconManagers }, 455 { "usethreedmenus", KEYWORD, kw0_Use3DMenus }, 456 { "usethreedtitles", KEYWORD, kw0_Use3DTitles }, 457 { "usethreedwmap", KEYWORD, kw0_Use3DWMap }, 458#ifdef VSCREEN 459 { "virtualscreens", VIRTUAL_SCREENS, 0 }, 460#endif 461 { "w", WINDOW, 0 }, 462 { "wait", WAITC, 0 }, 463 { "warpcursor", WARP_CURSOR, 0 }, 464 { "warpondeiconify", WARP_ON_DEICONIFY, 0 }, 465 { "warpringonscreen", KEYWORD, kw0_WarpRingOnScreen }, 466 { "warptodefaultmenuentry", KEYWORD, kw0_WarpToDefaultMenuEntry }, 467 { "warpunmapped", KEYWORD, kw0_WarpUnmapped }, 468 { "west", GRAVITY, GRAV_WEST }, 469 { "window", WINDOW, 0 }, 470#ifdef WINBOX 471 { "windowbox", WINDOW_BOX, 0 }, 472#endif 473 { "windowfunction", WINDOW_FUNCTION, 0 }, 474 { "windowgeometries", WINDOW_GEOMETRIES, 0 }, 475 { "windowregion", WINDOW_REGION, 0 }, 476 { "windowring", WINDOW_RING, 0 }, 477 { "windowringexclude", WINDOW_RING_EXCLUDE, 0}, 478 { "wmgrbuttonshadowdepth", NKEYWORD, kwn_WMgrButtonShadowDepth }, 479 { "wmgrbuttonstyle", SKEYWORD, kws_WMgrButtonStyle }, 480 { "wmgrhorizbuttonindent", NKEYWORD, kwn_WMgrHorizButtonIndent }, 481 { "wmgrvertbuttonindent", NKEYWORD, kwn_WMgrVertButtonIndent }, 482 { "workspace", WORKSPACE, 0 }, 483 { "workspacefont", SKEYWORD, kws_WorkSpaceFont }, 484 { "workspacemanagergeometry", WORKSPCMGR_GEOMETRY, 0 }, 485 { "workspaces", WORKSPACES, 0}, 486 { "xmovegrid", NKEYWORD, kwn_XMoveGrid }, 487 { "xorvalue", NKEYWORD, kwn_XorValue }, 488 { "xpmicondirectory", SKEYWORD, kws_PixmapDirectory }, 489 { "ymovegrid", NKEYWORD, kwn_YMoveGrid }, 490 { "zoom", ZOOM, 0 }, 491}; 492 493static const size_t numkeywords = (sizeof(keytable) / sizeof(keytable[0])); 494 495 496/* 497 * The lookup table for functions is generated. 498 */ 499#include "functions_parse_table.h" 500 501 502 503static int 504kt_compare(const void *lhs, const void *rhs) 505{ 506 const TwmKeyword *l = lhs; 507 const TwmKeyword *r = rhs; 508 return strcasecmp(l->name, r->name); 509} 510 511int 512parse_keyword(const char *s, int *nump) 513{ 514 const TwmKeyword srch = { .name = s }; 515 TwmKeyword *ret; 516 const TwmKeyword *srchtab; 517 size_t nstab; 518 519 /* Guard; nothing can't be a valid keyword */ 520 if(s == NULL || strlen(s) < 1) { 521 return ERRORTOKEN; 522 } 523 524 /* 525 * Functions are in their own table, so check for them there. 526 * 527 * This is safe as long as (strlen >= 1), which we already checked. 528 */ 529 if(s[0] == 'f' && s[1] == '.') { 530 srchtab = funckeytable; 531 nstab = numfunckeywords; 532 } 533 else { 534 srchtab = keytable; 535 nstab = numkeywords; 536 } 537 538 /* Find it */ 539 ret = bsearch(&srch, srchtab, nstab, sizeof(TwmKeyword), kt_compare); 540 if(ret) { 541 *nump = ret->subnum; 542 return ret->value; 543 } 544 545 return ERRORTOKEN; 546} 547 548 549/* 550 * Simple tester function 551 */ 552void 553chk_keytable_order(void) 554{ 555 int i; 556 557 for(i = 0 ; i < (numkeywords - 1) ; i++) { 558 if(strcasecmp(keytable[i].name, keytable[i + 1].name) >= 0) { 559 fprintf(stderr, "%s: INTERNAL ERROR: keytable sorting: " 560 "'%s' >= '%s'\n", ProgramName, 561 keytable[i].name, keytable[i + 1].name); 562 } 563 } 564 565 for(i = 0 ; i < (numfunckeywords - 1) ; i++) { 566 if(strcasecmp(funckeytable[i].name, funckeytable[i + 1].name) >= 0) { 567 fprintf(stderr, "%s: INTERNAL ERROR: funckeytable sorting: " 568 "'%s' >= '%s'\n", ProgramName, 569 funckeytable[i].name, funckeytable[i + 1].name); 570 } 571 } 572} 573 574 575 576/* 577 * action routines called by grammar 578 */ 579 580bool 581do_single_keyword(int keyword) 582{ 583 switch(keyword) { 584 case kw0_NoDefaults: 585 Scr->NoDefaults = true; 586 return true; 587 588 case kw0_AutoRelativeResize: 589 Scr->AutoRelativeResize = true; 590 return true; 591 592 case kw0_ForceIcons: 593 if(Scr->FirstTime) { 594 Scr->ForceIcon = true; 595 } 596 return true; 597 598 case kw0_NoIconManagers: 599 Scr->NoIconManagers = true; 600 return true; 601 602 case kw0_InterpolateMenuColors: 603 if(Scr->FirstTime) { 604 Scr->InterpolateMenuColors = true; 605 } 606 return true; 607 608 case kw0_SortIconManager: 609 if(Scr->FirstTime) { 610 Scr->SortIconMgr = true; 611 } 612 return true; 613 614 case kw0_NoSortIconManager: 615 if(Scr->FirstTime) { 616 Scr->SortIconMgr = false; 617 } 618 return true; 619 620 case kw0_GrabServer: 621 Scr->NoGrabServer = false; 622 return true; 623 624 case kw0_NoGrabServer: 625 Scr->NoGrabServer = true; 626 return true; 627 628 case kw0_NoMenuShadows: 629 if(Scr->FirstTime) { 630 Scr->Shadow = false; 631 } 632 return true; 633 634 case kw0_NoRaiseOnMove: 635 if(Scr->FirstTime) { 636 Scr->NoRaiseMove = true; 637 } 638 return true; 639 640 case kw0_NoRaiseOnResize: 641 if(Scr->FirstTime) { 642 Scr->NoRaiseResize = true; 643 } 644 return true; 645 646 case kw0_NoRaiseOnDeiconify: 647 if(Scr->FirstTime) { 648 Scr->NoRaiseDeicon = true; 649 } 650 return true; 651 652 case kw0_DontMoveOff: 653 Scr->DontMoveOff = true; 654 return true; 655 656 case kw0_NoBackingStore: 657 Scr->BackingStore = false; 658 return true; 659 660 case kw0_BackingStore: 661 Scr->BackingStore = true; 662 return true; 663 664 case kw0_NoSaveUnders: 665 Scr->SaveUnder = false; 666 return true; 667 668 // XXX Shouldn't these be in Scr too? 669 case kw0_RestartPreviousState: 670 RestartPreviousState = true; 671 return true; 672 673 case kw0_NoRestartPreviousState: 674 RestartPreviousState = false; 675 return true; 676 677 case kw0_ClientBorderWidth: 678 if(Scr->FirstTime) { 679 Scr->ClientBorderWidth = true; 680 } 681 return true; 682 683 case kw0_NoTitleFocus: 684 Scr->TitleFocus = false; 685 return true; 686 687 case kw0_DecorateTransients: 688 Scr->DecorateTransients = true; 689 return true; 690 691 case kw0_NoDecorateTransients: 692 Scr->DecorateTransients = false; 693 return true; 694 695 case kw0_ShowIconManager: 696 Scr->ShowIconManager = true; 697 return true; 698 699 case kw0_ShowWorkspaceManager: 700 Scr->ShowWorkspaceManager = true; 701 return true; 702 703 case kw0_StartInButtonState: 704 Scr->workSpaceMgr.initialstate = WMS_buttons; 705 return true; 706 707 case kw0_StartInMapState: 708 Scr->workSpaceMgr.initialstate = WMS_map; 709 return true; 710 711 case kw0_NoShowOccupyAll: 712 Scr->workSpaceMgr.noshowoccupyall = true; 713 return true; 714 715 case kw0_AutoOccupy: 716 Scr->AutoOccupy = true; 717 return true; 718 719 case kw0_AutoPriority: 720 Scr->AutoPriority = true; 721 return true; 722 723 case kw0_TransientHasOccupation: 724 Scr->TransientHasOccupation = true; 725 return true; 726 727 case kw0_DontPaintRootWindow: 728 Scr->DontPaintRootWindow = true; 729 return true; 730 731 case kw0_UseSunkTitlePixmap: 732 Scr->UseSunkTitlePixmap = true; 733 return true; 734 735 case kw0_Use3DBorders: 736 Scr->use3Dborders = true; 737 return true; 738 739 case kw0_Use3DIconManagers: 740 Scr->use3Diconmanagers = true; 741 return true; 742 743 case kw0_Use3DMenus: 744 Scr->use3Dmenus = true; 745 return true; 746 747 case kw0_Use3DTitles: 748 Scr->use3Dtitles = true; 749 return true; 750 751 case kw0_Use3DWMap: 752 Scr->use3Dwmap = true; 753 return true; 754 755 case kw0_SunkFocusWindowTitle: 756 Scr->SunkFocusWindowTitle = true; 757 return true; 758 759 case kw0_BeNiceToColormap: 760 Scr->BeNiceToColormap = true; 761 return true; 762 763 case kw0_BorderResizeCursors: 764 Scr->BorderCursors = true; 765 return true; 766 767 case kw0_NoCaseSensitive: 768 Scr->CaseSensitive = false; 769 return true; 770 771 case kw0_NoRaiseOnWarp: 772 Scr->RaiseOnWarp = false; 773 return true; 774 775 case kw0_RaiseOnWarp: 776 Scr->RaiseOnWarp = true; 777 return true; 778 779 case kw0_WarpUnmapped: 780 Scr->WarpUnmapped = true; 781 return true; 782 783 case kw0_WarpRingOnScreen: 784 Scr->WarpRingAnyWhere = false; 785 return true; 786 787 case kw0_NoIconManagerFocus: 788 Scr->IconManagerFocus = false; 789 return true; 790 791 case kw0_StayUpMenus: 792 Scr->StayUpMenus = true; 793 return true; 794 795 case kw0_ClickToFocus: 796 Scr->ClickToFocus = true; 797 return true; 798 799 case kw0_ReallyMoveInWorkspaceManager: 800 Scr->ReallyMoveInWorkspaceManager = true; 801 return true; 802 803 case kw0_ShowWinWhenMovingInWmgr: 804 Scr->ShowWinWhenMovingInWmgr = true; 805 return true; 806 807 case kw0_ReverseCurrentWorkspace: 808 Scr->ReverseCurrentWorkspace = true; 809 return true; 810 811 case kw0_DontWarpCursorInWMap: 812 Scr->DontWarpCursorInWMap = true; 813 return true; 814 815 case kw0_CenterFeedbackWindow: 816 Scr->CenterFeedbackWindow = true; 817 return true; 818 819 case kw0_WarpToDefaultMenuEntry: 820 Scr->WarpToDefaultMenuEntry = true; 821 return true; 822 823 case kw0_ShrinkIconTitles: 824 Scr->ShrinkIconTitles = true; 825 return true; 826 827 case kw0_AutoRaiseIcons: 828 Scr->AutoRaiseIcons = true; 829 return true; 830 831 /* kai */ 832 case kw0_AutoFocusToTransients: 833 Scr->AutoFocusToTransients = true; 834 return true; 835 836 case kw0_ShortAllWindowsMenus: 837 Scr->ShortAllWindowsMenus = true; 838 return true; 839 840 case kw0_RaiseWhenAutoUnSqueeze: 841 Scr->RaiseWhenAutoUnSqueeze = true; 842 return true; 843 844 case kw0_RaiseOnClick: 845 Scr->RaiseOnClick = true; 846 return true; 847 848 case kw0_IgnoreLockModifier: 849 Scr->IgnoreModifier |= LockMask; 850 return true; 851 852 case kw0_PackNewWindows: 853 Scr->PackNewWindows = true; 854 return true; 855 856 case kw0_IgnoreCaseInMenuSelection: 857 Scr->IgnoreCaseInMenuSelection = true; 858 return true; 859 860 case kw0_SloppyFocus: 861 Scr->SloppyFocus = true; 862 return true; 863 864 case kw0_SaveWorkspaceFocus: 865 Scr->SaveWorkspaceFocus = true; 866 return true; 867 868 case kw0_NoImagesInWorkSpaceManager: 869 Scr->NoImagesInWorkSpaceManager = true; 870 return true; 871 872 case kw0_NoWarpToMenuTitle: 873 Scr->NoWarpToMenuTitle = true; 874 return true; 875 876 case kw0_DontShowWelcomeWindow: 877 Scr->ShowWelcomeWindow = false; 878 return true; 879 880 case kw0_DontToggleWorkspacemanagerState: 881 Scr->DontToggleWorkspaceManagerState = true; 882 return true; 883 884 case kw0_DontNameDecorations: 885 Scr->NameDecorations = false; 886 return true; 887 888 case kw0_StrictWinNameEncoding: 889 Scr->StrictWinNameEncoding = true; 890 return true; 891 892 } 893 return false; 894} 895 896 897bool 898do_string_string_keyword(int keyword, const char *s1, const char *s2) 899{ 900 switch(keyword) { 901 case kwss_RandomPlacement: { 902 /* RandomPlacement {on,off,all,unmapped} [displacement geom] */ 903 int rp; 904 int gmask, gx, gy; // Geometry mask/x/y values 905 unsigned int gjw, gjh; // width/height (ignored) 906 int exmask = (XValue | YValue); // Bits we need in the mask 907 908 rp = ParseRandomPlacement(s1); 909 if(rp < 0) { 910 twmrc_error_prefix(); 911 fprintf(stderr, 912 "ignoring invalid RandomPlacement argument 1 \"%s\"\n", 913 s1); 914 } 915 else { 916 Scr->RandomPlacement = rp; 917 } 918 919 /* If no geom, we're done */ 920 if(s2 == NULL) { 921 return true; 922 } 923 924 /* 925 * Figure what the geom means. We actually don't care about 926 * the size (it probably won't even be provided), so the 927 * width/height are junk. The X/Y offsets are what we need. 928 * But we do need them. 929 */ 930 gmask = XParseGeometry(s2, &gx, &gy, &gjw, &gjh); 931#ifdef DEBUG 932 fprintf(stderr, "DEBUG:: Mask = %x, Width = %d, Height = %d\n", 933 gmask, gjw, gjh); 934 fprintf(stderr, "DEBUG:: X = %d, Y = %d\n", gx, gy); 935#endif 936 if((gmask & exmask) != exmask) { 937 /* Didn't get X and Y */ 938 twmrc_error_prefix(); 939 fprintf(stderr, 940 "ignoring invalid RandomPlacement displacement \"%s\"\n", s2); 941 } 942 else { 943 Scr->RandomDisplacementX = gx; 944 Scr->RandomDisplacementY = gy; 945 } 946 947 /* Done */ 948 return true; 949 } 950 } 951 return false; 952} 953 954 955bool 956do_string_keyword(int keyword, char *s) 957{ 958 switch(keyword) { 959 case kws_UsePPosition: { 960 int ppos = ParseUsePPosition(s); 961 if(ppos < 0) { 962 twmrc_error_prefix(); 963 fprintf(stderr, 964 "ignoring invalid UsePPosition argument \"%s\"\n", s); 965 } 966 else { 967 Scr->UsePPosition = ppos; 968 } 969 return true; 970 } 971 972 case kws_IconFont: 973 if(!Scr->HaveFonts) { 974 Scr->IconFont.basename = s; 975 } 976 return true; 977 978 case kws_ResizeFont: 979 if(!Scr->HaveFonts) { 980 Scr->SizeFont.basename = s; 981 } 982 return true; 983 984 case kws_MenuFont: 985 if(!Scr->HaveFonts) { 986 Scr->MenuFont.basename = s; 987 } 988 return true; 989 990 case kws_WorkSpaceFont: 991 if(!Scr->HaveFonts) { 992 Scr->workSpaceMgr.windowFont.basename = s; 993 } 994 return true; 995 996 case kws_TitleFont: 997 if(!Scr->HaveFonts) { 998 Scr->TitleBarFont.basename = s; 999 } 1000 return true; 1001 1002 case kws_IconManagerFont: 1003 if(!Scr->HaveFonts) { 1004 Scr->IconManagerFont.basename = s; 1005 } 1006 return true; 1007 1008 case kws_UnknownIcon: 1009 if(Scr->FirstTime) { 1010 Scr->UnknownImage = GetImage(s, Scr->IconC); 1011 } 1012 return true; 1013 1014 case kws_IconDirectory: 1015 if(Scr->FirstTime) { 1016 Scr->IconDirectory = ExpandFilePath(s); 1017 } 1018 return true; 1019 1020 case kws_PixmapDirectory: 1021 if(Scr->FirstTime) { 1022 Scr->PixmapDirectory = ExpandFilePath(s); 1023 } 1024 return true; 1025 1026 case kws_MaxWindowSize: { 1027 int gmask; 1028 int exmask = (WidthValue | HeightValue); 1029 unsigned int gw, gh; // Stuff we care about 1030 int gjx, gjy; // Stuff we don't 1031 1032 gmask = XParseGeometry(s, &gjx, &gjy, &gw, &gh); 1033 if((gmask & exmask) != exmask) { 1034 twmrc_error_prefix(); 1035 fprintf(stderr, "bad MaxWindowSize \"%s\"\n", s); 1036 return false; 1037 } 1038 if(gw == 0 || gh == 0) { 1039 twmrc_error_prefix(); 1040 fprintf(stderr, "MaxWindowSize \"%s\" must be non-zero\n", s); 1041 return false; 1042 } 1043 Scr->MaxWindowWidth = gw; 1044 Scr->MaxWindowHeight = gh; 1045 return true; 1046 } 1047 1048 case kws_IconJustification: { 1049 int just = ParseTitleJustification(s); 1050 1051 if((just < 0) || (just == TJ_UNDEF)) { 1052 twmrc_error_prefix(); 1053 fprintf(stderr, 1054 "ignoring invalid IconJustification argument \"%s\"\n", s); 1055 } 1056 else { 1057 Scr->IconJustification = just; 1058 } 1059 return true; 1060 } 1061 case kws_IconRegionJustification: { 1062 int just = ParseIRJustification(s); 1063 1064 if(just < 0 || (just == IRJ_UNDEF)) { 1065 twmrc_error_prefix(); 1066 fprintf(stderr, 1067 "ignoring invalid IconRegionJustification argument \"%s\"\n", s); 1068 } 1069 else { 1070 Scr->IconRegionJustification = just; 1071 } 1072 return true; 1073 } 1074 case kws_IconRegionAlignement: { 1075 int just = ParseAlignement(s); 1076 1077 if(just < 0) { 1078 twmrc_error_prefix(); 1079 fprintf(stderr, 1080 "ignoring invalid IconRegionAlignement argument \"%s\"\n", s); 1081 } 1082 else { 1083 Scr->IconRegionAlignement = just; 1084 } 1085 return true; 1086 } 1087 1088 case kws_TitleJustification: { 1089 int just = ParseTitleJustification(s); 1090 1091 if((just < 0) || (just == TJ_UNDEF)) { 1092 twmrc_error_prefix(); 1093 fprintf(stderr, 1094 "ignoring invalid TitleJustification argument \"%s\"\n", s); 1095 } 1096 else { 1097 Scr->TitleJustification = just; 1098 } 1099 return true; 1100 } 1101 case kws_RplaySoundHost: 1102 case kws_SoundHost: 1103 if(Scr->FirstTime) { 1104 /* Warning to be enabled in the future before removal */ 1105 if(0 && keyword == kws_SoundHost) { 1106 twmrc_error_prefix(); 1107 fprintf(stderr, "SoundHost is deprecated, please " 1108 "use RplaySoundHost instead.\n"); 1109 } 1110#ifdef SOUNDS 1111 set_sound_host(s); 1112#else 1113 twmrc_error_prefix(); 1114 fprintf(stderr, "Ignoring %sSoundHost; rplay not ronfigured.\n", 1115 (keyword == kws_RplaySoundHost ? "Rplay" : "")); 1116#endif 1117 } 1118 return true; 1119 1120 case kws_WMgrButtonStyle: { 1121 int style = ParseButtonStyle(s); 1122 1123 if(style < 0) { 1124 twmrc_error_prefix(); 1125 fprintf(stderr, 1126 "ignoring invalid WMgrButtonStyle argument \"%s\"\n", s); 1127 } 1128 else { 1129 Scr->workSpaceMgr.buttonStyle = style; 1130 } 1131 return true; 1132 } 1133 1134 case kws_IconifyStyle: { 1135 int style = ParseIconifyStyle(s); 1136 1137 if(style < 0) { 1138 twmrc_error_prefix(); 1139 fprintf(stderr, "ignoring invalid IconifyStyle argument \"%s\"\n", s); 1140 } 1141 else { 1142 Scr->IconifyStyle = style; 1143 } 1144 return true; 1145 } 1146 1147#ifdef EWMH 1148 case kws_IconSize: 1149 if(sscanf(s, "%dx%d", &Scr->PreferredIconWidth, 1150 &Scr->PreferredIconHeight) == 2) { 1151 /* ok */ 1152 } 1153 else if(sscanf(s, "%d", &Scr->PreferredIconWidth) == 1) { 1154 Scr->PreferredIconHeight = Scr->PreferredIconWidth; 1155 } 1156 else { 1157 Scr->PreferredIconHeight = Scr->PreferredIconWidth = 48; 1158 } 1159 return true; 1160#endif 1161 } 1162 return false; 1163} 1164 1165 1166bool 1167do_number_keyword(int keyword, int num) 1168{ 1169 switch(keyword) { 1170 case kwn_ConstrainedMoveTime: 1171 ConstrainedMoveTime = num; 1172 return true; 1173 1174 case kwn_MoveDelta: 1175 Scr->MoveDelta = num; 1176 return true; 1177 1178 case kwn_MoveOffResistance: 1179 Scr->MoveOffResistance = num; 1180 return true; 1181 1182 case kwn_MovePackResistance: 1183 if(num < 0) { 1184 num = 20; 1185 } 1186 Scr->MovePackResistance = num; 1187 return true; 1188 1189 case kwn_XMoveGrid: 1190 if(num < 1) { 1191 num = 1; 1192 } 1193 if(num > 100) { 1194 num = 100; 1195 } 1196 Scr->XMoveGrid = num; 1197 return true; 1198 1199 case kwn_YMoveGrid: 1200 if(num < 1) { 1201 num = 1; 1202 } 1203 if(num > 100) { 1204 num = 100; 1205 } 1206 Scr->YMoveGrid = num; 1207 return true; 1208 1209 case kwn_XorValue: 1210 if(Scr->FirstTime) { 1211 Scr->XORvalue = num; 1212 } 1213 return true; 1214 1215 case kwn_FramePadding: 1216 if(Scr->FirstTime) { 1217 Scr->FramePadding = num; 1218 } 1219 return true; 1220 1221 case kwn_TitlePadding: 1222 if(Scr->FirstTime) { 1223 Scr->TitlePadding = num; 1224 } 1225 return true; 1226 1227 case kwn_ButtonIndent: 1228 if(Scr->FirstTime) { 1229 Scr->ButtonIndent = num; 1230 } 1231 return true; 1232 1233 case kwn_ThreeDBorderWidth: 1234 if(Scr->FirstTime) { 1235 Scr->ThreeDBorderWidth = num; 1236 } 1237 return true; 1238 1239 case kwn_BorderWidth: 1240 if(Scr->FirstTime) { 1241 Scr->BorderWidth = num; 1242 } 1243 return true; 1244 1245 case kwn_IconBorderWidth: 1246 if(Scr->FirstTime) { 1247 Scr->IconBorderWidth = num; 1248 } 1249 return true; 1250 1251 case kwn_TitleButtonBorderWidth: 1252 if(Scr->FirstTime) { 1253 Scr->TBInfo.border = num; 1254 } 1255 return true; 1256 1257 case kwn_RaiseDelay: 1258 RaiseDelay = num; 1259 return true; 1260 1261 case kwn_TransientOnTop: 1262 if(Scr->FirstTime) { 1263 Scr->TransientOnTop = num; 1264 } 1265 return true; 1266 1267 case kwn_OpaqueMoveThreshold: 1268 if(Scr->FirstTime) { 1269 Scr->OpaqueMoveThreshold = num; 1270 } 1271 return true; 1272 1273 case kwn_OpaqueResizeThreshold: 1274 if(Scr->FirstTime) { 1275 Scr->OpaqueResizeThreshold = num; 1276 } 1277 return true; 1278 1279 case kwn_WMgrVertButtonIndent: 1280 if(Scr->FirstTime) { 1281 Scr->WMgrVertButtonIndent = num; 1282 } 1283 if(Scr->WMgrVertButtonIndent < 0) { 1284 Scr->WMgrVertButtonIndent = 0; 1285 } 1286 Scr->workSpaceMgr.vspace = Scr->WMgrVertButtonIndent; 1287 Scr->workSpaceMgr.occupyWindow->vspace = Scr->WMgrVertButtonIndent; 1288 return true; 1289 1290 case kwn_WMgrHorizButtonIndent: 1291 if(Scr->FirstTime) { 1292 Scr->WMgrHorizButtonIndent = num; 1293 } 1294 if(Scr->WMgrHorizButtonIndent < 0) { 1295 Scr->WMgrHorizButtonIndent = 0; 1296 } 1297 Scr->workSpaceMgr.hspace = Scr->WMgrHorizButtonIndent; 1298 Scr->workSpaceMgr.occupyWindow->hspace = Scr->WMgrHorizButtonIndent; 1299 return true; 1300 1301 case kwn_WMgrButtonShadowDepth: 1302 if(Scr->FirstTime) { 1303 Scr->WMgrButtonShadowDepth = num; 1304 } 1305 if(Scr->WMgrButtonShadowDepth < 1) { 1306 Scr->WMgrButtonShadowDepth = 1; 1307 } 1308 return true; 1309 1310 case kwn_MaxIconTitleWidth: 1311 if(Scr->FirstTime) { 1312 Scr->MaxIconTitleWidth = num; 1313 } 1314 return true; 1315 1316 case kwn_ClearShadowContrast: 1317 if(Scr->FirstTime) { 1318 Scr->ClearShadowContrast = num; 1319 } 1320 if(Scr->ClearShadowContrast < 0) { 1321 Scr->ClearShadowContrast = 0; 1322 } 1323 if(Scr->ClearShadowContrast > 100) { 1324 Scr->ClearShadowContrast = 100; 1325 } 1326 return true; 1327 1328 case kwn_DarkShadowContrast: 1329 if(Scr->FirstTime) { 1330 Scr->DarkShadowContrast = num; 1331 } 1332 if(Scr->DarkShadowContrast < 0) { 1333 Scr->DarkShadowContrast = 0; 1334 } 1335 if(Scr->DarkShadowContrast > 100) { 1336 Scr->DarkShadowContrast = 100; 1337 } 1338 return true; 1339 1340 case kwn_AnimationSpeed: 1341 if(num < 0) { 1342 num = 0; 1343 } 1344 SetAnimationSpeed(num); 1345 return true; 1346 1347 case kwn_BorderShadowDepth: 1348 if(Scr->FirstTime) { 1349 Scr->BorderShadowDepth = num; 1350 } 1351 if(Scr->BorderShadowDepth < 0) { 1352 Scr->BorderShadowDepth = 2; 1353 } 1354 return true; 1355 1356 case kwn_BorderLeft: 1357 if(Scr->FirstTime) { 1358 Scr->BorderLeft = num; 1359 } 1360 if(Scr->BorderLeft < 0) { 1361 Scr->BorderLeft = 0; 1362 } 1363 return true; 1364 1365 case kwn_BorderRight: 1366 if(Scr->FirstTime) { 1367 Scr->BorderRight = num; 1368 } 1369 if(Scr->BorderRight < 0) { 1370 Scr->BorderRight = 0; 1371 } 1372 return true; 1373 1374 case kwn_BorderTop: 1375 if(Scr->FirstTime) { 1376 Scr->BorderTop = num; 1377 } 1378 if(Scr->BorderTop < 0) { 1379 Scr->BorderTop = 0; 1380 } 1381 return true; 1382 1383 case kwn_BorderBottom: 1384 if(Scr->FirstTime) { 1385 Scr->BorderBottom = num; 1386 } 1387 if(Scr->BorderBottom < 0) { 1388 Scr->BorderBottom = 0; 1389 } 1390 return true; 1391 1392 case kwn_TitleButtonShadowDepth: 1393 if(Scr->FirstTime) { 1394 Scr->TitleButtonShadowDepth = num; 1395 } 1396 if(Scr->TitleButtonShadowDepth < 0) { 1397 Scr->TitleButtonShadowDepth = 2; 1398 } 1399 return true; 1400 1401 case kwn_TitleShadowDepth: 1402 if(Scr->FirstTime) { 1403 Scr->TitleShadowDepth = num; 1404 } 1405 if(Scr->TitleShadowDepth < 0) { 1406 Scr->TitleShadowDepth = 2; 1407 } 1408 return true; 1409 1410 case kwn_IconManagerShadowDepth: 1411 if(Scr->FirstTime) { 1412 Scr->IconManagerShadowDepth = num; 1413 } 1414 if(Scr->IconManagerShadowDepth < 0) { 1415 Scr->IconManagerShadowDepth = 2; 1416 } 1417 return true; 1418 1419 case kwn_MenuShadowDepth: 1420 if(Scr->FirstTime) { 1421 Scr->MenuShadowDepth = num; 1422 } 1423 if(Scr->MenuShadowDepth < 0) { 1424 Scr->MenuShadowDepth = 2; 1425 } 1426 return true; 1427 1428 case kwn_OpenWindowTimeout: 1429 if(Scr->FirstTime) { 1430 Scr->OpenWindowTimeout = num; 1431 } 1432 if(Scr->OpenWindowTimeout < 0) { 1433 Scr->OpenWindowTimeout = 0; 1434 } 1435 return true; 1436 1437 case kwn_RaiseOnClickButton: 1438 if(Scr->FirstTime) { 1439 Scr->RaiseOnClickButton = num; 1440 } 1441 if(Scr->RaiseOnClickButton < 1) { 1442 Scr->RaiseOnClickButton = 1; 1443 } 1444 if(Scr->RaiseOnClickButton > MAX_BUTTONS) { 1445 Scr->RaiseOnClickButton = MAX_BUTTONS; 1446 } 1447 return true; 1448 1449 1450 } 1451 1452 return false; 1453} 1454 1455name_list ** 1456do_colorlist_keyword(int keyword, int colormode, char *s) 1457{ 1458 switch(keyword) { 1459 case kwcl_BorderColor: 1460 GetColor(colormode, &Scr->BorderColorC.back, s); 1461 return &Scr->BorderColorL; 1462 1463 case kwcl_IconManagerHighlight: 1464 GetColor(colormode, &Scr->IconManagerHighlight, s); 1465 return &Scr->IconManagerHighlightL; 1466 1467 case kwcl_BorderTileForeground: 1468 GetColor(colormode, &Scr->BorderTileC.fore, s); 1469 return &Scr->BorderTileForegroundL; 1470 1471 case kwcl_BorderTileBackground: 1472 GetColor(colormode, &Scr->BorderTileC.back, s); 1473 return &Scr->BorderTileBackgroundL; 1474 1475 case kwcl_TitleForeground: 1476 GetColor(colormode, &Scr->TitleC.fore, s); 1477 return &Scr->TitleForegroundL; 1478 1479 case kwcl_TitleBackground: 1480 GetColor(colormode, &Scr->TitleC.back, s); 1481 return &Scr->TitleBackgroundL; 1482 1483 case kwcl_IconForeground: 1484 GetColor(colormode, &Scr->IconC.fore, s); 1485 return &Scr->IconForegroundL; 1486 1487 case kwcl_IconBackground: 1488 GetColor(colormode, &Scr->IconC.back, s); 1489 return &Scr->IconBackgroundL; 1490 1491 case kwcl_IconBorderColor: 1492 GetColor(colormode, &Scr->IconBorderColor, s); 1493 return &Scr->IconBorderColorL; 1494 1495 case kwcl_IconManagerForeground: 1496 GetColor(colormode, &Scr->IconManagerC.fore, s); 1497 return &Scr->IconManagerFL; 1498 1499 case kwcl_IconManagerBackground: 1500 GetColor(colormode, &Scr->IconManagerC.back, s); 1501 return &Scr->IconManagerBL; 1502 1503 case kwcl_MapWindowBackground: 1504 GetColor(colormode, &Scr->workSpaceMgr.windowcp.back, s); 1505 Scr->workSpaceMgr.windowcpgiven = true; 1506 return &Scr->workSpaceMgr.windowBackgroundL; 1507 1508 case kwcl_MapWindowForeground: 1509 GetColor(colormode, &Scr->workSpaceMgr.windowcp.fore, s); 1510 Scr->workSpaceMgr.windowcpgiven = true; 1511 return &Scr->workSpaceMgr.windowForegroundL; 1512 } 1513 return NULL; 1514} 1515 1516bool 1517do_color_keyword(int keyword, int colormode, char *s) 1518{ 1519 switch(keyword) { 1520 case kwc_DefaultForeground: 1521 GetColor(colormode, &Scr->DefaultC.fore, s); 1522 return true; 1523 1524 case kwc_DefaultBackground: 1525 GetColor(colormode, &Scr->DefaultC.back, s); 1526 return true; 1527 1528 case kwc_MenuForeground: 1529 GetColor(colormode, &Scr->MenuC.fore, s); 1530 return true; 1531 1532 case kwc_MenuBackground: 1533 GetColor(colormode, &Scr->MenuC.back, s); 1534 return true; 1535 1536 case kwc_MenuTitleForeground: 1537 GetColor(colormode, &Scr->MenuTitleC.fore, s); 1538 return true; 1539 1540 case kwc_MenuTitleBackground: 1541 GetColor(colormode, &Scr->MenuTitleC.back, s); 1542 return true; 1543 1544 case kwc_MenuShadowColor: 1545 GetColor(colormode, &Scr->MenuShadowColor, s); 1546 return true; 1547 1548 } 1549 1550 return false; 1551} 1552 1553/* 1554 * put_pixel_on_root() Save a pixel value in twm root window color property. 1555 */ 1556static void 1557put_pixel_on_root(Pixel pixel) 1558{ 1559 bool addone = true; 1560 Atom retAtom; 1561 int retFormat; 1562 unsigned long nPixels, retAfter; 1563 Pixel *retProp; 1564 1565 // Get current list 1566 if(XGetWindowProperty(dpy, Scr->Root, XA__MIT_PRIORITY_COLORS, 0, 8192, 1567 False, XA_CARDINAL, &retAtom, 1568 &retFormat, &nPixels, &retAfter, 1569 (unsigned char **)&retProp) != Success || !retProp) { 1570 return; 1571 } 1572 1573 // See if we already have this one 1574 for(int i = 0; i < nPixels; i++) { 1575 if(pixel == retProp[i]) { 1576 addone = false; 1577 } 1578 } 1579 XFree(retProp); 1580 1581 // If not, append it 1582 if(addone) { 1583 XChangeProperty(dpy, Scr->Root, XA__MIT_PRIORITY_COLORS, 1584 XA_CARDINAL, 32, PropModeAppend, 1585 (unsigned char *)&pixel, 1); 1586 } 1587} 1588 1589/* 1590 * Stash for SaveColor{} values during config parsing. 1591 */ 1592typedef struct _cnode { 1593 int i; 1594 int cmode; 1595 char *sname; 1596 struct _cnode *next; 1597} Cnode; 1598static Cnode *chead = NULL; 1599 1600/** 1601 * Add a SaveColor{} entry to our stash. 1602 */ 1603static void 1604add_cnode(int kwcl, int cmode, char *colname) 1605{ 1606 Cnode *cnew; 1607 1608 cnew = calloc(1, sizeof(Cnode)); 1609 cnew->i = kwcl; 1610 cnew->cmode = cmode; 1611 cnew->sname = colname; 1612 1613 if(!chead) { 1614 chead = cnew; 1615 } 1616 else { 1617 cnew->next = chead; 1618 chead = cnew; 1619 } 1620 1621 return; 1622} 1623 1624 1625/* 1626 * do_string_savecolor() save a color from a string in the twmrc file. 1627 */ 1628void 1629do_string_savecolor(int colormode, char *s) 1630{ 1631 add_cnode(0, colormode, s); 1632} 1633 1634/* 1635 * do_var_savecolor() save a color from a var in the twmrc file. 1636 */ 1637void 1638do_var_savecolor(int key) 1639{ 1640 add_cnode(key, 0, NULL); 1641} 1642 1643/* 1644 * assign_var_savecolor() traverse the var save color list placeing the pixels 1645 * in the root window property. 1646 */ 1647void 1648assign_var_savecolor(void) 1649{ 1650 Cnode *cp = chead; 1651 1652 // Start with an empty property 1653 XChangeProperty(dpy, Scr->Root, XA__MIT_PRIORITY_COLORS, 1654 XA_CARDINAL, 32, PropModeReplace, NULL, 0); 1655 1656 // Loop over, stash 'em, and clean up 1657 while(cp != NULL) { 1658 Cnode *tmp_cp = cp; 1659 1660 switch(cp->i) { 1661 case kwcl_BorderColor: 1662 put_pixel_on_root(Scr->BorderColorC.back); 1663 break; 1664 case kwcl_IconManagerHighlight: 1665 put_pixel_on_root(Scr->IconManagerHighlight); 1666 break; 1667 case kwcl_BorderTileForeground: 1668 put_pixel_on_root(Scr->BorderTileC.fore); 1669 break; 1670 case kwcl_BorderTileBackground: 1671 put_pixel_on_root(Scr->BorderTileC.back); 1672 break; 1673 case kwcl_TitleForeground: 1674 put_pixel_on_root(Scr->TitleC.fore); 1675 break; 1676 case kwcl_TitleBackground: 1677 put_pixel_on_root(Scr->TitleC.back); 1678 break; 1679 case kwcl_IconForeground: 1680 put_pixel_on_root(Scr->IconC.fore); 1681 break; 1682 case kwcl_IconBackground: 1683 put_pixel_on_root(Scr->IconC.back); 1684 break; 1685 case kwcl_IconBorderColor: 1686 put_pixel_on_root(Scr->IconBorderColor); 1687 break; 1688 case kwcl_IconManagerForeground: 1689 put_pixel_on_root(Scr->IconManagerC.fore); 1690 break; 1691 case kwcl_IconManagerBackground: 1692 put_pixel_on_root(Scr->IconManagerC.back); 1693 break; 1694 case kwcl_MapWindowForeground: 1695 put_pixel_on_root(Scr->workSpaceMgr.windowcp.fore); 1696 break; 1697 case kwcl_MapWindowBackground: 1698 put_pixel_on_root(Scr->workSpaceMgr.windowcp.back); 1699 break; 1700 case 0: { 1701 // This means it's a string, not one of our keywords 1702 Pixel p; 1703 GetColor(cp->cmode, &p, cp->sname); 1704 put_pixel_on_root(p); 1705 } 1706 } 1707 1708 cp = cp->next; 1709 free(tmp_cp); 1710 } 1711 if(chead) { 1712 chead = NULL; 1713 } 1714} 1715 1716 1717/* 1718 * RandomPlacement [...] parse 1719 */ 1720static int 1721ParseRandomPlacement(const char *s) 1722{ 1723 /* No first arg -> 'all' */ 1724 if(s == NULL) { 1725 return RP_ALL; 1726 } 1727 if(strlen(s) == 0) { 1728 return RP_ALL; 1729 } 1730 1731#define CHK(str, ret) if(strcasecmp(s, str) == 0) { return RP_##ret; } 1732 CHK(DEFSTRING, ALL); 1733 CHK("on", ALL); 1734 CHK("all", ALL); 1735 CHK("off", OFF); 1736 CHK("unmapped", UNMAPPED); 1737#undef CHK 1738 1739 return -1; 1740} 1741 1742 1743/* 1744 * Parse out IconRegionJustification string. 1745 * 1746 * X-ref comment on ParseAlignement about return value. 1747 */ 1748int 1749ParseIRJustification(const char *s) 1750{ 1751 if(strlen(s) == 0) { 1752 return -1; 1753 } 1754 1755#define CHK(str, ret) if(strcasecmp(s, str) == 0) { return IRJ_##ret; } 1756 CHK(DEFSTRING, CENTER); 1757 CHK("undef", UNDEF); 1758 CHK("left", LEFT); 1759 CHK("center", CENTER); 1760 CHK("right", RIGHT); 1761 CHK("border", BORDER); 1762#undef CHK 1763 1764 return -1; 1765} 1766 1767 1768/* 1769 * Parse out string for title justification. From TitleJustification, 1770 * IconJustification, iconjust arg to IconRegion. 1771 * 1772 * X-ref comment on ParseAlignement about return value. 1773 */ 1774int 1775ParseTitleJustification(const char *s) 1776{ 1777 if(strlen(s) == 0) { 1778 return -1; 1779 } 1780 1781#define CHK(str, ret) if(strcasecmp(s, str) == 0) { return TJ_##ret; } 1782 /* XXX Different uses really have different defaults... */ 1783 CHK(DEFSTRING, CENTER); 1784 CHK("undef", UNDEF); 1785 CHK("left", LEFT); 1786 CHK("center", CENTER); 1787 CHK("right", RIGHT); 1788#undef CHK 1789 1790 return -1; 1791} 1792 1793 1794/* 1795 * Parse out the string specifier for IconRegion Alignement[sic]. 1796 * Strictly speaking, this [almost always] returns an IRAlignement enum 1797 * value. However, it's specified as int to allow the -1 return for 1798 * invalid values. enum's start numbering from 0 (unless specific values 1799 * are given), so that's a safe out-of-bounds value. And making an 1800 * IRA_INVALID value would just add unnecessary complication, since 1801 * during parsing is the only time it makes sense. 1802 */ 1803int 1804ParseAlignement(const char *s) 1805{ 1806 if(strlen(s) == 0) { 1807 return -1; 1808 } 1809 1810#define CHK(str, ret) if(strcasecmp(s, str) == 0) { return IRA_##ret; } 1811 CHK(DEFSTRING, CENTER); 1812 CHK("center", CENTER); 1813 CHK("top", TOP); 1814 CHK("bottom", BOTTOM); 1815 CHK("border", BORDER); 1816 CHK("undef", UNDEF); 1817#undef CHK 1818 1819 return -1; 1820} 1821 1822static int 1823ParseUsePPosition(const char *s) 1824{ 1825 if(strlen(s) == 0) { 1826 return -1; 1827 } 1828 1829#define CHK(str, ret) if(strcasecmp(s, str) == 0) { return PPOS_##ret; } 1830 CHK(DEFSTRING, OFF); 1831 CHK("off", OFF); 1832 CHK("on", ON); 1833 CHK("non-zero", NON_ZERO); 1834 CHK("nonzero", NON_ZERO); 1835#undef CHK 1836 1837 return -1; 1838} 1839 1840static int 1841ParseButtonStyle(const char *s) 1842{ 1843 if(s == NULL || strlen(s) == 0) { 1844 return -1; 1845 } 1846 1847#define CHK(str, ret) if(strcasecmp(s, str) == 0) { return STYLE_##ret; } 1848 CHK(DEFSTRING, NORMAL); 1849 CHK("normal", NORMAL); 1850 CHK("style1", STYLE1); 1851 CHK("style2", STYLE2); 1852 CHK("style3", STYLE3); 1853#undef CHK 1854 1855 return -1; 1856} 1857 1858static int 1859ParseIconifyStyle(const char *s) 1860{ 1861 if(s == NULL || strlen(s) == 0) { 1862 return -1; 1863 } 1864 1865#define CHK(str, ret) if(strcasecmp(s, str) == 0) { return ICONIFY_##ret; } 1866 CHK(DEFSTRING, NORMAL); 1867 CHK("normal", NORMAL); 1868 CHK("mosaic", MOSAIC); 1869 CHK("zoomin", ZOOMIN); 1870 CHK("zoomout", ZOOMOUT); 1871 CHK("fade", FADE); 1872 CHK("sweep", SWEEP); 1873#undef CHK 1874 1875 return -1; 1876} 1877 1878void 1879do_squeeze_entry(name_list **slist, // squeeze or dont-squeeze list 1880 const char *name, // window name 1881 SIJust justify, // left, center, right 1882 int num, // signed num 1883 int denom) // 0 or indicates fraction denom 1884{ 1885 int absnum = (num < 0 ? -num : num); 1886 1887 if(denom < 0) { 1888 twmrc_error_prefix(); 1889 fprintf(stderr, "negative SqueezeTitle denominator %d\n", denom); 1890 ParseError = true; 1891 return; 1892 } 1893 if(absnum > denom && denom != 0) { 1894 twmrc_error_prefix(); 1895 fprintf(stderr, "SqueezeTitle fraction %d/%d outside window\n", 1896 num, denom); 1897 ParseError = true; 1898 return; 1899 } 1900 /* Process the special cases from the manual here rather than 1901 * each time we calculate the position of the title bar 1902 * in ComputeTitleLocation(). 1903 * In fact, it's better to get rid of them entirely, but we 1904 * probably should not do that for compatibility's sake. 1905 * By using a non-zero denominator the position will be relative. 1906 */ 1907 if(denom == 0 && num == 0) { 1908 if(justify == SIJ_CENTER) { 1909 num = 1; 1910 denom = 2; 1911 } 1912 else if(justify == SIJ_RIGHT) { 1913 num = 2; 1914 denom = 2; 1915 } 1916 twmrc_error_prefix(); 1917 fprintf(stderr, "deprecated SqueezeTitle faction 0/0, assuming %d/%d\n", 1918 num, denom); 1919 } 1920 1921 if(HasShape) { 1922 SqueezeInfo *sinfo; 1923 sinfo = malloc(sizeof(SqueezeInfo)); 1924 1925 if(!sinfo) { 1926 twmrc_error_prefix(); 1927 fprintf(stderr, "unable to allocate %lu bytes for squeeze info\n", 1928 (unsigned long) sizeof(SqueezeInfo)); 1929 ParseError = true; 1930 return; 1931 } 1932 sinfo->justify = justify; 1933 sinfo->num = num; 1934 sinfo->denom = denom; 1935 AddToList(slist, name, sinfo); 1936 } 1937 return; 1938} 1939 1940 1941/* 1942 * Parsing for EWMHIgnore { } lists 1943 */ 1944void 1945proc_ewmh_ignore(void) 1946{ 1947#ifndef EWMH 1948 twmrc_error_prefix(); 1949 fprintf(stderr, "EWMH not enabled, EWMHIgnore { } ignored.\n"); 1950 ParseError = true; 1951 return; 1952#endif 1953 /* else nada */ 1954 return; 1955} 1956void 1957add_ewmh_ignore(char *s) 1958{ 1959#ifndef EWMH 1960 return; 1961#else 1962 1963#define HANDLE(x) \ 1964 if(strcasecmp(s, (x)) == 0) { \ 1965 AddToList(&Scr->EWMHIgnore, (x), ""); \ 1966 return; \ 1967 } 1968 HANDLE("STATE_MAXIMIZED_VERT"); 1969 HANDLE("STATE_MAXIMIZED_HORZ"); 1970 HANDLE("STATE_FULLSCREEN"); 1971 HANDLE("STATE_SHADED"); 1972 HANDLE("STATE_ABOVE"); 1973 HANDLE("STATE_BELOW"); 1974#undef HANDLE 1975 1976 twmrc_error_prefix(); 1977 fprintf(stderr, "Unexpected EWMHIgnore value '%s'\n", s); 1978 ParseError = true; 1979 return; 1980#endif /* EWMH */ 1981} 1982 1983 1984/* 1985 * Parsing for MWMIgnore { } lists 1986 */ 1987void 1988proc_mwm_ignore(void) 1989{ 1990 /* Nothing to do */ 1991 return; 1992} 1993void 1994add_mwm_ignore(char *s) 1995{ 1996#define HANDLE(x) \ 1997 if(strcasecmp(s, (x)) == 0) { \ 1998 AddToList(&Scr->MWMIgnore, (x), ""); \ 1999 return; \ 2000 } 2001 HANDLE("DECOR_BORDER"); 2002 HANDLE("DECOR_TITLE"); 2003#undef HANDLE 2004 2005 twmrc_error_prefix(); 2006 fprintf(stderr, "Unexpected MWMIgnore value '%s'\n", s); 2007 ParseError = true; 2008 return; 2009} 2010 2011 2012/* 2013 * Parsing for Layout { } lists, to override the monitor layout we 2014 * assumed or got from RANDR. 2015 */ 2016static RAreaList *override_monitors; 2017static struct { 2018 char **names; 2019 int len; 2020 int cap; 2021} override_monitors_names; 2022 2023 2024/** 2025 * Allocate space for our monitor override list. 2026 */ 2027void 2028init_layout_override(void) 2029{ 2030 // 4 seems like a good guess. If we're doing this, we're probably 2031 // making at least 2 monitors, and >4 is gonna be pretty rare, so... 2032 const int initsz = 4; 2033 2034 override_monitors = RAreaListNew(initsz, NULL); 2035 if(override_monitors == NULL) { 2036 twmrc_error_prefix(); 2037 fprintf(stderr, "Failed allocating RAreaList for monitors.\n"); 2038 ParseError = true; 2039 return; 2040 // Maybe we should just abort(); if malloc failed allocating a 2041 // few dozen bytes this early, we're _screwed_. 2042 } 2043 2044 override_monitors_names.names = calloc(initsz, sizeof(char *)); 2045 override_monitors_names.len = 0; 2046 override_monitors_names.cap = initsz; 2047 2048 return; 2049} 2050 2051/** 2052 * Add an entry to our monitor list 2053 * 2054 * Expecting: [Name:]WxH[+X[+Y]] 2055 */ 2056void 2057add_layout_override_entry(const char *s) 2058{ 2059 const char *tmp; 2060 int xpgret; 2061 int x, y; 2062 unsigned int width, height; 2063 2064 if(override_monitors == NULL) { 2065 // alloc failed, so just give up; we'll fail in the end anyway... 2066 return; 2067 } 2068 2069 // Got a name? 2070 tmp = strchr(s, ':'); 2071 if(tmp != NULL && tmp != s) { 2072 // Stash the name 2073 override_monitors_names.names[override_monitors_names.len] 2074 = strndup(s, tmp - s); 2075 // len advances below 2076 2077 // Advance to geom 2078 s = tmp + 1; 2079 } 2080 // Advance whether we got a name or not, to keep in sync. 2081 override_monitors_names.len++; 2082 2083 2084 // Either way, s points at the geom now 2085 xpgret = XParseGeometry(s, &x, &y, &width, &height); 2086 2087 // Width and height are non-optional. If x/y aren't given, we assume 2088 // +0+0. If we're given -0's, well, we don't _support_ that, but 2089 // XPG() turns them into positives for us, so just accept it... 2090 const int has_hw = (WidthValue | HeightValue); 2091 if((xpgret & has_hw) != has_hw) { 2092 twmrc_error_prefix(); 2093 fprintf(stderr, "Need both height and width in '%s'\n", s); 2094 ParseError = true; 2095 // Don't bother free()'ing stuff, we're going to exit after 2096 // parse completes 2097 return; 2098 } 2099 if(!(xpgret & XValue)) { 2100 x = 0; 2101 } 2102 if(!(xpgret & YValue)) { 2103 y = 0; 2104 } 2105 2106 2107 // And stash it 2108 RAreaListAdd(override_monitors, RAreaNewStatic(x, y, width, height)); 2109 2110 // Whether we had a name for this 'monitor' or not, we need to 2111 // possibly grow the names list, since it has to stay in lockstep 2112 // with the areas as we add 'em. 2113 { 2114 char ***names = &override_monitors_names.names; 2115 int len = override_monitors_names.len; 2116 2117 if(len == override_monitors_names.cap) { 2118 char **tnames = realloc(*names, (len + 1) * sizeof(char *)); 2119 if(tnames == NULL) { 2120 abort(); 2121 } 2122 *names = tnames; 2123 override_monitors_names.cap++; 2124 } 2125 } 2126 2127 return; 2128} 2129 2130/** 2131 * Finalize the override layout and store it up globally. 2132 */ 2133void 2134proc_layout_override(void) 2135{ 2136 RLayout *new_layout; 2137 2138 // Guard 2139 if(RAreaListLen(override_monitors) < 1) { 2140 // Make this non-fatal, so an empty spec not-quite-quietly does 2141 // nothing. 2142 twmrc_error_prefix(); 2143 fprintf(stderr, "no monitors specified, ignoring MonitorLayout\n"); 2144 2145 // Since it's non-fatal, we _do_ need to cleanup more 2146 // carefully... 2147 RAreaListFree(override_monitors); 2148 for(int i = 0; i < override_monitors_names.len ; i++) { 2149 free(override_monitors_names.names[i]); 2150 } 2151 free(override_monitors_names.names); 2152 return; 2153 } 2154 2155 new_layout = RLayoutNew(override_monitors); 2156 RLayoutSetMonitorsNames(new_layout, override_monitors_names.names); 2157 // Silently stop paying attention to o_m_n. Don't free() anything, 2158 // since new_layout now owns it. If we get another MonitorLayout{} 2159 // block, it'll start over again with init(), and allocate new space. 2160 2161#ifdef DEBUG 2162 fprintf(stderr, "Overridden layout: "); 2163 RLayoutPrint(new_layout); 2164#endif 2165 2166 RLayoutFree(Scr->Layout); 2167 Scr->Layout = new_layout; 2168 return; 2169} 2170